https://bugs.winehq.org/show_bug.cgi?id=48417
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|Wine 32-bit builtins in PE |All Wine 32-bit PE builtin |format occupy low address |dlls created by llvm-mingw |space range, preventing |use the same fixed |non-relocatable native |imagebase, preventing |executables from being |non-relocatable native |loaded |executables from being | |loaded (dynamicbase/ASLR | |should be default)
--- Comment #4 from Anastasius Focht focht@gmx.net --- Hello Alexandre,
--- quote --- Note that this is specific to llvm-mingw, standard mingw uses --enable-auto-image-base by default. llvm-mingw should probably do the same. --- quote ---
the distro MinGW-w64 (gcc) indeed has 'enable-auto-image-base' by default:
--- snip --- $ i686-w64-mingw32-gcc -v Using built-in specs. COLLECT_GCC=/usr/bin/i686-w64-mingw32-gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/i686-w64-mingw32/7.3.0/lto-wrapper Target: i686-w64-mingw32 Configured with: ../configure --prefix=/usr --bindir=/usr/bin --includedir=/usr/include --mandir=/usr/share/man --infodir=/usr/share/info --datadir=/usr/share --build=x86_64-redhat-linux-gnu --host=x86_64-redhat-linux-gnu --with-gnu-as --with-gnu-ld --verbose --without-newlib --disable-multilib --disable-plugin --with-system-zlib --disable-nls --without-included-gettext --disable-win32-registry --enable-languages=c,c++,objc,obj-c++,fortran --with-bugurl=http://bugzilla.redhat.com/bugzilla --with-cloog --enable-threads=posix --enable-libgomp --target=i686-w64-mingw32 --with-sysroot=/usr/i686-w64-mingw32/sys-root --with-gxx-include-dir=/usr/i686-w64-mingw32/sys-root/mingw/include/c++ Thread model: posix gcc version 7.3.0 20180125 (Fedora MinGW 7.3.0-1.fc28) (GCC)
$ i686-w64-mingw32-gcc -dumpspecs | grep enable-auto-image-base %{m64:-m i386pep} %{!m64:-m i386pe} %{mwindows:--subsystem windows} %{mconsole:--subsystem console} %{shared: %{mdll: %eshared and mdll are not compatible}} %{shared: --shared} %{mdll:--dll} %{static:-Bstatic} %{!static:-Bdynamic} %{shared|mdll: %{m64:-e DllMainCRTStartup} %{!m64:-e _DllMainCRTStartup@12} --enable-auto-image-base} %(shared_libgcc_undefs) --- snip ---
The problem: LLVM's LLD doesn't seem to support this ;-(
https://github.com/llvm/llvm-project/blob/master/lld/MinGW/Options.td#L92
--- snip --- // Ignored options def: Joined<["-"], "O">; def: F<"build-id">; def: F<"disable-auto-image-base">; def: F<"enable-auto-image-base">; def: F<"enable-auto-import">, HelpText<"Ignored; listed for libtool compatibility">; def: F<"end-group">; def: Flag<["--"], "full-shutdown">; def: F<"high-entropy-va">; def: S<"major-image-version">; def: S<"minor-image-version">; def: F<"no-seh">; def: F<"nxcompat">; def: F<"pic-executable">; ... --- snip ---
The closest functionality I could find is LLD option '--dynamicbase' which is used for ASLR.
https://github.com/llvm/llvm-project/blob/b11386f9be9b2dc7276a758d64f66833da...
--- snip --- if (config->dynamicBase) pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE; --- snip ---
I've injected '-Wl,--dynamicbase' into 'CROSSLDFLAGS'.
--- snip --- $ winedump $(winepath -u "c:\windows\syswow64\kernelbase.dll") Contents of /home/focht/.wine/dosdevices/c:/windows/syswow64/kernelbase.dll: 1802240 bytes
*** This is a Wine builtin DLL ***
File Header Machine: 014C (i386) Number of Sections: 13 TimeDateStamp: 5E11DCBC (Sun Jan 5 13:55:24 2020) offset 128 PointerToSymbolTable: 001B7E00 NumberOfSymbols: 00000000 SizeOfOptionalHeader: 00E0 Characteristics: 2102 EXECUTABLE_IMAGE 32BIT_MACHINE DLL
Optional Header (32bit) Magic 0x10B 267 linker version 14.00 size of code 0x46800 288768 size of initialized data 0x171200 1511936 size of uninitialized data 0x0 0 entrypoint RVA 0x20850 133200 base of code 0x1000 4096 base of data 0x0 0 image base 0x10000000 268435456 section align 0x1000 4096 file align 0x200 512 required OS version 6.00 image version 0.00 subsystem version 6.00 Win32 Version 0x0 0 size of image 0x1c1000 1839104 size of headers 0x400 1024 checksum 0x0 0 Subsystem 0x2 (Windows GUI) DLL characteristics: 0x140 DYNAMIC_BASE NX_COMPAT stack reserve size 0x100000 1048576 stack commit size 0x1000 4096 heap reserve size 0x100000 1048576 heap commit size 0x1000 4096 loader flags 0x0 0 RVAs & sizes 0x10 16
Data Directory EXPORT rva: 0x72468 size: 0xa8e3 IMPORT rva: 0x7cd4b size: 0x28 RESOURCE rva: 0x0 size: 0x0 EXCEPTION rva: 0x0 size: 0x0 SECURITY rva: 0x0 size: 0x0 BASERELOC rva: 0x85000 size: 0x4158 DEBUG rva: 0x80000 size: 0x1c ARCHITECTURE rva: 0x0 size: 0x0 GLOBALPTR rva: 0x0 size: 0x0 TLS rva: 0x0 size: 0x0 LOAD_CONFIG rva: 0x0 size: 0x0 Bound IAT rva: 0x0 size: 0x0 IAT rva: 0x7d324 size: 0x5b0 Delay IAT rva: 0x0 size: 0x0 CLR Header rva: 0x0 size: 0x0 rva: 0x0 size: 0x0
Done dumping /home/focht/.wine/dosdevices/c:/windows/syswow64/kernelbase.dll --- snip ---
'DLL characteristics' -> 'DYNAMIC_BASE'
Dlls will still have the default image base set though:
https://github.com/llvm/llvm-project/blob/d3fec7fb456138c83b84e38ce785ea6bfa...
--- snip --- static uint64_t getDefaultImageBase() { if (config->is64()) return config->dll ? 0x180000000 : 0x140000000; return config->dll ? 0x10000000 : 0x400000; } --- snip ---
https://github.com/llvm/llvm-project/blob/d3fec7fb456138c83b84e38ce785ea6bfa...
--- snip --- // Set default image base if /base is not given. if (config->imageBase == uint64_t(-1)) config->imageBase = getDefaultImageBase(); --- snip ---
The problem: ASLR isn't supported in Wine loader yet.
--- snip --- $ grep -Hrn DYNAMIC_BASE
dlls/kernel32/tests/loader.c:462: if (!(nt_header->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)) dlls/kernel32/tests/loader.c:1123: nt_header.OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; dlls/kernel32/tests/loader.c:1297: nt64.OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; dlls/kernel32/tests/loader.c:1408: nt32.OptionalHeader.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
dlls/fusion/tests/asmcache.c:328: IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE |
tools/winedump/pe.c:218: X(IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE, "DYNAMIC_BASE");
server/mapping.c:651: if ((nt.opt.hdr32.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) && server/mapping.c:691: if ((nt.opt.hdr64.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) &&
include/winnt.h:2986:#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 --- snip ---
--- snip --- $ grep -Hrni DynamicallyRelocated
dlls/kernel32/tests/loader.c:387: (S(U(image)).ImageDynamicallyRelocated && LOWORD(image.TransferAddress) == LOWORD(entry_point)), dlls/kernel32/tests/loader.c:463: ok( !S(U(image)).ImageDynamicallyRelocated || broken( S(U(image)).ComPlusILOnly ), /* <= win7 */ dlls/kernel32/tests/loader.c:464: "%u: wrong ImageDynamicallyRelocated flags %02x\n", id, U(image).ImageFlags ); dlls/kernel32/tests/loader.c:466: ok( S(U(image)).ImageDynamicallyRelocated || broken(is_winxp), dlls/kernel32/tests/loader.c:467: "%u: wrong ImageDynamicallyRelocated flags %02x\n", id, U(image).ImageFlags ); dlls/kernel32/tests/loader.c:469: ok( !S(U(image)).ImageDynamicallyRelocated || broken(TRUE), /* <= win8 */ dlls/kernel32/tests/loader.c:470: "%u: wrong ImageDynamicallyRelocated flags %02x\n", id, U(image).ImageFlags );
server/protocol.def:767:#define IMAGE_FLAGS_ImageDynamicallyRelocated 0x04
server/mapping.c:653: mapping->image.image_flags |= IMAGE_FLAGS_ImageDynamicallyRelocated; server/mapping.c:693: mapping->image.image_flags |= IMAGE_FLAGS_ImageDynamicallyRelocated;
include/winternl.h:2028: UCHAR ImageDynamicallyRelocated : 1;
include/wine/server_protocol.h:751:#define IMAGE_FLAGS_ImageDynamicallyRelocated 0x04 --- snip ---
I'm not sure if upstream LLVM project is keen to implement 'enable-auto-image-base' since there is already 'dynamicbase'. Actually 'auto-image-base' would be contradictory when 'dynamicbase' is provided. Why would the linker need to generate a random image load address when the OS loader does a better job at runtime (has the knowledge of the address space layout).
I think supporting ASLR in Wine loader is more preferable as it would bring the PE binaries created with mingw cross-toolchain in line with what's produced by Microsoft's toolchains by default -> https://web.archive.org/web/20200105131452/https://devblogs.microsoft.com/cp...
If upstream doesn't want 'auto-image-base' for above stated reasons, we could make this bug report about defaulting to 'dynamicbase' in llvm-mingw (still upstream?) and create another bug about supporting ASLR in Wine loader.
Regards