From: Nat Brown <natbro@gmail.com> qemu-user synthesizes signal frames without filling in the trap number, leaving TRAP_sig() as -1. segv_handler() then falls through to the default case, logs "Got unexpected trap -1" and never services the fault, so page faults during 32-bit module loading surface as unhandled exceptions. Infer the trap from the delivered signal instead. Note that ERROR_sig() is unset for the same reason, so faults routed to TRAP_x86_PAGEFLT are classified as reads; that is sufficient to get through process startup but is not a complete emulation of the missing context. Signed-off-by: Nat Brown <natbro@gmail.com> --- dlls/ntdll/unix/signal_i386.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index f8a0958bb95..de78fd6a468 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1956,9 +1956,21 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *_sigcontext ) struct xcontext xcontext; EXCEPTION_RECORD rec = { .ExceptionAddress = (void *)EIP_sig( sigcontext ) }; + int trap = TRAP_sig(sigcontext); + save_context( data, &xcontext.c, sigcontext ); - switch (TRAP_sig(sigcontext)) + /* qemu-user synthesizes signal frames without filling in the trap number, + * leaving it -1, so the dispatch below falls through to the default case and + * the fault is never serviced. Infer it from the signal instead. */ + if (trap < 0) switch (signal) + { + case SIGSEGV: trap = TRAP_x86_PAGEFLT; break; + case SIGBUS: trap = TRAP_x86_ALIGNFLT; break; + case SIGILL: trap = TRAP_x86_PRIVINFLT; break; + } + + switch (trap) { case TRAP_x86_OFLOW: /* Overflow exception */ rec.ExceptionCode = EXCEPTION_INT_OVERFLOW; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11737