From 9e6903c4b32d7d2f49b6cf8fbe2fb2b76396607f Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 9 Apr 2010 13:15:41 +0200 Subject: [PATCH] ntdll: Restructure x86_64 exception processing to treat all functions with missing exception data as leaf functions. --- dlls/ntdll/signal_x86_64.c | 164 +++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 80 deletions(-) diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 59d1d6cd04b..4900b434681 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -1817,7 +1817,6 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex { EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList; UNWIND_HISTORY_TABLE table; - RUNTIME_FUNCTION *dir; DISPATCHER_CONTEXT dispatch; CONTEXT context, new_context; LDR_MODULE *module; @@ -1835,60 +1834,63 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex /* FIXME: should use the history table to make things faster */ - dir = NULL; module = NULL; dispatch.ImageBase = 0; + /* first look for PE exception information */ + if (!LdrFindEntryForAddress( (void *)context.Rip, &module )) { - if (!(dir = RtlImageDirectoryEntryToData( module->BaseAddress, TRUE, - IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size )) && - !(module->Flags & LDR_WINE_INTERNAL)) - { - ERR( "module %s doesn't contain exception data, can't dispatch exception\n", - debugstr_w(module->BaseDllName.Buffer) ); - break; - } + RUNTIME_FUNCTION *dir; + dispatch.ImageBase = (ULONG64)module->BaseAddress; + if ((dir = RtlImageDirectoryEntryToData( module->BaseAddress, TRUE, + IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size ))) + { + if ((dispatch.FunctionEntry = find_function_info( context.Rip, module->BaseAddress, + dir, size ))) + { + dispatch.LanguageHandler = RtlVirtualUnwind( UNW_FLAG_EHANDLER, dispatch.ImageBase, + context.Rip, dispatch.FunctionEntry, + &new_context, &dispatch.HandlerData, + &dispatch.EstablisherFrame, NULL ); + goto unwind_done; + } + } + else if (!(module->Flags & LDR_WINE_INTERNAL)) + WARN( "exception data not found in %s\n", debugstr_w(module->BaseDllName.Buffer) ); } - if (!dir) + /* then look for host system exception information */ + + if (!module || (module->Flags & LDR_WINE_INTERNAL)) { struct dwarf_eh_bases bases; const struct dwarf_fde *fde = _Unwind_Find_FDE( (void *)(context.Rip - 1), &bases ); - if (!fde) + + if (fde) { - /* assume leaf function */ - context.Rip = *(ULONG64 *)context.Rsp; - context.Rsp += sizeof(ULONG64); - continue; + status = dwarf_virtual_unwind( context.Rip, &dispatch.EstablisherFrame, &new_context, + fde, &bases, &dispatch.LanguageHandler, &dispatch.HandlerData ); + if (status != STATUS_SUCCESS) return status; + dispatch.FunctionEntry = NULL; + if (dispatch.LanguageHandler && !module) + { + FIXME( "calling personality routine in system library not supported yet\n" ); + dispatch.LanguageHandler = NULL; + } + goto unwind_done; } - status = dwarf_virtual_unwind( context.Rip, &dispatch.EstablisherFrame, &new_context, - fde, &bases, &dispatch.LanguageHandler, &dispatch.HandlerData ); - if (status != STATUS_SUCCESS) return status; - dispatch.FunctionEntry = NULL; - if (dispatch.LanguageHandler && !module) - { - FIXME( "calling personality routine in system library not supported yet\n" ); - dispatch.LanguageHandler = NULL; - } - } - else - { - if (!(dispatch.FunctionEntry = find_function_info( context.Rip, module->BaseAddress, - dir, size ))) - { - /* leaf function */ - context.Rip = *(ULONG64 *)context.Rsp; - context.Rsp += sizeof(ULONG64); - continue; - } - dispatch.LanguageHandler = RtlVirtualUnwind( UNW_FLAG_EHANDLER, dispatch.ImageBase, - context.Rip, dispatch.FunctionEntry, - &new_context, &dispatch.HandlerData, - &dispatch.EstablisherFrame, NULL ); } + /* no exception information, treat as a leaf function */ + + new_context.Rip = *(ULONG64 *)context.Rsp; + new_context.Rsp = context.Rsp + sizeof(ULONG64); + dispatch.EstablisherFrame = new_context.Rsp; + dispatch.LanguageHandler = NULL; + + unwind_done: if (!dispatch.EstablisherFrame) break; if ((dispatch.EstablisherFrame & 7) || @@ -2704,7 +2706,6 @@ void WINAPI RtlUnwindEx( ULONG64 end_frame, ULONG64 target_ip, EXCEPTION_RECORD { EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList; EXCEPTION_RECORD record; - RUNTIME_FUNCTION *dir; DISPATCHER_CONTEXT dispatch; CONTEXT context, new_context; LDR_MODULE *module; @@ -2747,61 +2748,64 @@ void WINAPI RtlUnwindEx( ULONG64 end_frame, ULONG64 target_ip, EXCEPTION_RECORD /* FIXME: should use the history table to make things faster */ - dir = NULL; module = NULL; dispatch.ImageBase = 0; dispatch.ScopeIndex = 0; /* FIXME */ + /* first look for PE exception information */ + if (!LdrFindEntryForAddress( (void *)context.Rip, &module )) { - if (!(dir = RtlImageDirectoryEntryToData( module->BaseAddress, TRUE, - IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size )) && - !(module->Flags & LDR_WINE_INTERNAL)) - { - ERR( "module %s doesn't contain exception data, can't unwind exception\n", - debugstr_w(module->BaseDllName.Buffer) ); - raise_status( STATUS_BAD_FUNCTION_TABLE, rec ); - } + RUNTIME_FUNCTION *dir; + dispatch.ImageBase = (ULONG64)module->BaseAddress; + if ((dir = RtlImageDirectoryEntryToData( module->BaseAddress, TRUE, + IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size ))) + { + if ((dispatch.FunctionEntry = find_function_info( context.Rip, module->BaseAddress, + dir, size ))) + { + dispatch.LanguageHandler = RtlVirtualUnwind( UNW_FLAG_UHANDLER, dispatch.ImageBase, + context.Rip, dispatch.FunctionEntry, + &new_context, &dispatch.HandlerData, + &dispatch.EstablisherFrame, NULL ); + goto unwind_done; + } + } + else if (!(module->Flags & LDR_WINE_INTERNAL)) + WARN( "exception data not found in %s\n", debugstr_w(module->BaseDllName.Buffer) ); } - if (!dir) + /* then look for host system exception information */ + + if (!module || (module->Flags & LDR_WINE_INTERNAL)) { struct dwarf_eh_bases bases; const struct dwarf_fde *fde = _Unwind_Find_FDE( (void *)(context.Rip - 1), &bases ); - if (!fde) + + if (fde) { - /* assume leaf function */ - context.Rip = *(ULONG64 *)context.Rsp; - context.Rsp += sizeof(ULONG64); - continue; + dispatch.FunctionEntry = NULL; + status = dwarf_virtual_unwind( context.Rip, &dispatch.EstablisherFrame, &new_context, fde, + &bases, &dispatch.LanguageHandler, &dispatch.HandlerData ); + if (status != STATUS_SUCCESS) raise_status( status, rec ); + if (dispatch.LanguageHandler && !module) + { + FIXME( "calling personality routine in system library not supported yet\n" ); + dispatch.LanguageHandler = NULL; + } + goto unwind_done; } - dispatch.FunctionEntry = NULL; - status = dwarf_virtual_unwind( context.Rip, &dispatch.EstablisherFrame, &new_context, fde, - &bases, &dispatch.LanguageHandler, &dispatch.HandlerData ); - if (status != STATUS_SUCCESS) raise_status( status, rec ); - if (dispatch.LanguageHandler && !module) - { - FIXME( "calling personality routine in system library not supported yet\n" ); - dispatch.LanguageHandler = NULL; - } - } - else - { - if (!(dispatch.FunctionEntry = find_function_info( context.Rip, module->BaseAddress, - dir, size ))) - { - /* leaf function */ - context.Rip = *(ULONG64 *)context.Rsp; - context.Rsp += sizeof(ULONG64); - continue; - } - dispatch.LanguageHandler = RtlVirtualUnwind( UNW_FLAG_UHANDLER, dispatch.ImageBase, - context.Rip, dispatch.FunctionEntry, - &new_context, &dispatch.HandlerData, - &dispatch.EstablisherFrame, NULL ); } + /* no exception information, treat as a leaf function */ + + new_context.Rip = *(ULONG64 *)context.Rsp; + new_context.Rsp = context.Rsp + sizeof(ULONG64); + dispatch.EstablisherFrame = new_context.Rsp; + dispatch.LanguageHandler = NULL; + + unwind_done: if (!dispatch.EstablisherFrame) break; if (is_inside_signal_stack( (void *)dispatch.EstablisherFrame ))