Module: wine Branch: master Commit: 47f94fcf5f8e4be9fc418c2aa2cdf13b0d223ddc URL: https://gitlab.winehq.org/wine/wine/-/commit/47f94fcf5f8e4be9fc418c2aa2cdf13...
Author: Alexandre Julliard julliard@winehq.org Date: Mon Mar 25 18:04:37 2024 +0100
ntdll: Copy the context contents instead of the pointer on collided unwind.
Similar to how it's done on ARM platforms.
---
dlls/ntdll/signal_x86_64.c | 44 ++++++++++++-------------------------------- 1 file changed, 12 insertions(+), 32 deletions(-)
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 80636037cb7..6930f4df34e 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -210,6 +210,7 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) DISPATCHER_CONTEXT dispatch; CONTEXT context; NTSTATUS status; + ULONG_PTR frame;
context = *orig_context; context.ContextFlags &= ~0x40; /* Clear xstate flag. */ @@ -246,16 +247,10 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) rec->ExceptionFlags |= EXCEPTION_NESTED_CALL; TRACE( "nested exception\n" ); break; - case ExceptionCollidedUnwind: { - ULONG64 frame; - - context = *dispatch.ContextRecord; - dispatch.ContextRecord = &context; - RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, - dispatch.ControlPc, dispatch.FunctionEntry, - &context, NULL, &frame, NULL ); + case ExceptionCollidedUnwind: + RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, dispatch.ControlPc, + dispatch.FunctionEntry, &context, NULL, &frame, NULL ); goto unwind_done; - } default: return STATUS_INVALID_DISPOSITION; } @@ -277,17 +272,11 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) rec->ExceptionFlags |= EXCEPTION_NESTED_CALL; TRACE( "nested exception\n" ); break; - case ExceptionCollidedUnwind: { - ULONG64 frame; - - context = *dispatch.ContextRecord; - dispatch.ContextRecord = &context; - RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, - dispatch.ControlPc, dispatch.FunctionEntry, - &context, NULL, &frame, NULL ); + case ExceptionCollidedUnwind: + RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, dispatch.ControlPc, + dispatch.FunctionEntry, &context, NULL, &frame, NULL ); teb_frame = teb_frame->Prev; goto unwind_done; - } default: return STATUS_INVALID_DISPOSITION; } @@ -447,11 +436,12 @@ DWORD __cdecl unwind_exception_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTR dispatch->ImageBase = unwind_frame->dispatch->ImageBase; dispatch->FunctionEntry = unwind_frame->dispatch->FunctionEntry; dispatch->EstablisherFrame = unwind_frame->dispatch->EstablisherFrame; - dispatch->ContextRecord = unwind_frame->dispatch->ContextRecord; dispatch->LanguageHandler = unwind_frame->dispatch->LanguageHandler; dispatch->HandlerData = unwind_frame->dispatch->HandlerData; dispatch->HistoryTable = unwind_frame->dispatch->HistoryTable; dispatch->ScopeIndex = unwind_frame->dispatch->ScopeIndex; + *dispatch->ContextRecord = *unwind_frame->dispatch->ContextRecord; + dispatch->ContextRecord->ContextFlags &= ~0x40; TRACE( "detected collided unwind\n" ); return ExceptionCollidedUnwind; } @@ -728,6 +718,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec DISPATCHER_CONTEXT dispatch; CONTEXT new_context; NTSTATUS status; + ULONG_PTR frame; DWORD i;
RtlCaptureContext( context ); @@ -783,12 +774,7 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec if (dispatch.EstablisherFrame == (ULONG64)end_frame) rec->ExceptionFlags |= EXCEPTION_TARGET_UNWIND; if (call_unwind_handler( rec, &dispatch ) == ExceptionCollidedUnwind) { - ULONG64 frame; - - new_context = *dispatch.ContextRecord; - new_context.ContextFlags &= ~0x40; - *context = new_context; - dispatch.ContextRecord = context; + new_context = *context; RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, dispatch.ControlPc, dispatch.FunctionEntry, &new_context, NULL, &frame, NULL ); @@ -808,14 +794,8 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec dispatch.EstablisherFrame = (ULONG64)teb_frame; if (call_teb_unwind_handler( rec, &dispatch, teb_frame ) == ExceptionCollidedUnwind) { - ULONG64 frame; - teb_frame = __wine_pop_frame( teb_frame ); - - new_context = *dispatch.ContextRecord; - new_context.ContextFlags &= ~0x40; - *context = new_context; - dispatch.ContextRecord = context; + new_context = *context; RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, dispatch.ControlPc, dispatch.FunctionEntry, &new_context, NULL, &frame, NULL );