Module: wine Branch: master Commit: db28edc790ccabdab20dfe31e3e06fe7e3e1e8b6 URL: http://source.winehq.org/git/wine.git/?a=commit;h=db28edc790ccabdab20dfe31e3...
Author: Peter Beutner p.beutner@gmx.net Date: Fri Nov 9 17:49:06 2007 +0100
ntdll: Better trap exception handling.
---
dlls/ntdll/signal_i386.c | 15 ++++++++++----- dlls/ntdll/tests/exception.c | 6 +++--- 2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 793b22e..df62a30 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -1040,16 +1040,21 @@ static void WINAPI raise_trap_exception( EXCEPTION_RECORD *rec, CONTEXT *context { if (rec->ExceptionCode == EXCEPTION_SINGLE_STEP) { - if (context->EFlags & 0x100) - { - context->EFlags &= ~0x100; /* clear single-step flag */ - } - else /* hardware breakpoint, fetch the debug registers */ + struct ntdll_thread_regs * const regs = ntdll_get_thread_regs(); + + /* when single stepping can't tell whether this is a hw bp or a + * single step interrupt. try to avoid as much overhead as possible + * and only do a server call if there is any hw bp enabled. */ + + if( !(context->EFlags & 0x100) || (regs->dr7 & 0xff) ) { + /* (possible) hardware breakpoint, fetch the debug registers */ context->ContextFlags = CONTEXT_DEBUG_REGISTERS; NtGetContextThread(GetCurrentThread(), context); context->ContextFlags |= CONTEXT_FULL; /* restore flags */ } + + context->EFlags &= ~0x100; /* clear single-step flag */ }
__regs_RtlRaiseException( rec, context ); diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index ce5d31b..9bd5678 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -489,7 +489,7 @@ static DWORD bpx_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD * /* single step exception on second nop */ ok( context->Eip == (DWORD)code_mem + 1, "eip is wrong: %x instead of %x\n", context->Eip, (DWORD)code_mem + 1); - todo_wine{ ok( (context->Dr6 & 0x4000), "BS flag is not set in Dr6\n"); }; + ok( (context->Dr6 & 0x4000), "BS flag is not set in Dr6\n"); /* depending on the win version the B0 bit is already set here as well ok( (context->Dr6 & 0xf) == 0, "B0...3 flags in Dr6 shouldn't be set\n"); */ context->EFlags |= 0x100; @@ -497,7 +497,7 @@ static DWORD bpx_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD * /* hw bp exception on second nop */ ok( context->Eip == (DWORD)code_mem + 1, "eip is wrong: %x instead of %x\n", context->Eip, (DWORD)code_mem + 1); - todo_wine{ ok( (context->Dr6 & 0xf) == 1, "B0 flag is not set in Dr6\n"); }; + ok( (context->Dr6 & 0xf) == 1, "B0 flag is not set in Dr6\n"); ok( !(context->Dr6 & 0x4000), "BS flag is set in Dr6\n"); context->Dr0 = 0; /* clear breakpoint */ context->EFlags |= 0x100; @@ -506,7 +506,7 @@ static DWORD bpx_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD * ok( context->Eip == (DWORD)code_mem + 2, "eip is wrong: %x instead of %x\n", context->Eip, (DWORD)code_mem + 2); ok( (context->Dr6 & 0xf) == 0, "B0...3 flags in Dr6 shouldn't be set\n"); - todo_wine{ ok( (context->Dr6 & 0x4000), "BS flag is not set in Dr6\n"); }; + ok( (context->Dr6 & 0x4000), "BS flag is not set in Dr6\n"); }
context->Dr6 = 0; /* clear status register */