ntdll: Port the RtlRaiseException test to ARM64.
This commit is contained in:
parent
0fb7c99c33
commit
077252f13b
2 changed files with 151 additions and 16 deletions
|
@ -905,6 +905,9 @@ __ASM_GLOBAL_FUNC( RtlRaiseException,
|
|||
"stp x4, x5, [x1, #0xf0]\n\t" /* context->Fp, Lr */
|
||||
"str x5, [x1, #0x108]\n\t" /* context->Pc */
|
||||
"str x5, [x0, #0x10]\n\t" /* rec->ExceptionAddress */
|
||||
"ldr w2, [x1]\n\t" /* context->ContextFlags */
|
||||
"orr w2, w2, #0x20000000\n\t" /* CONTEXT_UNWOUND_TO_CALL */
|
||||
"str w2, [x1]\n\t"
|
||||
"ldr x3, [x18, #0x60]\n\t" /* peb */
|
||||
"ldrb w2, [x3, #2]\n\t" /* peb->BeingDebugged */
|
||||
"cbnz w2, 1f\n\t"
|
||||
|
|
|
@ -6252,11 +6252,11 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx)
|
|||
{
|
||||
if (stage == STAGE_RTLRAISE_NOT_HANDLED)
|
||||
{
|
||||
ok((char *)ctx.Pc == (char *)code_mem_address + 0xb, "Pc at %p instead of %p\n",
|
||||
(char *)ctx.Pc, (char *)code_mem_address + 0xb);
|
||||
ok((char *)ctx.Pc == (char *)code_mem_address + 0xc, "Pc at %p instead of %p\n",
|
||||
(char *)ctx.Pc, (char *)code_mem_address + 0xc);
|
||||
/* setting the context from debugger does not affect the context that the
|
||||
* exception handler gets, except on w2008 */
|
||||
ctx.Pc = (UINT_PTR)code_mem_address + 0xd;
|
||||
ctx.Pc = (UINT_PTR)code_mem_address + 0x10;
|
||||
ctx.X0 = 0xf00f00f1;
|
||||
/* let the debuggee handle the exception */
|
||||
continuestatus = DBG_EXCEPTION_NOT_HANDLED;
|
||||
|
@ -6266,9 +6266,9 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx)
|
|||
if (de.u.Exception.dwFirstChance)
|
||||
{
|
||||
/* debugger gets first chance exception with unmodified ctx.Pc */
|
||||
ok((char *)ctx.Pc == (char *)code_mem_address + 0xb, "Pc at %p instead of %p\n",
|
||||
(char *)ctx.Pc, (char *)code_mem_address + 0xb);
|
||||
ctx.Pc = (UINT_PTR)code_mem_address + 0xd;
|
||||
ok((char *)ctx.Pc == (char *)code_mem_address + 0xc, "Pc at %p instead of %p\n",
|
||||
(char *)ctx.Pc, (char *)code_mem_address + 0xc);
|
||||
ctx.Pc = (UINT_PTR)code_mem_address + 0x10;
|
||||
ctx.X0 = 0xf00f00f1;
|
||||
/* pass exception to debuggee
|
||||
* exception will not be handled and a second chance exception will be raised */
|
||||
|
@ -6280,13 +6280,13 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx)
|
|||
/* ctx.Pc is the same value the exception handler got */
|
||||
if (de.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
|
||||
{
|
||||
ok((char *)ctx.Pc == (char *)code_mem_address + 0xa,
|
||||
"Pc at %p instead of %p\n", (char *)ctx.Pc, (char *)code_mem_address + 0xa);
|
||||
ok((char *)ctx.Pc == (char *)code_mem_address + 0xc,
|
||||
"Pc at %p instead of %p\n", (char *)ctx.Pc, (char *)code_mem_address + 0xc);
|
||||
/* need to fixup Pc for debuggee */
|
||||
ctx.Pc += 4;
|
||||
}
|
||||
else ok((char *)ctx.Pc == (char *)code_mem_address + 0xb,
|
||||
"Pc at %p instead of %p\n", (void *)ctx.Pc, (char *)code_mem_address + 0xb);
|
||||
else ok((char *)ctx.Pc == (char *)code_mem_address + 0xc,
|
||||
"Pc at %p instead of %p\n", (void *)ctx.Pc, (char *)code_mem_address + 0xc);
|
||||
/* here we handle exception */
|
||||
}
|
||||
}
|
||||
|
@ -6767,12 +6767,13 @@ static void test_KiUserCallbackDispatcher(void)
|
|||
|
||||
static void run_exception_test(void *handler, const void* context,
|
||||
const void *code, unsigned int code_size,
|
||||
unsigned int func2_offset, DWORD access, DWORD handler_flags)
|
||||
unsigned int func2_offset, DWORD access, DWORD handler_flags,
|
||||
void *arg1, void *arg2)
|
||||
{
|
||||
DWORD buf[14];
|
||||
RUNTIME_FUNCTION runtime_func[2];
|
||||
IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA unwind;
|
||||
void (*func)(void) = code_mem;
|
||||
void (*func)(void*,void*) = code_mem;
|
||||
DWORD oldaccess, oldaccess2;
|
||||
|
||||
runtime_func[0].BeginAddress = 0;
|
||||
|
@ -6807,7 +6808,7 @@ static void run_exception_test(void *handler, const void* context,
|
|||
FlushInstructionCache( GetCurrentProcess(), code_mem, 0x2000 );
|
||||
|
||||
pRtlAddFunctionTable(runtime_func, ARRAY_SIZE(runtime_func), (ULONG_PTR)code_mem);
|
||||
func();
|
||||
func( arg1, arg2 );
|
||||
pRtlDeleteFunctionTable(runtime_func);
|
||||
|
||||
if (access) VirtualProtect(code_mem, code_size, oldaccess, &oldaccess2);
|
||||
|
@ -6876,7 +6877,7 @@ static void test_nested_exception(void)
|
|||
{
|
||||
got_nested_exception = got_prev_frame_exception = FALSE;
|
||||
run_exception_test(nested_exception_handler, NULL, nested_except_code, sizeof(nested_except_code),
|
||||
5 * sizeof(DWORD), PAGE_EXECUTE_READ, UNW_FLAG_EHANDLER);
|
||||
5 * sizeof(DWORD), PAGE_EXECUTE_READ, UNW_FLAG_EHANDLER, 0, 0);
|
||||
ok(got_nested_exception, "Did not get nested exception.\n");
|
||||
ok(got_prev_frame_exception, "Did not get nested exception in the previous frame.\n");
|
||||
}
|
||||
|
@ -6944,10 +6945,140 @@ static void test_collided_unwind(void)
|
|||
got_nested_exception = got_prev_frame_exception = FALSE;
|
||||
collided_unwind_exception_count = 0;
|
||||
run_exception_test(collided_exception_handler, NULL, nested_except_code, sizeof(nested_except_code),
|
||||
5 * sizeof(DWORD), PAGE_EXECUTE_READ, UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER);
|
||||
5 * sizeof(DWORD), PAGE_EXECUTE_READ, UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER, 0, 0);
|
||||
ok(collided_unwind_exception_count == 6, "got %u.\n", collided_unwind_exception_count);
|
||||
}
|
||||
|
||||
|
||||
static int rtlraiseexception_unhandled_handler_called;
|
||||
static int rtlraiseexception_teb_handler_called;
|
||||
static int rtlraiseexception_handler_called;
|
||||
|
||||
static void rtlraiseexception_handler_( EXCEPTION_RECORD *rec, void *frame, CONTEXT *context,
|
||||
void *dispatcher, BOOL unhandled_handler )
|
||||
{
|
||||
void *addr = rec->ExceptionAddress;
|
||||
|
||||
trace( "exception: %08lx flags:%lx addr:%p context: Pc:%p\n",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, (void *)context->Pc );
|
||||
|
||||
ok( addr == (char *)code_mem + 0x0c,
|
||||
"ExceptionAddress at %p instead of %p\n", addr, (char *)code_mem + 0x0c );
|
||||
ok( context->ContextFlags == (CONTEXT_FULL | CONTEXT_UNWOUND_TO_CALL) ||
|
||||
context->ContextFlags == (CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS | CONTEXT_UNWOUND_TO_CALL),
|
||||
"wrong context flags %lx\n", context->ContextFlags );
|
||||
ok( context->Pc == (UINT_PTR)addr,
|
||||
"%d: Pc at %Ix instead of %Ix\n", test_stage, context->Pc, (UINT_PTR)addr );
|
||||
|
||||
ok( context->X0 == 0xf00f00f0, "context->X0 is %Ix, should have been set to 0xf00f00f0 in vectored handler\n", context->X0 );
|
||||
}
|
||||
|
||||
static LONG CALLBACK rtlraiseexception_unhandled_handler(EXCEPTION_POINTERS *ExceptionInfo)
|
||||
{
|
||||
PCONTEXT context = ExceptionInfo->ContextRecord;
|
||||
PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
|
||||
|
||||
rtlraiseexception_unhandled_handler_called = 1;
|
||||
rtlraiseexception_handler_(rec, NULL, context, NULL, TRUE);
|
||||
if (test_stage == STAGE_RTLRAISE_HANDLE_LAST_CHANCE) return EXCEPTION_CONTINUE_SEARCH;
|
||||
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
|
||||
static DWORD WINAPI rtlraiseexception_teb_handler( EXCEPTION_RECORD *rec,
|
||||
EXCEPTION_REGISTRATION_RECORD *frame,
|
||||
CONTEXT *context,
|
||||
EXCEPTION_REGISTRATION_RECORD **dispatcher )
|
||||
{
|
||||
rtlraiseexception_teb_handler_called = 1;
|
||||
rtlraiseexception_handler_(rec, frame, context, dispatcher, FALSE);
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
static DWORD WINAPI rtlraiseexception_handler( EXCEPTION_RECORD *rec, void *frame,
|
||||
CONTEXT *context, void *dispatcher )
|
||||
{
|
||||
rtlraiseexception_handler_called = 1;
|
||||
rtlraiseexception_handler_(rec, frame, context, dispatcher, FALSE);
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
static LONG CALLBACK rtlraiseexception_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
|
||||
{
|
||||
PCONTEXT context = ExceptionInfo->ContextRecord;
|
||||
PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
|
||||
void *addr = rec->ExceptionAddress;
|
||||
|
||||
ok( addr == (char *)code_mem + 0xc,
|
||||
"ExceptionAddress at %p instead of %p\n", addr, (char *)code_mem + 0xc );
|
||||
ok( context->Pc == (UINT_PTR)addr,
|
||||
"%d: Pc at %Ix instead of %Ix\n", test_stage, context->Pc, (UINT_PTR)addr );
|
||||
|
||||
context->X0 = 0xf00f00f0;
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
static const DWORD call_one_arg_code[] =
|
||||
{
|
||||
0xa9bf7bfd, /* 00: stp x29, x30, [sp, #-16]! */
|
||||
0x910003fd, /* 04: mov x29, sp */
|
||||
0xd63f0020, /* 08: blr x1 */
|
||||
0xd503201f, /* 0c: nop */
|
||||
0xa8c17bfd, /* 10: ldp x29, x30, [sp], #16 */
|
||||
0xd65f03c0, /* 14: ret */
|
||||
};
|
||||
|
||||
static void run_rtlraiseexception_test(DWORD exceptioncode)
|
||||
{
|
||||
EXCEPTION_REGISTRATION_RECORD frame;
|
||||
EXCEPTION_RECORD record;
|
||||
PVOID vectored_handler = NULL;
|
||||
|
||||
record.ExceptionCode = exceptioncode;
|
||||
record.ExceptionFlags = 0;
|
||||
record.ExceptionRecord = NULL;
|
||||
record.ExceptionAddress = NULL; /* does not matter, copied return address */
|
||||
record.NumberParameters = 0;
|
||||
|
||||
frame.Handler = rtlraiseexception_teb_handler;
|
||||
frame.Prev = NtCurrentTeb()->Tib.ExceptionList;
|
||||
|
||||
NtCurrentTeb()->Tib.ExceptionList = &frame;
|
||||
vectored_handler = pRtlAddVectoredExceptionHandler(TRUE, rtlraiseexception_vectored_handler);
|
||||
ok(vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n");
|
||||
if (pRtlSetUnhandledExceptionFilter) pRtlSetUnhandledExceptionFilter(rtlraiseexception_unhandled_handler);
|
||||
|
||||
rtlraiseexception_handler_called = 0;
|
||||
rtlraiseexception_teb_handler_called = 0;
|
||||
rtlraiseexception_unhandled_handler_called = 0;
|
||||
|
||||
run_exception_test( rtlraiseexception_handler, NULL, call_one_arg_code,
|
||||
sizeof(call_one_arg_code), sizeof(call_one_arg_code),
|
||||
PAGE_EXECUTE_READ, UNW_FLAG_EHANDLER,
|
||||
&record, pRtlRaiseException);
|
||||
|
||||
ok( record.ExceptionAddress == (char *)code_mem + 0x0c,
|
||||
"address set to %p instead of %p\n", record.ExceptionAddress, (char *)code_mem + 0x0c );
|
||||
|
||||
todo_wine
|
||||
ok( !rtlraiseexception_teb_handler_called, "Frame TEB handler called\n" );
|
||||
ok( rtlraiseexception_handler_called, "Frame handler called\n" );
|
||||
ok( rtlraiseexception_unhandled_handler_called, "UnhandledExceptionFilter wasn't called\n" );
|
||||
|
||||
pRtlRemoveVectoredExceptionHandler(vectored_handler);
|
||||
|
||||
if (pRtlSetUnhandledExceptionFilter) pRtlSetUnhandledExceptionFilter(NULL);
|
||||
NtCurrentTeb()->Tib.ExceptionList = frame.Prev;
|
||||
}
|
||||
|
||||
static void test_rtlraiseexception(void)
|
||||
{
|
||||
run_rtlraiseexception_test(0x12345);
|
||||
run_rtlraiseexception_test(EXCEPTION_BREAKPOINT);
|
||||
run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
#endif /* __aarch64__ */
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
|
@ -10079,7 +10210,7 @@ START_TEST(exception)
|
|||
return;
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
|
||||
if (pRtlRaiseException)
|
||||
{
|
||||
test_stage = STAGE_RTLRAISE_NOT_HANDLED;
|
||||
|
@ -10206,6 +10337,7 @@ START_TEST(exception)
|
|||
test_continue();
|
||||
test_nested_exception();
|
||||
test_collided_unwind();
|
||||
test_rtlraiseexception();
|
||||
|
||||
#elif defined(__arm__)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue