ntdll: Use the correct structure for non-volatile registers on ARM64.

This commit is contained in:
Alexandre Julliard 2024-03-04 13:18:44 +01:00
parent a9671befc1
commit 42cebcca3c
3 changed files with 40 additions and 6 deletions

View file

@ -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 (;;)
{

View file

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

View file

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