From b2c573c7d371f760d92b7490fd1aca002e2f18c6 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Tue, 26 Oct 2021 19:07:26 +0300 Subject: [PATCH] ntdll: Don't use Wine frames during exception processing on x64. CW-Bug-ID: #19570 --- dlls/ntdll/signal_x86_64.c | 65 +++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index b1ab4933b93..3d163fbc6ea 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -347,15 +347,32 @@ __ASM_GLOBAL_FUNC( RtlCaptureContext, "fxsave 0x100(%rcx)\n\t" /* context->FltSave */ "ret" ); -static DWORD __cdecl nested_exception_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame, +DWORD __cdecl nested_exception_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame, CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher ) { + TRACE( "exception flags %#x.\n", rec->ExceptionFlags ); + if (!(rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))) - rec->ExceptionFlags |= EH_NESTED_CALL; + return ExceptionNestedException; return ExceptionContinueSearch; } +/*********************************************************************** + * exception_handler_call_wrapper + */ +DWORD exception_handler_call_wrapper( EXCEPTION_RECORD *rec, void *frame, + CONTEXT *context, DISPATCHER_CONTEXT *dispatch ); +__ASM_GLOBAL_FUNC( exception_handler_call_wrapper, + __ASM_SEH(".seh_endprologue\n\t") + "subq $0x28, %rsp\n\t" + __ASM_SEH(".seh_stackalloc 0x28\n\t") + __ASM_SEH(".seh_handler nested_exception_handler, @except\n\t") + "callq *0x30(%r9)\n\t" /* dispatch->LanguageHandler */ + "nop\n\t" + "addq $0x28, %rsp\n\t" + "ret" ); + /********************************************************************** * call_handler * @@ -364,19 +381,19 @@ static DWORD __cdecl nested_exception_handler( EXCEPTION_RECORD *rec, EXCEPTION_ */ static DWORD call_handler( EXCEPTION_RECORD *rec, CONTEXT *context, DISPATCHER_CONTEXT *dispatch ) { - EXCEPTION_REGISTRATION_RECORD frame; DWORD res; - frame.Handler = nested_exception_handler; - __wine_push_frame( &frame ); - TRACE_(seh)( "calling handler %p (rec=%p, frame=%p context=%p, dispatch=%p)\n", dispatch->LanguageHandler, rec, (void *)dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch ); - res = dispatch->LanguageHandler( rec, (void *)dispatch->EstablisherFrame, context, dispatch ); + res = exception_handler_call_wrapper( rec, (void *)dispatch->EstablisherFrame, context, dispatch ); TRACE_(seh)( "handler at %p returned %u\n", dispatch->LanguageHandler, res ); rec->ExceptionFlags &= EH_NONCONTINUABLE; - __wine_pop_frame( &frame ); + if (res == ExceptionNestedException) + { + rec->ExceptionFlags |= EH_NESTED_CALL; + res = ExceptionContinueSearch; + } return res; } @@ -990,7 +1007,8 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc, struct unwind_exception_frame { - EXCEPTION_REGISTRATION_RECORD frame; + BYTE dummy[0x28]; + void *rip; DISPATCHER_CONTEXT *dispatch; }; @@ -999,7 +1017,7 @@ struct unwind_exception_frame * * Handler for exceptions happening while calling an unwind handler. */ -static DWORD __cdecl unwind_exception_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame, +DWORD __cdecl unwind_exception_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame, CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher ) { struct unwind_exception_frame *unwind_frame = (struct unwind_exception_frame *)frame; @@ -1019,27 +1037,36 @@ static DWORD __cdecl unwind_exception_handler( EXCEPTION_RECORD *rec, EXCEPTION_ return ExceptionCollidedUnwind; } +/*********************************************************************** + * exception_handler_call_wrapper + */ +DWORD unwind_handler_call_wrapper( EXCEPTION_RECORD *rec, void *frame, + CONTEXT *context, DISPATCHER_CONTEXT *dispatch ); +__ASM_GLOBAL_FUNC( unwind_handler_call_wrapper, + __ASM_SEH(".seh_endprologue\n\t") + "movq %r9, 0x8(%rsp)\n\t" + "subq $0x28, %rsp\n\t" + __ASM_SEH(".seh_stackalloc 0x28\n\t") + __ASM_SEH(".seh_handler unwind_exception_handler, @except, @unwind\n\t") + "callq *0x30(%r9)\n\t" /* dispatch->LanguageHandler */ + "nop\n\t" + "addq $0x28, %rsp\n\t" + "ret" ); + /********************************************************************** * call_unwind_handler * * Call a single unwind handler. */ -static DWORD call_unwind_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch ) +DWORD call_unwind_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch ) { - struct unwind_exception_frame frame; DWORD res; - frame.frame.Handler = unwind_exception_handler; - frame.dispatch = dispatch; - __wine_push_frame( &frame.frame ); - TRACE( "calling handler %p (rec=%p, frame=%p context=%p, dispatch=%p)\n", dispatch->LanguageHandler, rec, (void *)dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch ); - res = dispatch->LanguageHandler( rec, (void *)dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch ); + res = unwind_handler_call_wrapper( rec, (void *)dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch ); TRACE( "handler %p returned %x\n", dispatch->LanguageHandler, res ); - __wine_pop_frame( &frame.frame ); - switch (res) { case ExceptionContinueSearch: -- 2.35.1