ntdll: Fixup instruction pointer for EXCEPTION_BREAKPOINT in the Unix part on x86/x86_64.
Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b72270cb16
commit
e722660114
|
@ -230,9 +230,6 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||||
context->SegEs, context->SegFs, context->SegGs, context->EFlags );
|
context->SegEs, context->SegFs, context->SegGs, context->EFlags );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
|
|
||||||
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Eip--;
|
|
||||||
|
|
||||||
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
|
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
|
||||||
NtContinue( context, FALSE );
|
NtContinue( context, FALSE );
|
||||||
|
|
||||||
|
|
|
@ -564,9 +564,6 @@ NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
|
||||||
context->R12, context->R13, context->R14, context->R15 );
|
context->R12, context->R13, context->R14, context->R15 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
|
|
||||||
if (rec->ExceptionCode == EXCEPTION_BREAKPOINT) context->Rip--;
|
|
||||||
|
|
||||||
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
|
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
|
||||||
NtContinue( context, FALSE );
|
NtContinue( context, FALSE );
|
||||||
|
|
||||||
|
|
|
@ -1671,6 +1671,9 @@ static DWORD dbg_except_continue_handler(EXCEPTION_RECORD *rec, EXCEPTION_REGIST
|
||||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher)
|
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher)
|
||||||
{
|
{
|
||||||
ok(hook_called, "Hook was not called.\n");
|
ok(hook_called, "Hook was not called.\n");
|
||||||
|
|
||||||
|
ok(rec->ExceptionCode == 0x80000003, "Got unexpected ExceptionCode %#x.\n", rec->ExceptionCode);
|
||||||
|
|
||||||
got_exception = 1;
|
got_exception = 1;
|
||||||
dbg_except_continue_handler_eip = (void *)context->Eip;
|
dbg_except_continue_handler_eip = (void *)context->Eip;
|
||||||
++context->Eip;
|
++context->Eip;
|
||||||
|
@ -1682,11 +1685,22 @@ static LONG WINAPI dbg_except_continue_vectored_handler(struct _EXCEPTION_POINTE
|
||||||
EXCEPTION_RECORD *rec = e->ExceptionRecord;
|
EXCEPTION_RECORD *rec = e->ExceptionRecord;
|
||||||
CONTEXT *context = e->ContextRecord;
|
CONTEXT *context = e->ContextRecord;
|
||||||
|
|
||||||
trace("dbg_except_continue_vectored_handler, code %#x, eip %#x.\n", rec->ExceptionCode, context->Eip);
|
trace("dbg_except_continue_vectored_handler, code %#x, eip %#x, ExceptionAddress %p.\n",
|
||||||
|
rec->ExceptionCode, context->Eip, rec->ExceptionAddress);
|
||||||
|
|
||||||
|
ok(rec->ExceptionCode == 0x80000003, "Got unexpected ExceptionCode %#x.\n", rec->ExceptionCode);
|
||||||
|
|
||||||
got_exception = 1;
|
got_exception = 1;
|
||||||
++context->Eip;
|
|
||||||
|
|
||||||
|
if ((ULONG_PTR)rec->ExceptionAddress == context->Eip + 1)
|
||||||
|
{
|
||||||
|
/* XP and Vista+ have ExceptionAddress == Eip + 1, Eip is adjusted even
|
||||||
|
* for software raised breakpoint exception.
|
||||||
|
* Win2003 has Eip not adjusted and matching ExceptionAddress.
|
||||||
|
* Win2008 has Eip not adjuated and ExceptionAddress not filled for
|
||||||
|
* software raised exception. */
|
||||||
|
context->Eip = (ULONG_PTR)rec->ExceptionAddress;
|
||||||
|
}
|
||||||
return EXCEPTION_CONTINUE_EXECUTION;
|
return EXCEPTION_CONTINUE_EXECUTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1775,7 +1789,7 @@ static void test_kiuserexceptiondispatcher(void)
|
||||||
ok(hook_exception_address == code_mem || broken(!hook_exception_address) /* Win2008 */,
|
ok(hook_exception_address == code_mem || broken(!hook_exception_address) /* Win2008 */,
|
||||||
"Got unexpected exception address %p, expected %p.\n",
|
"Got unexpected exception address %p, expected %p.\n",
|
||||||
hook_exception_address, code_mem);
|
hook_exception_address, code_mem);
|
||||||
todo_wine ok(hook_KiUserExceptionDispatcher_eip == code_mem, "Got unexpected exception address %p, expected %p.\n",
|
ok(hook_KiUserExceptionDispatcher_eip == code_mem, "Got unexpected exception address %p, expected %p.\n",
|
||||||
hook_KiUserExceptionDispatcher_eip, code_mem);
|
hook_KiUserExceptionDispatcher_eip, code_mem);
|
||||||
ok(dbg_except_continue_handler_eip == code_mem, "Got unexpected exception address %p, expected %p.\n",
|
ok(dbg_except_continue_handler_eip == code_mem, "Got unexpected exception address %p, expected %p.\n",
|
||||||
dbg_except_continue_handler_eip, code_mem);
|
dbg_except_continue_handler_eip, code_mem);
|
||||||
|
@ -1796,7 +1810,7 @@ static void test_kiuserexceptiondispatcher(void)
|
||||||
pRtlRaiseException(&record);
|
pRtlRaiseException(&record);
|
||||||
|
|
||||||
ok(got_exception, "Handler was not called.\n");
|
ok(got_exception, "Handler was not called.\n");
|
||||||
ok(hook_called, "Hook was not called.\n");
|
ok(hook_called || broken(!hook_called) /* 2003 */, "Hook was not called.\n");
|
||||||
|
|
||||||
RemoveVectoredExceptionHandler(dbg_except_continue_vectored_handler);
|
RemoveVectoredExceptionHandler(dbg_except_continue_vectored_handler);
|
||||||
ret = VirtualProtect(pKiUserExceptionDispatcher, sizeof(saved_KiUserExceptionDispatcher_bytes),
|
ret = VirtualProtect(pKiUserExceptionDispatcher, sizeof(saved_KiUserExceptionDispatcher_bytes),
|
||||||
|
@ -2832,13 +2846,13 @@ static LONG WINAPI dbg_except_continue_vectored_handler(struct _EXCEPTION_POINTE
|
||||||
|
|
||||||
trace("dbg_except_continue_vectored_handler, code %#x, Rip %#lx.\n", rec->ExceptionCode, context->Rip);
|
trace("dbg_except_continue_vectored_handler, code %#x, Rip %#lx.\n", rec->ExceptionCode, context->Rip);
|
||||||
|
|
||||||
|
ok(rec->ExceptionCode == 0x80000003, "Got unexpected exception code %#x.\n", rec->ExceptionCode);
|
||||||
|
|
||||||
got_exception = 1;
|
got_exception = 1;
|
||||||
if (NtCurrentTeb()->Peb->BeingDebugged || !strcmp( winetest_platform, "wine" ))
|
dbg_except_continue_handler_rip = (void *)context->Rip;
|
||||||
{
|
if (NtCurrentTeb()->Peb->BeingDebugged)
|
||||||
todo_wine_if(!NtCurrentTeb()->Peb->BeingDebugged)
|
|
||||||
ok(NtCurrentTeb()->Peb->BeingDebugged, "context->Rip misplaced for dbg breakpoint exception.\n");
|
|
||||||
++context->Rip;
|
++context->Rip;
|
||||||
}
|
|
||||||
return EXCEPTION_CONTINUE_EXECUTION;
|
return EXCEPTION_CONTINUE_EXECUTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2934,7 +2948,7 @@ static void test_kiuserexceptiondispatcher(void)
|
||||||
ok(hook_exception_address == code_mem || broken(!hook_exception_address) /* Win2008 */,
|
ok(hook_exception_address == code_mem || broken(!hook_exception_address) /* Win2008 */,
|
||||||
"Got unexpected exception address %p, expected %p.\n",
|
"Got unexpected exception address %p, expected %p.\n",
|
||||||
hook_exception_address, code_mem);
|
hook_exception_address, code_mem);
|
||||||
todo_wine ok(hook_KiUserExceptionDispatcher_rip == code_mem, "Got unexpected exception address %p, expected %p.\n",
|
ok(hook_KiUserExceptionDispatcher_rip == code_mem, "Got unexpected exception address %p, expected %p.\n",
|
||||||
hook_KiUserExceptionDispatcher_rip, code_mem);
|
hook_KiUserExceptionDispatcher_rip, code_mem);
|
||||||
ok(dbg_except_continue_handler_rip == code_mem, "Got unexpected exception address %p, expected %p.\n",
|
ok(dbg_except_continue_handler_rip == code_mem, "Got unexpected exception address %p, expected %p.\n",
|
||||||
dbg_except_continue_handler_rip, code_mem);
|
dbg_except_continue_handler_rip, code_mem);
|
||||||
|
@ -2969,10 +2983,27 @@ static void test_kiuserexceptiondispatcher(void)
|
||||||
ok(got_exception, "Handler was not called.\n");
|
ok(got_exception, "Handler was not called.\n");
|
||||||
ok(hook_called, "Hook was not called.\n");
|
ok(hook_called, "Hook was not called.\n");
|
||||||
|
|
||||||
NtCurrentTeb()->Peb->BeingDebugged = 0;
|
ok(hook_exception_address == (BYTE *)hook_KiUserExceptionDispatcher_rip + 1
|
||||||
|
|| broken(!hook_exception_address) /* 2008 */, "Got unexpected addresses %p, %p.\n",
|
||||||
|
hook_KiUserExceptionDispatcher_rip, hook_exception_address);
|
||||||
|
|
||||||
RemoveVectoredExceptionHandler(dbg_except_continue_vectored_handler);
|
RemoveVectoredExceptionHandler(dbg_except_continue_vectored_handler);
|
||||||
|
|
||||||
|
memcpy(pKiUserExceptionDispatcher, patched_KiUserExceptionDispatcher_bytes,
|
||||||
|
sizeof(patched_KiUserExceptionDispatcher_bytes));
|
||||||
|
got_exception = 0;
|
||||||
|
hook_called = FALSE;
|
||||||
|
run_exception_test(dbg_except_continue_handler, NULL, except_code, ARRAY_SIZE(except_code), PAGE_EXECUTE_READ);
|
||||||
|
|
||||||
|
ok(got_exception, "Handler was not called.\n");
|
||||||
|
ok(hook_called, "Hook was not called.\n");
|
||||||
|
ok(hook_KiUserExceptionDispatcher_rip == code_mem, "Got unexpected exception address %p, expected %p.\n",
|
||||||
|
hook_KiUserExceptionDispatcher_rip, code_mem);
|
||||||
|
ok(dbg_except_continue_handler_rip == code_mem, "Got unexpected exception address %p, expected %p.\n",
|
||||||
|
dbg_except_continue_handler_rip, code_mem);
|
||||||
|
|
||||||
|
NtCurrentTeb()->Peb->BeingDebugged = 0;
|
||||||
|
|
||||||
ret = VirtualProtect(pKiUserExceptionDispatcher, sizeof(saved_KiUserExceptionDispatcher_bytes),
|
ret = VirtualProtect(pKiUserExceptionDispatcher, sizeof(saved_KiUserExceptionDispatcher_bytes),
|
||||||
old_protect2, &old_protect2);
|
old_protect2, &old_protect2);
|
||||||
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
|
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
|
||||||
|
|
|
@ -1584,11 +1584,22 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *
|
||||||
SS_sig(sigcontext) = get_ds();
|
SS_sig(sigcontext) = get_ds();
|
||||||
stack->rec_ptr = &stack->rec; /* arguments for KiUserExceptionDispatcher */
|
stack->rec_ptr = &stack->rec; /* arguments for KiUserExceptionDispatcher */
|
||||||
stack->context_ptr = &stack->context;
|
stack->context_ptr = &stack->context;
|
||||||
|
|
||||||
|
if (stack->rec.ExceptionCode == EXCEPTION_BREAKPOINT)
|
||||||
|
{
|
||||||
|
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
|
||||||
|
stack->context.Eip--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__ASM_GLOBAL_FUNC( call_user_exception_dispatcher,
|
__ASM_GLOBAL_FUNC( call_user_exception_dispatcher,
|
||||||
"add $4,%esp\n\t"
|
"add $4,%esp\n\t"
|
||||||
"jmp *8(%esp)")
|
"movl (%esp),%eax\n\t" /* rec */
|
||||||
|
"cmpl $0x80000003,(%eax)\n\t" /* ExceptionCode */
|
||||||
|
"jne 1f\n\t"
|
||||||
|
"movl 4(%esp),%eax\n\t" /* context */
|
||||||
|
"decl 0xb8(%eax)\n\t" /* Eip */
|
||||||
|
"1:\tjmp *8(%esp)")
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* get_fpu_code
|
* get_fpu_code
|
||||||
|
|
|
@ -1958,6 +1958,12 @@ static void setup_raise_exception( ucontext_t *sigcontext, struct stack_layout *
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stack->rec.ExceptionCode == EXCEPTION_BREAKPOINT)
|
||||||
|
{
|
||||||
|
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
|
||||||
|
stack->context.Rip--;
|
||||||
|
}
|
||||||
|
|
||||||
/* now modify the sigcontext to return to the raise function */
|
/* now modify the sigcontext to return to the raise function */
|
||||||
RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline;
|
RIP_sig(sigcontext) = (ULONG_PTR)raise_func_trampoline;
|
||||||
R8_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher;
|
R8_sig(sigcontext) = (ULONG_PTR)pKiUserExceptionDispatcher;
|
||||||
|
@ -1983,6 +1989,13 @@ void WINAPI do_call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *c
|
||||||
{
|
{
|
||||||
memmove(&stack->context, context, sizeof(*context));
|
memmove(&stack->context, context, sizeof(*context));
|
||||||
memcpy(&stack->rec, rec, sizeof(*rec));
|
memcpy(&stack->rec, rec, sizeof(*rec));
|
||||||
|
|
||||||
|
if (stack->rec.ExceptionCode == EXCEPTION_BREAKPOINT)
|
||||||
|
{
|
||||||
|
/* fix up instruction pointer in context for EXCEPTION_BREAKPOINT */
|
||||||
|
stack->context.Rip--;
|
||||||
|
}
|
||||||
|
|
||||||
user_exception_dispatcher_trampoline( stack, dispatcher );
|
user_exception_dispatcher_trampoline( stack, dispatcher );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue