From 42cebcca3cf8220e5dfffecc99d51ded972c54d6 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 4 Mar 2024 13:18:44 +0100 Subject: [PATCH] ntdll: Use the correct structure for non-volatile registers on ARM64. --- dlls/ntdll/signal_arm64.c | 16 +++++++++++----- dlls/ntdll/tests/exception.c | 14 +++++++++++++- include/winnt.h | 16 ++++++++++++++++ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 192bcdce83d..e6e59712530 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -147,13 +147,19 @@ __ASM_GLOBAL_FUNC( RtlCaptureContext, */ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEXT *context ) { + DISPATCHER_CONTEXT_NONVOLREG_ARM64 *nonvol_regs; DWORD64 pc = context->Pc; + int i; dispatch->ScopeIndex = 0; dispatch->ControlPc = pc; dispatch->ControlPcIsUnwound = (context->ContextFlags & CONTEXT_UNWOUND_TO_CALL) != 0; if (dispatch->ControlPcIsUnwound) pc -= 4; + nonvol_regs = (DISPATCHER_CONTEXT_NONVOLREG_ARM64 *)dispatch->NonVolatileRegisters; + memcpy( nonvol_regs->GpNvRegs, &context->X19, sizeof(nonvol_regs->GpNvRegs) ); + for (i = 0; i < 8; i++) nonvol_regs->FpNvRegs[i] = context->V[i + 8].D[0]; + dispatch->FunctionEntry = RtlLookupFunctionEntry( pc, &dispatch->ImageBase, dispatch->HistoryTable ); if (RtlVirtualUnwind2( type, dispatch->ImageBase, pc, dispatch->FunctionEntry, context, @@ -334,17 +340,17 @@ static DWORD call_teb_handler( EXCEPTION_RECORD *rec, CONTEXT *context, DISPATCH NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) { EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList; + DISPATCHER_CONTEXT_NONVOLREG_ARM64 nonvol_regs; UNWIND_HISTORY_TABLE table; DISPATCHER_CONTEXT dispatch; - CONTEXT context, prev_context; + CONTEXT context; NTSTATUS status; context = *orig_context; dispatch.TargetPc = 0; dispatch.ContextRecord = &context; dispatch.HistoryTable = &table; - prev_context = context; - dispatch.NonVolatileRegisters = (BYTE *)&prev_context.X19; + dispatch.NonVolatileRegisters = nonvol_regs.Buffer; for (;;) { @@ -424,7 +430,6 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) } if (context.Sp == (ULONG64)NtCurrentTeb()->Tib.StackBase) break; - prev_context = context; } return STATUS_UNHANDLED_EXCEPTION; } @@ -628,6 +633,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec PVOID retval, CONTEXT *context, UNWIND_HISTORY_TABLE *table ) { EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList; + DISPATCHER_CONTEXT_NONVOLREG_ARM64 nonvol_regs; EXCEPTION_RECORD record; DISPATCHER_CONTEXT dispatch; CONTEXT new_context; @@ -659,7 +665,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec dispatch.TargetPc = (ULONG64)target_ip; dispatch.ContextRecord = context; dispatch.HistoryTable = table; - dispatch.NonVolatileRegisters = (BYTE *)&context->X19; + dispatch.NonVolatileRegisters = nonvol_regs.Buffer; for (;;) { diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 0fece1e7243..e6add6dd60e 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -7127,8 +7127,20 @@ static DWORD WINAPI rtlraiseexception_teb_handler( EXCEPTION_RECORD *rec, } static DWORD WINAPI rtlraiseexception_handler( EXCEPTION_RECORD *rec, void *frame, - CONTEXT *context, void *dispatcher ) + CONTEXT *context, DISPATCHER_CONTEXT *dispatcher ) { + DISPATCHER_CONTEXT_NONVOLREG_ARM64 *nonvol_regs = (void *)dispatcher->NonVolatileRegisters; + int i; + + for (i = 0; i < NONVOL_INT_NUMREG_ARM64; i++) + ok( nonvol_regs->GpNvRegs[i] == ((DWORD64 *)&context->X19)[i], + "wrong non volatile reg x%u %I64x / %I64x\n", i + 19, + nonvol_regs->GpNvRegs[i] , ((DWORD64 *)&context->X19)[i] ); + for (i = 0; i < NONVOL_FP_NUMREG_ARM64; i++) + ok( nonvol_regs->FpNvRegs[i] == context->V[i + 8].D[0], + "wrong non volatile reg d%u %g / %g\n", i + 8, + nonvol_regs->FpNvRegs[i] , context->V[i + 8].D[0] ); + rtlraiseexception_handler_called = 1; rtlraiseexception_handler_(rec, frame, context, dispatcher, FALSE); return ExceptionContinueSearch; diff --git a/include/winnt.h b/include/winnt.h index beac6efebd7..7adbc1d3761 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -2013,6 +2013,22 @@ typedef struct _DISPATCHER_CONTEXT_ARM64 PBYTE NonVolatileRegisters; } DISPATCHER_CONTEXT_ARM64, *PDISPATCHER_CONTEXT_ARM64; +#define NONVOL_INT_NUMREG_ARM64 11 +#define NONVOL_FP_NUMREG_ARM64 8 + +#define NONVOL_INT_SIZE_ARM64 (NONVOL_INT_NUMREG_ARM64 * sizeof(DWORD64)) +#define NONVOL_FP_SIZE_ARM64 (NONVOL_FP_NUMREG_ARM64 * sizeof(double)) + +typedef union _DISPATCHER_CONTEXT_NONVOLREG_ARM64 +{ + BYTE Buffer[NONVOL_INT_SIZE_ARM64 + NONVOL_FP_SIZE_ARM64]; + struct + { + DWORD64 GpNvRegs[NONVOL_INT_NUMREG_ARM64]; + double FpNvRegs[NONVOL_FP_NUMREG_ARM64]; + } DUMMYSTRUCTNAME; +} DISPATCHER_CONTEXT_NONVOLREG_ARM64; + #ifdef __x86_64__ typedef struct _DISPATCHER_CONTEXT