Commit af3aee8a authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

ntdll: Don't call NtRaiseException() on x64 if debugger is not present.

parent c198390c
...@@ -1338,7 +1338,12 @@ __ASM_GLOBAL_FUNC( RtlRaiseException, ...@@ -1338,7 +1338,12 @@ __ASM_GLOBAL_FUNC( RtlRaiseException,
"movq %rax,0xf8(%rdx)\n\t" /* context->Rip */ "movq %rax,0xf8(%rdx)\n\t" /* context->Rip */
"movq %rax,0x10(%rcx)\n\t" /* rec->ExceptionAddress */ "movq %rax,0x10(%rcx)\n\t" /* rec->ExceptionAddress */
"movl $1,%r8d\n\t" "movl $1,%r8d\n\t"
"call " __ASM_NAME("NtRaiseException") "\n\t" "movq %gs:(0x30),%rax\n\t" /* Teb */
"movq 0x60(%rax),%rax\n\t" /* Peb */
"cmpb $0,0x02(%rax)\n\t" /* BeingDebugged */
"jne 1f\n\t"
"call " __ASM_NAME("dispatch_exception") "\n"
"1:\tcall " __ASM_NAME("NtRaiseException") "\n\t"
"movq %rax,%rcx\n\t" "movq %rax,%rcx\n\t"
"call " __ASM_NAME("RtlRaiseStatus") /* does not return */ ); "call " __ASM_NAME("RtlRaiseStatus") /* does not return */ );
......
...@@ -1677,6 +1677,19 @@ static DWORD dbg_except_continue_handler(EXCEPTION_RECORD *rec, EXCEPTION_REGIST ...@@ -1677,6 +1677,19 @@ static DWORD dbg_except_continue_handler(EXCEPTION_RECORD *rec, EXCEPTION_REGIST
return ExceptionContinueExecution; return ExceptionContinueExecution;
} }
static LONG WINAPI dbg_except_continue_vectored_handler(struct _EXCEPTION_POINTERS *e)
{
EXCEPTION_RECORD *rec = e->ExceptionRecord;
CONTEXT *context = e->ContextRecord;
trace("dbg_except_continue_vectored_handler, code %#x, eip %#x.\n", rec->ExceptionCode, context->Eip);
got_exception = 1;
++context->Eip;
return EXCEPTION_CONTINUE_EXECUTION;
}
/* Use CDECL to leave arguments on stack. */ /* Use CDECL to leave arguments on stack. */
void CDECL hook_KiUserExceptionDispatcher(EXCEPTION_RECORD *rec, CONTEXT *context) void CDECL hook_KiUserExceptionDispatcher(EXCEPTION_RECORD *rec, CONTEXT *context)
{ {
...@@ -1714,8 +1727,10 @@ static void test_kiuserexceptiondispatcher(void) ...@@ -1714,8 +1727,10 @@ static void test_kiuserexceptiondispatcher(void)
0x00, 0x00, 0x00, 0x00, /* jmpq *addr */ /* jump to original function. */ 0x00, 0x00, 0x00, 0x00, /* jmpq *addr */ /* jump to original function. */
}; };
void *phook_KiUserExceptionDispatcher = hook_KiUserExceptionDispatcher; void *phook_KiUserExceptionDispatcher = hook_KiUserExceptionDispatcher;
BYTE patched_KiUserExceptionDispatcher_bytes[7];
void *phook_trampoline = hook_trampoline; void *phook_trampoline = hook_trampoline;
DWORD old_protect1, old_protect2; DWORD old_protect1, old_protect2;
EXCEPTION_RECORD record;
BYTE *ptr; BYTE *ptr;
BOOL ret; BOOL ret;
...@@ -1738,7 +1753,8 @@ static void test_kiuserexceptiondispatcher(void) ...@@ -1738,7 +1753,8 @@ static void test_kiuserexceptiondispatcher(void)
memcpy(saved_KiUserExceptionDispatcher_bytes, pKiUserExceptionDispatcher, memcpy(saved_KiUserExceptionDispatcher_bytes, pKiUserExceptionDispatcher,
sizeof(saved_KiUserExceptionDispatcher_bytes)); sizeof(saved_KiUserExceptionDispatcher_bytes));
ptr = (BYTE *)pKiUserExceptionDispatcher;
ptr = patched_KiUserExceptionDispatcher_bytes;
/* mov hook_trampoline, %eax */ /* mov hook_trampoline, %eax */
*ptr++ = 0xa1; *ptr++ = 0xa1;
*(void **)ptr = &phook_trampoline; *(void **)ptr = &phook_trampoline;
...@@ -1747,9 +1763,12 @@ static void test_kiuserexceptiondispatcher(void) ...@@ -1747,9 +1763,12 @@ static void test_kiuserexceptiondispatcher(void)
*ptr++ = 0xff; *ptr++ = 0xff;
*ptr++ = 0xe0; *ptr++ = 0xe0;
memcpy(pKiUserExceptionDispatcher, patched_KiUserExceptionDispatcher_bytes,
sizeof(patched_KiUserExceptionDispatcher_bytes));
got_exception = 0; got_exception = 0;
run_exception_test(dbg_except_continue_handler, NULL, except_code, ARRAY_SIZE(except_code), run_exception_test(dbg_except_continue_handler, NULL, except_code, ARRAY_SIZE(except_code),
PAGE_EXECUTE_READ); PAGE_EXECUTE_READ);
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");
...@@ -1761,6 +1780,25 @@ static void test_kiuserexceptiondispatcher(void) ...@@ -1761,6 +1780,25 @@ static void test_kiuserexceptiondispatcher(void)
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);
record.ExceptionCode = 0x80000003;
record.ExceptionFlags = 0;
record.ExceptionRecord = NULL;
record.ExceptionAddress = NULL; /* does not matter, copied return address */
record.NumberParameters = 0;
AddVectoredExceptionHandler(TRUE, dbg_except_continue_vectored_handler);
memcpy(pKiUserExceptionDispatcher, patched_KiUserExceptionDispatcher_bytes,
sizeof(patched_KiUserExceptionDispatcher_bytes));
got_exception = 0;
hook_called = FALSE;
pRtlRaiseException(&record);
ok(got_exception, "Handler was not called.\n");
ok(hook_called, "Hook was not called.\n");
RemoveVectoredExceptionHandler(dbg_except_continue_vectored_handler);
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());
...@@ -2777,17 +2815,37 @@ static void *hook_exception_address; ...@@ -2777,17 +2815,37 @@ static void *hook_exception_address;
static DWORD dbg_except_continue_handler(EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame, static DWORD dbg_except_continue_handler(EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher) CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher)
{ {
ok(hook_called, "Hook was not called.\n"); trace("handler context->Rip %#lx, codemem %p.\n", context->Rip, code_mem);
got_exception = 1; got_exception = 1;
dbg_except_continue_handler_rip = (void *)context->Rip; dbg_except_continue_handler_rip = (void *)context->Rip;
++context->Rip; ++context->Rip;
memcpy(pKiUserExceptionDispatcher, saved_KiUserExceptionDispatcher_bytes,
sizeof(saved_KiUserExceptionDispatcher_bytes));
return ExceptionContinueExecution; return ExceptionContinueExecution;
} }
static LONG WINAPI dbg_except_continue_vectored_handler(struct _EXCEPTION_POINTERS *e)
{
EXCEPTION_RECORD *rec = e->ExceptionRecord;
CONTEXT *context = e->ContextRecord;
trace("dbg_except_continue_vectored_handler, code %#x, Rip %#lx.\n", rec->ExceptionCode, context->Rip);
got_exception = 1;
if (NtCurrentTeb()->Peb->BeingDebugged || !strcmp( winetest_platform, "wine" ))
{
todo_wine_if(!NtCurrentTeb()->Peb->BeingDebugged)
ok(NtCurrentTeb()->Peb->BeingDebugged, "context->Rip misplaced for dbg breakpoint exception.\n");
++context->Rip;
}
return EXCEPTION_CONTINUE_EXECUTION;
}
void WINAPI hook_KiUserExceptionDispatcher(EXCEPTION_RECORD *rec, CONTEXT *context) void WINAPI hook_KiUserExceptionDispatcher(EXCEPTION_RECORD *rec, CONTEXT *context)
{ {
trace("rec %p, context %p.\n", rec, context); trace("rec %p, context %p.\n", rec, context);
trace("context->Rip %#lx, context->Rsp %#lx, ContextFlags %#lx.\n", sizeof(*context), trace("context->Rip %#lx, context->Rsp %#lx, ContextFlags %#lx.\n",
context->Rip, context->Rsp, context->ContextFlags); context->Rip, context->Rsp, context->ContextFlags);
hook_called = TRUE; hook_called = TRUE;
...@@ -2824,8 +2882,11 @@ static void test_kiuserexceptiondispatcher(void) ...@@ -2824,8 +2882,11 @@ static void test_kiuserexceptiondispatcher(void)
/* offset: 27 bytes */ /* offset: 27 bytes */
0x00, 0x00, 0x00, 0x00, /* jmpq *addr */ /* jump to original function. */ 0x00, 0x00, 0x00, 0x00, /* jmpq *addr */ /* jump to original function. */
}; };
void *phook_KiUserExceptionDispatcher = hook_KiUserExceptionDispatcher; void *phook_KiUserExceptionDispatcher = hook_KiUserExceptionDispatcher;
BYTE patched_KiUserExceptionDispatcher_bytes[12];
DWORD old_protect1, old_protect2; DWORD old_protect1, old_protect2;
EXCEPTION_RECORD record;
BYTE *ptr; BYTE *ptr;
BOOL ret; BOOL ret;
...@@ -2847,11 +2908,13 @@ static void test_kiuserexceptiondispatcher(void) ...@@ -2847,11 +2908,13 @@ static void test_kiuserexceptiondispatcher(void)
ret = VirtualProtect(hook_trampoline, ARRAY_SIZE(hook_trampoline), PAGE_EXECUTE_READWRITE, &old_protect1); ret = VirtualProtect(hook_trampoline, ARRAY_SIZE(hook_trampoline), PAGE_EXECUTE_READWRITE, &old_protect1);
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
ret = VirtualProtect(pKiUserExceptionDispatcher, 5, PAGE_EXECUTE_READWRITE, &old_protect2); ret = VirtualProtect(pKiUserExceptionDispatcher, sizeof(saved_KiUserExceptionDispatcher_bytes),
PAGE_EXECUTE_READWRITE, &old_protect2);
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
memcpy(saved_KiUserExceptionDispatcher_bytes, pKiUserExceptionDispatcher, sizeof(saved_KiUserExceptionDispatcher_bytes)); memcpy(saved_KiUserExceptionDispatcher_bytes, pKiUserExceptionDispatcher,
ptr = (BYTE *)pKiUserExceptionDispatcher; sizeof(saved_KiUserExceptionDispatcher_bytes));
ptr = (BYTE *)patched_KiUserExceptionDispatcher_bytes;
/* mov hook_trampoline, %rax */ /* mov hook_trampoline, %rax */
*ptr++ = 0x48; *ptr++ = 0x48;
*ptr++ = 0xb8; *ptr++ = 0xb8;
...@@ -2861,6 +2924,8 @@ static void test_kiuserexceptiondispatcher(void) ...@@ -2861,6 +2924,8 @@ static void test_kiuserexceptiondispatcher(void)
*ptr++ = 0xff; *ptr++ = 0xff;
*ptr++ = 0xe0; *ptr++ = 0xe0;
memcpy(pKiUserExceptionDispatcher, patched_KiUserExceptionDispatcher_bytes,
sizeof(patched_KiUserExceptionDispatcher_bytes));
got_exception = 0; got_exception = 0;
run_exception_test(dbg_except_continue_handler, NULL, except_code, ARRAY_SIZE(except_code), PAGE_EXECUTE_READ); 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(got_exception, "Handler was not called.\n");
...@@ -2874,7 +2939,42 @@ static void test_kiuserexceptiondispatcher(void) ...@@ -2874,7 +2939,42 @@ static void test_kiuserexceptiondispatcher(void)
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);
ret = VirtualProtect(pKiUserExceptionDispatcher, 5, old_protect2, &old_protect2); memset(&record, 0, sizeof(record));
record.ExceptionCode = 0x80000003;
record.ExceptionFlags = 0;
record.ExceptionRecord = NULL;
record.ExceptionAddress = NULL;
record.NumberParameters = 0;
AddVectoredExceptionHandler(TRUE, dbg_except_continue_vectored_handler);
memcpy(pKiUserExceptionDispatcher, patched_KiUserExceptionDispatcher_bytes,
sizeof(patched_KiUserExceptionDispatcher_bytes));
got_exception = 0;
hook_called = FALSE;
pRtlRaiseException(&record);
ok(got_exception, "Handler was not called.\n");
ok(!hook_called, "Hook was called.\n");
memcpy(pKiUserExceptionDispatcher, patched_KiUserExceptionDispatcher_bytes,
sizeof(patched_KiUserExceptionDispatcher_bytes));
got_exception = 0;
hook_called = FALSE;
NtCurrentTeb()->Peb->BeingDebugged = 1;
pRtlRaiseException(&record);
ok(got_exception, "Handler was not called.\n");
ok(hook_called, "Hook was not called.\n");
NtCurrentTeb()->Peb->BeingDebugged = 0;
RemoveVectoredExceptionHandler(dbg_except_continue_vectored_handler);
ret = VirtualProtect(pKiUserExceptionDispatcher, sizeof(saved_KiUserExceptionDispatcher_bytes),
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());
ret = VirtualProtect(hook_trampoline, ARRAY_SIZE(hook_trampoline), old_protect1, &old_protect1); ret = VirtualProtect(hook_trampoline, ARRAY_SIZE(hook_trampoline), old_protect1, &old_protect1);
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment