From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/tests/exception.c | 47 +++++++++++++++++++++++++++++++++ dlls/ntdll/unix/signal_i386.c | 9 +++++-- dlls/ntdll/unix/signal_x86_64.c | 9 +++++-- 3 files changed, 61 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index acf6946736e..c2ceef5eb7f 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -250,6 +250,51 @@ static void check_context_exception_request_( DWORD flags, BOOL hardware_excepti ok_(__FILE__, line)( (flags & exception_reporting_flags) == expected_flags, "got %#lx, expected %#lx.\n", flags, expected_flags ); } + +static BOOL test_hwbpt_in_syscall_trap; + +static LONG WINAPI test_hwbpt_in_syscall_handler( EXCEPTION_POINTERS *eptr ) +{ + EXCEPTION_RECORD *rec = eptr->ExceptionRecord; + + test_hwbpt_in_syscall_trap = TRUE; + ok(rec->ExceptionCode == EXCEPTION_SINGLE_STEP, "got %#lx.\n", rec->ExceptionCode); + return EXCEPTION_CONTINUE_EXECUTION; +} + +static void test_hwbpt_in_syscall(void) +{ + TEB *teb = NtCurrentTeb(); + NTSTATUS status; + void *handler; + CONTEXT c; + DWORD ind; + BOOL bret; + + ind = TlsAlloc(); + ok(ind < ARRAY_SIZE(teb->TlsSlots), "got %lu.\n", ind); + handler = AddVectoredExceptionHandler(TRUE, test_hwbpt_in_syscall_handler); + memset(&c, 0, sizeof(c)); + c.ContextFlags = CONTEXT_DEBUG_REGISTERS; + c.Dr0 = (ULONG_PTR)&teb->TlsSlots[ind]; + c.Dr7 = 3 | (3 << 16) | (3 << 18); /* read / write 4 byte breakpoint. */ + bret = SetThreadContext(GetCurrentThread(), &c); + ok(bret, "got error %lu.\n", GetLastError()); + test_hwbpt_in_syscall_trap = FALSE; + teb->TlsSlots[ind] = (void *)0xdeadbeef; + ok(test_hwbpt_in_syscall_trap, "expected trap.\n"); + + test_hwbpt_in_syscall_trap = FALSE; + status = NtSetInformationThread(GetCurrentThread(), ThreadZeroTlsCell, &ind, sizeof(ind)); + ok(!status, "got %#lx.\n", status); + ok(!test_hwbpt_in_syscall_trap, "got trap.\n"); + c.Dr7 = 0; + bret = SetThreadContext(GetCurrentThread(), &c); + ok(bret, "got error %lu.\n", GetLastError()); + ok(!teb->TlsSlots[ind], "got %p.\n", teb->TlsSlots[ind]); + RemoveVectoredExceptionHandler(handler); + TlsFree(ind); +} #endif
#ifdef __i386__ @@ -11498,6 +11543,7 @@ START_TEST(exception) test_extended_context(); test_copy_context(); test_set_live_context(); + test_hwbpt_in_syscall();
#elif defined(__x86_64__)
@@ -11527,6 +11573,7 @@ START_TEST(exception) test_unwind_from_apc(); test_syscall_clobbered_regs(); test_raiseexception_regs(); + test_hwbpt_in_syscall();
#elif defined(__aarch64__)
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index f55879a611e..b727a4d5d6a 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1850,7 +1850,7 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, void *stack_ptr, * * Handle a trap exception during a system call. */ -static BOOL handle_syscall_trap( ucontext_t *sigcontext ) +static BOOL handle_syscall_trap( ucontext_t *sigcontext, siginfo_t *siginfo ) { struct syscall_frame *frame = x86_thread_data()->syscall_frame;
@@ -1868,6 +1868,11 @@ static BOOL handle_syscall_trap( ucontext_t *sigcontext )
EIP_sig( sigcontext ) = (ULONG)__wine_unix_call_dispatcher_prolog_end; } + else if (siginfo->si_code == 4 /* TRAP_HWBKPT */ && is_inside_syscall( sigcontext )) + { + TRACE_(seh)( "ignoring HWBKPT in syscall eip=%p\n", (void *)EIP_sig(sigcontext) ); + return TRUE; + } else return FALSE;
TRACE( "ignoring trap in syscall eip=%08x eflags=%08x\n", EIP_sig(sigcontext), EFL_sig(sigcontext) ); @@ -1984,7 +1989,7 @@ static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext ) ucontext_t *ucontext = sigcontext; void *stack = setup_exception_record( sigcontext, &rec, &xcontext );
- if (handle_syscall_trap( ucontext )) return; + if (handle_syscall_trap( ucontext, siginfo )) return;
switch (TRAP_sig(ucontext)) { diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 8ed06cc5cc1..1557d7bcb43 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1894,7 +1894,7 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, EXCEPTION_RECORD *rec, * * Handle a trap exception during a system call. */ -static BOOL handle_syscall_trap( ucontext_t *sigcontext ) +static BOOL handle_syscall_trap( ucontext_t *sigcontext, siginfo_t *siginfo ) { struct syscall_frame *frame = amd64_thread_data()->syscall_frame;
@@ -1913,6 +1913,11 @@ static BOOL handle_syscall_trap( ucontext_t *sigcontext ) RIP_sig( sigcontext ) = (ULONG64)__wine_unix_call_dispatcher_prolog_end_ptr; R10_sig( sigcontext ) = RCX_sig( sigcontext ); } + else if (siginfo->si_code == 4 /* TRAP_HWBKPT */ && is_inside_syscall( sigcontext )) + { + TRACE_(seh)( "ignoring HWBKPT in syscall rip=%p\n", (void *)RIP_sig(sigcontext) ); + return TRUE; + } else return FALSE;
TRACE_(seh)( "ignoring trap in syscall rip=%p eflags=%08x\n", @@ -2025,7 +2030,7 @@ static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext ) struct xcontext context; ucontext_t *ucontext = init_handler( sigcontext );
- if (handle_syscall_trap( ucontext )) return; + if (handle_syscall_trap( ucontext, siginfo )) return;
rec.ExceptionAddress = (void *)RIP_sig(ucontext); save_context( &context, ucontext );