https://bugs.winehq.org/show_bug.cgi?id=56371
--- Comment #6 from Andrew Nguyen arethusa26@gmail.com --- Created attachment 76488 --> https://bugs.winehq.org/attachment.cgi?id=76488 C source for VirtualAlloc test program
I believe I've identified why the WinUAE MMAN allocation on Windows has a low base address.
Running winedump on winuae64.exe shows the following flags set for the PE file header characteristics field:
Characteristics: 0023 RELOCS_STRIPPED EXECUTABLE_IMAGE LARGE_ADDRESS_AWARE
It also sets the following flags for the DLL characteristics field in the PE optional header:
DLL characteristics: 0x8120 HIGH_ENTROPY_VA NX_COMPAT TERMINAL_SERVER_AWARE
MSDN documents the IMAGE_FILE_RELOCS_STRIPPED flag as indicating that "the file does not contain base relocations and must therefore be loaded at its preferred base address." However, this flag being set along with IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA, which allows for 64-bit ASLR, seems contradictory.
Attached is a test program that calls VirtualAlloc with a large size and no preferred address for a MEM_RESERVE request, in the same fashion as WinUAE, and reports the returned address. I compiled the program twice with x86_64-w64-mingw32-gcc, with one built with no special flags and another with -Wl,--disable-reloc-section.
I observed the following results on Windows 10:
C:\Users\Public>large_virtualalloc.exe VirtualAlloc returned 0000028b56e10000
C:\Users\Public>large_virtualalloc_reloc_stripped.exe VirtualAlloc returned 000000007fff0000
The mingw ld refuses to allow the IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA or IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flags to be set without enabling relocations, so I copied the reloc-stripped executable and modified the copy directly to set a combination of the two flags. I observed the following results:
C:\Users\Public>large_virtualalloc_reloc_stripped_dynbase.exe VirtualAlloc returned 000000007fff0000
C:\Users\Public>large_virtualalloc_reloc_stripped_high_va.exe VirtualAlloc returned 000000007fff0000
C:\Users\Public>large_virtualalloc_reloc_stripped_dynbase_high_va.exe VirtualAlloc returned 000000007fff0000
For completeness, I also built an executable with relocations available but ASLR completely disabled (no HIGH_ENTROPY_VA or DYNAMIC_BASE flags) and tested it:
C:\Users\Public>large_virtualalloc_reloc_no_aslr.exe VirtualAlloc returned 000000007fff0000
All these test cases on wine-9.9 show VirtualAlloc returning a high address outside a 32-bit address space. I deduce that, on Windows, disabling ASLR for an executable results in VirtualAlloc preferring lower addresses first if no preferred address is explicitly requested.