Improves behavior under Valgrind. Before: ``` ==221683== Memcheck, a memory error detector ==221683== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==221683== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info ==221683== Command: /games/wine/wine cmd /c dir ==221683== ==221683== Memcheck, a memory error detector ==221683== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==221683== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info ==221683== Command: /games/wine/loader/wine-preloader /games/wine/loader/wine cmd /c dir ==221683== ==221683== Jump to the invalid address stated on the next line ==221683== at 0x109108: wld_mmap (in /games/wine/loader/wine-preloader) ==221683== by 0x109E43: wld_start (preloader.c:1445) ==221683== by 0x10902D: (below main) (in /games/wine/loader/wine-preloader) ==221683== Address 0x109108 is in the Text segment of /games/wine/loader/wine-preloader ==221683== at 0x109108: wld_mmap (in /games/wine/loader/wine-preloader) ==221683== ==221683== ==221683== Process terminating with default action of signal 11 (SIGSEGV) ==221683== Bad permissions for mapped region at address 0x109108 ==221683== at 0x109108: wld_mmap (in /games/wine/loader/wine-preloader) ==221683== by 0x109E43: wld_start (preloader.c:1445) ==221683== by 0x10902D: (below main) (in /games/wine/loader/wine-preloader) ==221683== ==221683== HEAP SUMMARY: ==221683== in use at exit: 0 bytes in 0 blocks ==221683== total heap usage: 0 allocs, 0 frees, 0 bytes allocated ==221683== ==221683== All heap blocks were freed -- no leaks are possible ==221683== ==221683== For lists of detected and suppressed errors, rerun with: -s ==221683== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) ``` After: ``` ==221585== Memcheck, a memory error detector ==221585== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==221585== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info ==221585== Command: /games/wine/wine cmd /c dir ==221585== ==221585== Memcheck, a memory error detector ==221585== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al. ==221585== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info ==221585== Command: /games/wine/loader/wine-preloader /games/wine/loader/wine cmd /c dir ==221585== preloader: Warning: we got loaded into reserved range 0000000000010000-0000000000110000, ignoring reservation preloader: Warning: failed to reserve range 0000000000110000-0000000068000000 ==221585== ==221585== LOAD_PDB_DEBUGINFO: clreq: fd=7, avma=0x140000000, total_size=172032, bias=0x0 ==221585== LOAD_PDB_DEBUGINFO: objname: /games/wine/programs/start/x86_64-windows/start.exe ==221585== LOAD_PDB_DEBUGINFO: Find PDB file: /tmp/valgrind_petmp221585_237cbd3c is empty ==221585== Warning: Missing or un-stat-able /games/wine/programs/start/x86_64-windows/start.pdb ==221585== LOAD_PDB_DEBUGINFO: missing: /games/wine/programs/start/x86_64-windows/start.pdb ==221585== ==221585== LOAD_PDB_DEBUGINFO: clreq: fd=7, avma=0x6fffffc00000, total_size=4083712, bias=0x6ffe8fc00000 ==221585== LOAD_PDB_DEBUGINFO: objname: /games/wine/dlls/ntdll/x86_64-windows/ntdll.dll ==221585== LOAD_PDB_DEBUGINFO: Find PDB file: /tmp/valgrind_petmp221585_237cbd3c is empty ==221585== Warning: Missing or un-stat-able /games/wine/dlls/ntdll/x86_64-windows/ntdll.pdb ==221585== LOAD_PDB_DEBUGINFO: missing: /games/wine/dlls/ntdll/x86_64-windows/ntdll.pdb 0138:err:seh:segv_handler Got unexpected trap 0 vex amd64->IR: unhandled instruction bytes: 0x8E 0xD8 0x8E 0xC0 0x5B 0x5D 0x41 0x5C 0x41 0x5D vex amd64->IR: REX=0 REX.W=0 REX.R=0 REX.X=0 REX.B=0 vex amd64->IR: VEX=0 VEX.L=0 VEX.nVVVV=0x0 ESC=NONE vex amd64->IR: PFX.66=0 PFX.F2=0 PFX.F3=0 ==221585== valgrind: Unrecognised instruction at address 0x4e99e07. ==221585== at 0x4E99E07: leave_handler (signal_x86_64.c:876) ==221585== by 0x4E99E07: setup_raise_exception (signal_x86_64.c:1520) ==221585== by 0x4E99FD6: segv_handler (signal_x86_64.c:2101) ==221585== by 0x48B304F: ??? (in /usr/lib/x86_64-linux-gnu/libc.so.6) ==221585== by 0x6FFFFFC0FAAB: ??? (in /games/wine/dlls/ntdll/x86_64-windows/ntdll.dll) ==221585== Your program just tried to execute an instruction that Valgrind ==221585== did not recognise. There are two possible reasons for this. ==221585== 1. Your program has a bug and erroneously jumped to a non-code ==221585== location. If you are running Memcheck and you just saw a ==221585== warning about a bad jump, it's probably your program's fault. ==221585== 2. The instruction is legitimate but Valgrind doesn't handle it, ==221585== i.e. it's Valgrind's fault. If you think this is the case or ==221585== you are not sure, please let us know and we'll try to fix it. ==221585== Either way, Valgrind will now raise a SIGILL signal which will ==221585== probably kill your program. 0138:err:seh:segv_handler Got unexpected trap 0 0138:err:virtual:virtual_setup_exception nested exception on signal stack addr 0x4e99e07 stack 0x7ffceb30 ==221585== ==221585== HEAP SUMMARY: ==221585== in use at exit: 11,149 bytes in 30 blocks ==221585== total heap usage: 161 allocs, 131 frees, 856,134 bytes allocated ==221585== ==221585== LEAK SUMMARY: ==221585== definitely lost: 25 bytes in 1 blocks ==221585== indirectly lost: 0 bytes in 0 blocks ==221585== possibly lost: 5,582 bytes in 1 blocks ==221585== still reachable: 5,542 bytes in 28 blocks ==221585== suppressed: 0 bytes in 0 blocks ==221585== Rerun with --leak-check=full to see details of leaked memory ==221585== ==221585== For lists of detected and suppressed errors, rerun with: -s ==221585== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) ``` ...honestly not much of an improvement, but at least it gets a little further. And it makes abundantly clear the current blocker is not on Wine's side. (Valgrind having Opinions on the address space is [a well](https://bugs.kde.org/show_bug.cgi?id=374963) known [issue](https://bugs.winehq.org/show_bug.cgi?id=47125).)
From: Alfred Agrell floating@muncher.se
--- loader/preloader.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/loader/preloader.c b/loader/preloader.c index d0551bae63a..274849e9f4f 100644 --- a/loader/preloader.c +++ b/loader/preloader.c @@ -1442,6 +1442,14 @@ void* wld_start( void **stack ) remove_preload_range( i ); i--; } + else if ((char*)wld_start >= (char *)preload_info[i].addr && + (char *)wld_start <= (char *)preload_info[i].addr + preload_info[i].size) + { + wld_printf( "preloader: Warning: we got loaded into reserved range %p-%p, ignoring reservation\n", + preload_info[i].addr, (char *)preload_info[i].addr + preload_info[i].size ); + remove_preload_range( i ); + i--; + } else if (wld_mmap( preload_info[i].addr, preload_info[i].size, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0 ) == (void *)-1) {
Instead of removing the reserved range, we should split the range around the mapped area. See https://gitlab.winehq.org/wine/wine/-/merge_requests/6/diffs?commit_id=02247... for how this could be done.
Instead of removing the reserved range, we should split the range around the mapped area.
So if the memory looks like this:
``` [-- reserved range --] [preloader] ```
Then, instead of giving up the reserved range, we could simply split the reservation, like this:
``` [-- reserved range --] [-- rsvd 1 --][preloader][-- rsvd 2 --] ```
Note that the preloader *itself* now acts as part of the reservation, as its address won't be reused by mmap(2)—just like other reservations.
See https://gitlab.winehq.org/wine/wine/-/merge_requests/6/diffs?commit_id=02247... for how this could be done.
Alternatively, if you're looking for "just works" instead of a proper fix, have you tried WINELOADERNOEXEC=1?
On Sat Jun 21 17:26:05 2025 +0000, Jinoh Kang wrote:
Instead of removing the reserved range, we should split the range around the mapped area. So if the memory looks like this:
[-- reserved range --] [preloader]
Then, instead of giving up the reserved range, we could simply split the reservation, like this:
[-- reserved range --] [-- rsvd 1 --][preloader][-- rsvd 2 --]
Note that the preloader *itself* now acts as part of the reservation, as its address won't be reused by mmap(2)—just like other reservations. See https://gitlab.winehq.org/wine/wine/-/merge_requests/6/diffs?commit_id=02247... for how this could be done.
That ... is an improvement over just omitting the range, but I'm not sure if that amount of code is worth it. Maybe it's better to just document the workaround on the wiki.
(According to someone on IRC, latest Valgrind can run Wine's instructions properly, it's just that Debian's Valgrind is three years old.)
This merge request was closed by Alexandre Julliard.
Yes, just use `WINELOADERNOEXEC=1`. It doesn't make sense to use the preloader if it won't be able to reserve the ranges.