ntdll: Restructure x86_64 exception processing to treat all functions with missing exception data as leaf functions.

This commit is contained in:
Alexandre Julliard 2010-04-09 13:15:41 +02:00
parent 55fbf84d26
commit 9e6903c4b3
1 changed files with 84 additions and 80 deletions

View File

@ -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 ))