ntdll/tests: Add exception tests for RtlUnwind on i386.
This commit is contained in:
parent
1aa6e581d7
commit
0828715179
|
@ -43,6 +43,7 @@ static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
|
||||||
static NTSTATUS (WINAPI *pNtGetContextThread)(HANDLE,CONTEXT*);
|
static NTSTATUS (WINAPI *pNtGetContextThread)(HANDLE,CONTEXT*);
|
||||||
static NTSTATUS (WINAPI *pNtSetContextThread)(HANDLE,CONTEXT*);
|
static NTSTATUS (WINAPI *pNtSetContextThread)(HANDLE,CONTEXT*);
|
||||||
static NTSTATUS (WINAPI *pRtlRaiseException)(EXCEPTION_RECORD *rec);
|
static NTSTATUS (WINAPI *pRtlRaiseException)(EXCEPTION_RECORD *rec);
|
||||||
|
static PVOID (WINAPI *pRtlUnwind)(PVOID, PVOID, PEXCEPTION_RECORD, PVOID);
|
||||||
static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG first, PVECTORED_EXCEPTION_HANDLER func);
|
static PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG first, PVECTORED_EXCEPTION_HANDLER func);
|
||||||
static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID handler);
|
static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID handler);
|
||||||
static NTSTATUS (WINAPI *pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*);
|
static NTSTATUS (WINAPI *pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*);
|
||||||
|
@ -390,6 +391,83 @@ static void test_rtlraiseexception(void)
|
||||||
run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
|
run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD unwind_expected_eax;
|
||||||
|
|
||||||
|
static DWORD unwind_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||||
|
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||||
|
{
|
||||||
|
trace("exception: %08x flags:%x addr:%p context: Eip:%x\n",
|
||||||
|
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, context->Eip);
|
||||||
|
|
||||||
|
ok(rec->ExceptionCode == STATUS_UNWIND, "ExceptionCode is %08x instead of %08x\n",
|
||||||
|
rec->ExceptionCode, STATUS_UNWIND);
|
||||||
|
ok(rec->ExceptionAddress == (char *)code_mem + 0x22, "ExceptionAddress at %p instead of %p\n",
|
||||||
|
rec->ExceptionAddress, (char *)code_mem + 0x22);
|
||||||
|
ok(context->Eax == unwind_expected_eax, "context->Eax is %08x instead of %08x\n",
|
||||||
|
context->Eax, unwind_expected_eax);
|
||||||
|
|
||||||
|
context->Eax += 1;
|
||||||
|
return ExceptionContinueSearch;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const BYTE call_unwind_code[] = {
|
||||||
|
0x55, /* push %ebp */
|
||||||
|
0x53, /* push %ebx */
|
||||||
|
0x56, /* push %esi */
|
||||||
|
0x57, /* push %edi */
|
||||||
|
0xe8, 0x00, 0x00, 0x00, 0x00, /* call 0 */
|
||||||
|
0x58, /* 0: pop %eax */
|
||||||
|
0x05, 0x1e, 0x00, 0x00, 0x00, /* add $0x1e,%eax */
|
||||||
|
0xff, 0x74, 0x24, 0x20, /* push 0x20(%esp) */
|
||||||
|
0xff, 0x74, 0x24, 0x20, /* push 0x20(%esp) */
|
||||||
|
0x50, /* push %eax */
|
||||||
|
0xff, 0x74, 0x24, 0x24, /* push 0x24(%esp) */
|
||||||
|
0x8B, 0x44, 0x24, 0x24, /* mov 0x24(%esp),%eax */
|
||||||
|
0xff, 0xd0, /* call *%eax */
|
||||||
|
0x5f, /* pop %edi */
|
||||||
|
0x5e, /* pop %esi */
|
||||||
|
0x5b, /* pop %ebx */
|
||||||
|
0x5d, /* pop %ebp */
|
||||||
|
0xc3, /* ret */
|
||||||
|
0xcc, /* int $3 */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void test_unwind(void)
|
||||||
|
{
|
||||||
|
EXCEPTION_REGISTRATION_RECORD frame2, frame1;
|
||||||
|
DWORD (*func)(void* function, EXCEPTION_REGISTRATION_RECORD *pEndFrame, EXCEPTION_RECORD* record, DWORD retval) = code_mem;
|
||||||
|
DWORD retval;
|
||||||
|
|
||||||
|
memcpy(code_mem, call_unwind_code, sizeof(call_unwind_code));
|
||||||
|
|
||||||
|
/* add first unwind handler */
|
||||||
|
frame1.Handler = unwind_handler;
|
||||||
|
frame1.Prev = pNtCurrentTeb()->Tib.ExceptionList;
|
||||||
|
pNtCurrentTeb()->Tib.ExceptionList = &frame1;
|
||||||
|
|
||||||
|
/* add second unwind handler */
|
||||||
|
frame2.Handler = unwind_handler;
|
||||||
|
frame2.Prev = pNtCurrentTeb()->Tib.ExceptionList;
|
||||||
|
pNtCurrentTeb()->Tib.ExceptionList = &frame2;
|
||||||
|
|
||||||
|
/* test unwind to current frame */
|
||||||
|
unwind_expected_eax = 0xDEAD0000;
|
||||||
|
retval = func(pRtlUnwind, &frame2, NULL, 0xDEAD0000);
|
||||||
|
ok(retval == 0xDEAD0000, "RtlUnwind returned eax %08x instead of %08x\n", retval, 0xDEAD0000);
|
||||||
|
ok(pNtCurrentTeb()->Tib.ExceptionList == &frame2, "Exception record points to %p instead of %p\n",
|
||||||
|
pNtCurrentTeb()->Tib.ExceptionList, &frame2);
|
||||||
|
|
||||||
|
/* unwind to frame1 */
|
||||||
|
unwind_expected_eax = 0xDEAD0000;
|
||||||
|
retval = func(pRtlUnwind, &frame1, NULL, 0xDEAD0000);
|
||||||
|
ok(retval == 0xDEAD0001, "RtlUnwind returned eax %08x instead of %08x\n", retval, 0xDEAD0001);
|
||||||
|
ok(pNtCurrentTeb()->Tib.ExceptionList == &frame1, "Exception record points to %p instead of %p\n",
|
||||||
|
pNtCurrentTeb()->Tib.ExceptionList, &frame1);
|
||||||
|
|
||||||
|
/* restore original handler */
|
||||||
|
pNtCurrentTeb()->Tib.ExceptionList = frame1.Prev;
|
||||||
|
}
|
||||||
|
|
||||||
static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
|
||||||
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||||
{
|
{
|
||||||
|
@ -1625,6 +1703,7 @@ START_TEST(exception)
|
||||||
pNtGetContextThread = (void *)GetProcAddress( hntdll, "NtGetContextThread" );
|
pNtGetContextThread = (void *)GetProcAddress( hntdll, "NtGetContextThread" );
|
||||||
pNtSetContextThread = (void *)GetProcAddress( hntdll, "NtSetContextThread" );
|
pNtSetContextThread = (void *)GetProcAddress( hntdll, "NtSetContextThread" );
|
||||||
pNtReadVirtualMemory = (void *)GetProcAddress( hntdll, "NtReadVirtualMemory" );
|
pNtReadVirtualMemory = (void *)GetProcAddress( hntdll, "NtReadVirtualMemory" );
|
||||||
|
pRtlUnwind = (void *)GetProcAddress( hntdll, "RtlUnwind" );
|
||||||
pRtlRaiseException = (void *)GetProcAddress( hntdll, "RtlRaiseException" );
|
pRtlRaiseException = (void *)GetProcAddress( hntdll, "RtlRaiseException" );
|
||||||
pNtTerminateProcess = (void *)GetProcAddress( hntdll, "NtTerminateProcess" );
|
pNtTerminateProcess = (void *)GetProcAddress( hntdll, "NtTerminateProcess" );
|
||||||
pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll,
|
pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( hntdll,
|
||||||
|
@ -1687,6 +1766,7 @@ START_TEST(exception)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_unwind();
|
||||||
test_prot_fault();
|
test_prot_fault();
|
||||||
test_exceptions();
|
test_exceptions();
|
||||||
test_rtlraiseexception();
|
test_rtlraiseexception();
|
||||||
|
|
Loading…
Reference in New Issue