Module: wine Branch: master Commit: 0c35e9adce90562ecc5bf9869161e71a105a4b03 URL: https://gitlab.winehq.org/wine/wine/-/commit/0c35e9adce90562ecc5bf9869161e71...
Author: Alexandre Julliard julliard@winehq.org Date: Mon Mar 4 13:20:49 2024 +0100
ntdll: Use the correct structure for non-volatile registers on ARM.
---
dlls/ntdll/signal_arm.c | 27 ++++++++++++++++++++++----- dlls/ntdll/tests/exception.c | 14 +++++++++++++- 2 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index c7a036cefc0..4ae637fdcc4 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -69,6 +69,18 @@ static void dump_scope_table( ULONG base, const SCOPE_TABLE *table ) base + table->ScopeRecord[i].JumpTarget ); }
+/* undocumented, copied from the corresponding ARM64 structure */ +typedef union _DISPATCHER_CONTEXT_NONVOLREG_ARM +{ + BYTE Buffer[8 * sizeof(DWORD) + 8 * sizeof(double)]; + struct + { + DWORD GpNvRegs[8]; + double FpNvRegs[8]; + } DUMMYSTRUCTNAME; +} DISPATCHER_CONTEXT_NONVOLREG_ARM; + + /******************************************************************* * syscalls */ @@ -116,6 +128,7 @@ __ASM_GLOBAL_FUNC( RtlCaptureContext, */ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEXT *context ) { + DISPATCHER_CONTEXT_NONVOLREG_ARM *nonvol_regs; DWORD pc = context->Pc;
dispatch->ScopeIndex = 0; @@ -123,6 +136,10 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX dispatch->ControlPcIsUnwound = (context->ContextFlags & CONTEXT_UNWOUND_TO_CALL) != 0; if (dispatch->ControlPcIsUnwound) pc -= 2;
+ nonvol_regs = (DISPATCHER_CONTEXT_NONVOLREG_ARM *)dispatch->NonVolatileRegisters; + memcpy( nonvol_regs->GpNvRegs, &context->R4, sizeof(nonvol_regs->GpNvRegs) ); + memcpy( nonvol_regs->FpNvRegs, &context->D[8], sizeof(nonvol_regs->FpNvRegs) ); + dispatch->FunctionEntry = RtlLookupFunctionEntry( pc, (DWORD_PTR *)&dispatch->ImageBase, dispatch->HistoryTable ); if (RtlVirtualUnwind2( type, dispatch->ImageBase, pc, dispatch->FunctionEntry, context, @@ -297,17 +314,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_ARM 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.R4; + dispatch.NonVolatileRegisters = nonvol_regs.Buffer;
for (;;) { @@ -387,7 +404,6 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) }
if (context.Sp == (DWORD)NtCurrentTeb()->Tib.StackBase) break; - prev_context = context; } return STATUS_UNHANDLED_EXCEPTION; } @@ -541,6 +557,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_ARM nonvol_regs; EXCEPTION_RECORD record; DISPATCHER_CONTEXT dispatch; CONTEXT new_context; @@ -572,7 +589,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec dispatch.TargetPc = (ULONG_PTR)target_ip; dispatch.ContextRecord = context; dispatch.HistoryTable = table; - dispatch.NonVolatileRegisters = (BYTE *)&context->R4; + dispatch.NonVolatileRegisters = nonvol_regs.Buffer;
for (;;) { diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index e6add6dd60e..d33564e4800 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -6037,8 +6037,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 ) { + ULONG *nonvol_regs = (void *)dispatcher->NonVolatileRegisters; + int i; + + for (i = 0; i < 8; i++) + ok( nonvol_regs[i] == ((ULONG *)&context->R4)[i], + "wrong non volatile reg r%u %lx / %lx\n", i + 4, + nonvol_regs[i], ((ULONG *)&context->R4)[i] ); + for (i = 0; i < 8; i++) + ok( ((ULONGLONG *)(nonvol_regs + 8))[i] == context->D[i + 8], + "wrong non volatile reg d%u %I64x / %I64x\n", i + 8, + ((ULONGLONG *)(nonvol_regs + 8))[i], context->D[i + 8] ); + rtlraiseexception_handler_called = 1; rtlraiseexception_handler_(rec, frame, context, dispatcher, FALSE); return ExceptionContinueSearch;