[prev in list] [next in list] [prev in thread] [next in thread]
List: wine-devel
Subject: [PATCH 2/2] ntdll/tests: Add test for x64 KiUserExceptionDispatcher().
From: Paul Gofman <pgofman () codeweavers ! com>
Date: 2020-06-30 20:34:35
Message-ID: 20200630203435.489703-2-pgofman () codeweavers ! com
[Download RAW message or body]
Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
---
dlls/ntdll/tests/exception.c | 114 +++++++++++++++++++++++++++++++++++
1 file changed, 114 insertions(+)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 411439f180f..95d25375f77 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -2659,6 +2659,119 @@ static void test_wow64_context(void)
pNtTerminateProcess(pi.hProcess, 0);
}
+static BYTE saved_KiUserExceptionDispatcher_bytes[12];
+static void *pKiUserExceptionDispatcher;
+static BOOL hook_called;
+static void *hook_KiUserExceptionDispatcher_rip;
+static void *dbg_except_continue_handler_rip;
+static void *hook_exception_address;
+
+static DWORD dbg_except_continue_handler(EXCEPTION_RECORD *rec, \
EXCEPTION_REGISTRATION_RECORD *frame, + CONTEXT *context, \
EXCEPTION_REGISTRATION_RECORD **dispatcher) +{
+ ok(hook_called, "Hook was not called.\n");
+ got_exception = 1;
+ dbg_except_continue_handler_rip = (void *)context->Rip;
+ ++context->Rip;
+ return ExceptionContinueExecution;
+}
+
+void WINAPI hook_KiUserExceptionDispatcher(EXCEPTION_RECORD *rec, CONTEXT *context)
+{
+ trace("rec %p, context %p.\n", rec, context);
+ trace("context->Rip %#lx, context->Rsp %#lx, ContextFlags %#lx.\n", \
sizeof(*context), + context->Rip, context->Rsp, context->ContextFlags);
+
+ hook_called = TRUE;
+ /* Broken on Win2008, probably rec offset in stack is different. */
+ ok(rec->ExceptionCode == 0x80000003 || broken(!rec->ExceptionCode),
+ "Got unexpected ExceptionCode %#x.\n", rec->ExceptionCode);
+
+ hook_KiUserExceptionDispatcher_rip = (void *)context->Rip;
+ hook_exception_address = rec->ExceptionAddress;
+ memcpy(pKiUserExceptionDispatcher, saved_KiUserExceptionDispatcher_bytes, \
sizeof(saved_KiUserExceptionDispatcher_bytes)); +}
+
+static void test_kiuserexceptiondispatcher(void)
+{
+ HMODULE hntdll = GetModuleHandleA("ntdll.dll");
+ static const BYTE except_code[] =
+ {
+ 0xcc, /* int3 */
+ 0xc3, /* ret */
+ };
+ static BYTE hook_trampoline[] =
+ {
+ 0x48, 0x89, 0xe2, /* mov %rsp,%rdx */
+ 0x48, 0x8d, 0x8c, 0x24, 0xf0, 0x04, 0x00, 0x00,
+ /* lea 0x4f0(%rsp),%rcx */
+
+ 0xff, 0x14, 0x25,
+ /* offset: 14 bytes */
+ 0x00, 0x00, 0x00, 0x00, /* callq *addr */ /* call hook implementation. \
*/ + 0x48, 0x31, 0xc9, /* xor %rcx, %rcx */
+ 0x48, 0x31, 0xd2, /* xor %rdx, %rdx */
+
+ 0xff, 0x24, 0x25,
+ /* offset: 27 bytes */
+ 0x00, 0x00, 0x00, 0x00, /* jmpq *addr */ /* jump to original function. \
*/ + };
+ void *phook_KiUserExceptionDispatcher = hook_KiUserExceptionDispatcher;
+ DWORD old_protect1, old_protect2;
+ BYTE *ptr;
+ BOOL ret;
+
+ pKiUserExceptionDispatcher = (void *)GetProcAddress(hntdll, \
"KiUserExceptionDispatcher"); + if (!pKiUserExceptionDispatcher)
+ {
+ win_skip("KiUserExceptionDispatcher is not available.\n");
+ return;
+ }
+
+ ok(((ULONG64)&phook_KiUserExceptionDispatcher & 0xffffffff) == \
((ULONG64)&phook_KiUserExceptionDispatcher), + "Address is too long.\n");
+ ok(((ULONG64)&pKiUserExceptionDispatcher & 0xffffffff) == \
((ULONG64)&pKiUserExceptionDispatcher), + "Address is too long.\n");
+
+ *(unsigned int *)(hook_trampoline + 14) = (unsigned \
int)(ULONG_PTR)&phook_KiUserExceptionDispatcher; + *(unsigned int \
*)(hook_trampoline + 27) = (unsigned int)(ULONG_PTR)&pKiUserExceptionDispatcher; +
+ ret = VirtualProtect(hook_trampoline, ARRAY_SIZE(hook_trampoline), \
PAGE_EXECUTE_READWRITE, &old_protect1); + ok(ret, "Got unexpected ret %#x, \
GetLastError() %u.\n", ret, GetLastError()); +
+ ret = VirtualProtect(pKiUserExceptionDispatcher, 5, PAGE_EXECUTE_READWRITE, \
&old_protect2); + ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, \
GetLastError()); +
+ memcpy(saved_KiUserExceptionDispatcher_bytes, pKiUserExceptionDispatcher, \
sizeof(saved_KiUserExceptionDispatcher_bytes)); + ptr = (BYTE \
*)pKiUserExceptionDispatcher; + /* mov hook_trampoline, %rax */
+ *ptr++ = 0x48;
+ *ptr++ = 0xb8;
+ *(void **)ptr = hook_trampoline;
+ ptr += sizeof(ULONG64);
+ /* jmp *rax */
+ *ptr++ = 0xff;
+ *ptr++ = 0xe0;
+
+ got_exception = 0;
+ 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_exception_address == code_mem || broken(!hook_exception_address) /* \
Win2008 */, + "Got unexpected exception address %p, expected %p.\n",
+ hook_exception_address, code_mem);
+ todo_wine 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);
+
+ ret = VirtualProtect(pKiUserExceptionDispatcher, 5, old_protect2, \
&old_protect2); + ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, \
GetLastError()); + ret = VirtualProtect(hook_trampoline, \
ARRAY_SIZE(hook_trampoline), old_protect1, &old_protect1); + ok(ret, "Got \
unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError()); +}
+
#endif /* __x86_64__ */
#if defined(__i386__) || defined(__x86_64__)
@@ -3638,6 +3751,7 @@ START_TEST(exception)
test_suspend_thread();
test_suspend_process();
test_unload_trace();
+ test_kiuserexceptiondispatcher();
if (pRtlAddFunctionTable && pRtlDeleteFunctionTable && \
pRtlInstallFunctionTableCallback && pRtlLookupFunctionEntry) test_dynamic_unwind();
--
2.26.2
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic