From f35e2d513d5a96887d876bc3a0e171ff381f1ae5 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 1 Mar 2024 13:37:29 +0100 Subject: [PATCH] ntdll: Implement RtlRaiseException on ARM64EC. --- dlls/ntdll/signal_arm64ec.c | 28 ++++++++++++++++++++++-- dlls/ntdll/tests/exception.c | 42 ++++++++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index 1c4b8d94727..90060e26daf 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -1794,9 +1794,33 @@ void __attribute__((naked)) __chkstk_arm64ec(void) /*********************************************************************** * RtlRaiseException (NTDLL.@) */ -void WINAPI RtlRaiseException( struct _EXCEPTION_RECORD * rec) +void __attribute((naked)) RtlRaiseException( EXCEPTION_RECORD *rec ) { - FIXME( "not implemented\n" ); + asm( ".seh_proc RtlRaiseException\n\t" + "sub sp, sp, #0x4d0\n\t" /* sizeof(context) */ + ".seh_stackalloc 0x4d0\n\t" + "stp x29, x30, [sp, #-0x20]!\n\t" + ".seh_save_fplr_x 0x20\n\t" + "str x0, [sp, #0x10]\n\t" + ".seh_save_any_reg x0, 0x10\n\t" + ".seh_endprologue\n\t" + "add x0, sp, #0x20\n\t" + "bl RtlCaptureContext\n\t" + "add x1, sp, #0x20\n\t" /* context pointer */ + "ldr x0, [sp, #0x10]\n\t" /* rec */ + "ldr x2, [x1, #0xf8]\n\t" /* context->Rip */ + "str x2, [x0, #0x10]\n\t" /* rec->ExceptionAddress */ + "ldr w2, [x1, #0x30]\n\t" /* context->ContextFlags */ + "orr w2, w2, #0x20000000\n\t" /* CONTEXT_UNWOUND_TO_CALL */ + "str w2, [x1, #0x30]\n\t" + "ldr x3, [x18, #0x60]\n\t" /* peb */ + "ldrb w2, [x3, #2]\n\t" /* peb->BeingDebugged */ + "cbnz w2, 1f\n\t" + "bl dispatch_exception\n" + "1:\tmov w2, #1\n\t" + "bl NtRaiseException\n\t" + "b RtlRaiseStatus\n\t" /* does not return */ + ".seh_endproc" ); } diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 1e51d207f1c..b0b76f37813 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -3218,13 +3218,23 @@ static void rtlraiseexception_handler_( EXCEPTION_RECORD *rec, void *frame, CONT trace( "exception: %08lx flags:%lx addr:%p context: Rip:%p\n", rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, (void *)context->Rip ); - ok( addr == (char *)code_mem + 0x0c || broken( addr == code_mem || !addr ) /* 2008 */, - "ExceptionAddress at %p instead of %p\n", addr, (char *)code_mem + 0x0c ); - - ok( context->ContextFlags == CONTEXT_ALL || context->ContextFlags == (CONTEXT_ALL | CONTEXT_XSTATE) - || context->ContextFlags == (CONTEXT_FULL | CONTEXT_SEGMENTS) - || context->ContextFlags == (CONTEXT_FULL | CONTEXT_SEGMENTS | CONTEXT_XSTATE), - "wrong context flags %lx\n", context->ContextFlags ); + if (is_arm64ec) /* addr points to RtlRaiseException entry thunk */ + { + ok( ((ULONG *)addr)[-1] == 0xd63f0120 /* blr x9 */, + "ExceptionAddress not in entry thunk %p (ntdll+%Ix)\n", + addr, (char *)addr - (char *)hntdll ); + ok( context->ContextFlags == (CONTEXT_FULL | CONTEXT_UNWOUND_TO_CALL), + "wrong context flags %lx\n", context->ContextFlags ); + } + else + { + ok( addr == (char *)code_mem + 0x0c || broken( addr == code_mem || !addr ) /* 2008 */, + "ExceptionAddress at %p instead of %p\n", addr, (char *)code_mem + 0x0c ); + ok( context->ContextFlags == CONTEXT_ALL || context->ContextFlags == (CONTEXT_ALL | CONTEXT_XSTATE) + || context->ContextFlags == (CONTEXT_FULL | CONTEXT_SEGMENTS) + || context->ContextFlags == (CONTEXT_FULL | CONTEXT_SEGMENTS | CONTEXT_XSTATE), + "wrong context flags %lx\n", context->ContextFlags ); + } /* check that pc is fixed up only for EXCEPTION_BREAKPOINT * even if raised by RtlRaiseException @@ -3278,8 +3288,13 @@ static LONG CALLBACK rtlraiseexception_vectored_handler(EXCEPTION_POINTERS *Exce PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord; void *addr = rec->ExceptionAddress; - ok( addr == (char *)code_mem + 0xc || broken(addr == code_mem || !addr ) /* 2008 */, - "ExceptionAddress at %p instead of %p\n", addr, (char *)code_mem + 0xc ); + if (is_arm64ec) /* addr points to RtlRaiseException entry thunk */ + ok( ((ULONG *)addr)[-1] == 0xd63f0120 /* blr x9 */, + "ExceptionAddress not in entry thunk %p (ntdll+%Ix)\n", + addr, (char *)addr - (char *)hntdll ); + else + ok( addr == (char *)code_mem + 0xc || broken(addr == code_mem || !addr ) /* 2008 */, + "ExceptionAddress at %p instead of %p\n", addr, (char *)code_mem + 0xc ); /* check that Rip is fixed up only for EXCEPTION_BREAKPOINT * even if raised by RtlRaiseException @@ -3355,8 +3370,13 @@ static void run_rtlraiseexception_test(DWORD exceptioncode) rtlraiseexception_teb_handler_called = 0; rtlraiseexception_unhandled_handler_called = 0; func(pRtlRaiseException, &record); - ok( record.ExceptionAddress == (char *)code_mem + 0x0c, - "address set to %p instead of %p\n", record.ExceptionAddress, (char *)code_mem + 0x0c ); + if (is_arm64ec) /* addr points to RtlRaiseException entry thunk */ + ok( ((ULONG *)record.ExceptionAddress)[-1] == 0xd63f0120 /* blr x9 */, + "ExceptionAddress not in entry thunk %p (ntdll+%Ix)\n", + record.ExceptionAddress, (char *)record.ExceptionAddress - (char *)hntdll ); + else + 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" );