Module: wine Branch: master Commit: 5f890e3ce9b8119cef1a8a8a84aa37e525753514 URL: https://gitlab.winehq.org/wine/wine/-/commit/5f890e3ce9b8119cef1a8a8a84aa37e...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Mar 5 10:54:47 2024 +0100
ntdll: Use a common wrapper to call unwind handlers on ARM64.
---
dlls/ntdll/signal_arm64.c | 118 ++++++++++++++++------------------------------ 1 file changed, 40 insertions(+), 78 deletions(-)
diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index d48c65a5f36..32aca81b198 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -200,82 +200,22 @@ EXCEPTION_DISPOSITION WINAPI unwind_exception_handler( EXCEPTION_RECORD *record, return ExceptionCollidedUnwind; }
+ /********************************************************************** - * unwind_handler_wrapper + * call_unwind_handler */ -extern DWORD WINAPI unwind_handler_wrapper( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch ); -__ASM_GLOBAL_FUNC( unwind_handler_wrapper, +DWORD WINAPI call_unwind_handler( EXCEPTION_RECORD *rec, ULONG_PTR frame, + CONTEXT *context, void *dispatch, PEXCEPTION_ROUTINE handler ); +__ASM_GLOBAL_FUNC( call_unwind_handler, "stp x29, x30, [sp, #-32]!\n\t" ".seh_save_fplr_x 32\n\t" - "mov x29, sp\n\t" - ".seh_set_fp\n\t" ".seh_endprologue\n\t" - ".seh_handler " __ASM_NAME("unwind_exception_handler") ", @except, @unwind\n\t" - "str x1, [sp, #16]\n\t" /* frame[-2] = dispatch */ - "mov x3, x1\n\t" - "ldr x1, [x3, #0x18]\n\t" /* dispatch->EstablisherFrame */ - "ldr x2, [x3, #0x28]\n\t" /* dispatch->ContextRecord */ - "ldr x15, [x3, #0x30]\n\t" /* dispatch->LanguageHandler */ - "blr x15\n\t" + ".seh_handler unwind_exception_handler, @except\n\t" + "str x3, [sp, #16]\n\t" /* frame[-2] = dispatch */ + "blr x4\n\t" "ldp x29, x30, [sp], #32\n\t" "ret" )
-/********************************************************************** - * call_unwind_handler - * - * Call a single unwind handler. - */ -static DWORD call_unwind_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch ) -{ - DWORD res; - - TRACE( "calling handler %p (rec=%p, frame=%I64x context=%p, dispatch=%p)\n", - dispatch->LanguageHandler, rec, dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch ); - res = unwind_handler_wrapper( rec, dispatch ); - TRACE( "handler %p returned %lx\n", dispatch->LanguageHandler, res ); - - switch (res) - { - case ExceptionContinueSearch: - case ExceptionCollidedUnwind: - break; - default: - raise_status( STATUS_INVALID_DISPOSITION, rec ); - break; - } - - return res; -} - - -/********************************************************************** - * call_teb_unwind_handler - * - * Call a single unwind handler from the TEB chain. - */ -static DWORD call_teb_unwind_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch, - EXCEPTION_REGISTRATION_RECORD *teb_frame ) -{ - DWORD res; - - TRACE( "calling TEB handler %p (rec=%p, frame=%p context=%p, dispatch=%p)\n", - teb_frame->Handler, rec, teb_frame, dispatch->ContextRecord, dispatch ); - res = teb_frame->Handler( rec, teb_frame, dispatch->ContextRecord, (EXCEPTION_REGISTRATION_RECORD**)dispatch ); - TRACE( "handler at %p returned %lu\n", teb_frame->Handler, res ); - - switch (res) - { - case ExceptionContinueSearch: - case ExceptionCollidedUnwind: - break; - default: - raise_status( STATUS_INVALID_DISPOSITION, rec ); - break; - } - - return res; -} -
/*********************************************************************** * call_seh_handler @@ -601,7 +541,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec CONTEXT new_context; NTSTATUS status; ULONG_PTR frame; - DWORD i; + DWORD i, res;
RtlCaptureContext( context ); new_context = *context; @@ -654,8 +594,20 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec raise_status( STATUS_INVALID_UNWIND_TARGET, rec ); } if (dispatch.EstablisherFrame == (ULONG64)end_frame) rec->ExceptionFlags |= EXCEPTION_TARGET_UNWIND; - if (call_unwind_handler( rec, &dispatch ) == ExceptionCollidedUnwind) + + TRACE( "calling handler %p (rec=%p, frame=%I64x context=%p, dispatch=%p)\n", + dispatch.LanguageHandler, rec, dispatch.EstablisherFrame, + dispatch.ContextRecord, &dispatch ); + res = call_unwind_handler( rec, dispatch.EstablisherFrame, dispatch.ContextRecord, + &dispatch, dispatch.LanguageHandler ); + TRACE( "handler %p returned %lx\n", dispatch.LanguageHandler, res ); + + switch (res) { + case ExceptionContinueSearch: + rec->ExceptionFlags &= ~EXCEPTION_COLLIDED_UNWIND; + break; + case ExceptionCollidedUnwind: new_context = *context; RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, dispatch.ControlPc, dispatch.FunctionEntry, @@ -663,21 +615,30 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec NULL ); rec->ExceptionFlags |= EXCEPTION_COLLIDED_UNWIND; goto unwind_done; + default: + raise_status( STATUS_INVALID_DISPOSITION, rec ); + break; } - rec->ExceptionFlags &= ~EXCEPTION_COLLIDED_UNWIND; } else /* hack: call builtin handlers registered in the tib list */ { - DWORD64 backup_frame = dispatch.EstablisherFrame; while (is_valid_frame( (ULONG_PTR)teb_frame ) && (ULONG64)teb_frame < new_context.Sp && (ULONG64)teb_frame < (ULONG64)end_frame) { - TRACE( "found builtin frame %p handler %p\n", teb_frame, teb_frame->Handler ); - dispatch.EstablisherFrame = (ULONG64)teb_frame; - if (call_teb_unwind_handler( rec, &dispatch, teb_frame ) == ExceptionCollidedUnwind) + TRACE( "calling TEB handler %p (rec=%p, frame=%p context=%p, dispatch=%p)\n", + teb_frame->Handler, rec, teb_frame, dispatch.ContextRecord, &dispatch ); + res = call_unwind_handler( rec, (ULONG_PTR)teb_frame, dispatch.ContextRecord, &dispatch, + (PEXCEPTION_ROUTINE)teb_frame->Handler ); + TRACE( "handler at %p returned %lu\n", teb_frame->Handler, res ); + teb_frame = __wine_pop_frame( teb_frame ); + + switch (res) { - teb_frame = __wine_pop_frame( teb_frame ); + case ExceptionContinueSearch: + rec->ExceptionFlags &= ~EXCEPTION_COLLIDED_UNWIND; + break; + case ExceptionCollidedUnwind: new_context = *context; RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, dispatch.ControlPc, dispatch.FunctionEntry, @@ -685,11 +646,12 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec &frame, NULL ); rec->ExceptionFlags |= EXCEPTION_COLLIDED_UNWIND; goto unwind_done; + default: + raise_status( STATUS_INVALID_DISPOSITION, rec ); + break; } - teb_frame = __wine_pop_frame( teb_frame ); } if ((ULONG64)teb_frame == (ULONG64)end_frame && (ULONG64)end_frame < new_context.Sp) break; - dispatch.EstablisherFrame = backup_frame; }
if (dispatch.EstablisherFrame == (ULONG64)end_frame) break;