diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 630c2a460f8..a5747008a70 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1977,8 +1977,19 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) ucontext_t *ucontext = sigcontext; void *stack = setup_exception_record( sigcontext, &rec, &xcontext ); void *steamclient_addr = NULL; + int trap = TRAP_sig(ucontext); - switch (TRAP_sig(ucontext)) + /* 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; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index d5b93415c2a..00942d18c3f 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -574,7 +574,12 @@ static void mmap_add_reserved_area( void *addr, SIZE_T size ) assert( !((UINT_PTR)addr & host_page_mask) ); assert( !(size & host_page_mask) ); - if (!((intptr_t)addr + size)) size--; /* avoid wrap-around */ + /* An area ending exactly at the 4GB boundary wraps addr+size to 0. Back it off + * by a whole page rather than a single byte, so that the area bounds stay page + * aligned as the asserts above require; consumers such as alloc_virtual_heap() + * derive addresses from the area end and would otherwise be handed an + * unaligned one. */ + if (size >= host_page_size && !((intptr_t)addr + size)) size -= host_page_size; end = (char *)addr + size; LIST_FOR_EACH( ptr, &reserved_areas ) @@ -626,7 +631,12 @@ static void mmap_remove_reserved_area( void *addr, SIZE_T size ) assert( !((UINT_PTR)addr & host_page_mask) ); assert( !(size & host_page_mask) ); - if (!((intptr_t)addr + size)) size--; /* avoid wrap-around */ + /* An area ending exactly at the 4GB boundary wraps addr+size to 0. Back it off + * by a whole page rather than a single byte, so that the area bounds stay page + * aligned as the asserts above require; consumers such as alloc_virtual_heap() + * derive addresses from the area end and would otherwise be handed an + * unaligned one. */ + if (size >= host_page_size && !((intptr_t)addr + size)) size -= host_page_size; ptr = list_head( &reserved_areas ); /* find the first area covering address */