1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00

ntdll: Port the RtlRaiseException test to ARM64.

This commit is contained in:
Alexandre Julliard 2024-03-01 18:42:18 +01:00
parent 0fb7c99c33
commit 077252f13b
2 changed files with 151 additions and 16 deletions

View file

@ -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"

View file

@ -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__)