ntdll: Add a helper function for calling RtlVirtualUnwind() on x86-64.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
a9755d286e
commit
2002c22afa
|
@ -1591,6 +1591,73 @@ static NTSTATUS libunwind_virtual_unwind( ULONG64 ip, BOOL* got_info, ULONG64 *f
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* virtual_unwind
|
||||||
|
*/
|
||||||
|
static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEXT *context )
|
||||||
|
{
|
||||||
|
LDR_MODULE *module;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
dispatch->ImageBase = 0;
|
||||||
|
dispatch->ScopeIndex = 0;
|
||||||
|
dispatch->ControlPc = context->Rip;
|
||||||
|
|
||||||
|
/* first look for PE exception information */
|
||||||
|
|
||||||
|
if ((dispatch->FunctionEntry = lookup_function_info( context->Rip, &dispatch->ImageBase, &module )))
|
||||||
|
{
|
||||||
|
dispatch->LanguageHandler = RtlVirtualUnwind( type, dispatch->ImageBase, context->Rip,
|
||||||
|
dispatch->FunctionEntry, context,
|
||||||
|
&dispatch->HandlerData, &dispatch->EstablisherFrame,
|
||||||
|
NULL );
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* then look for host system exception information */
|
||||||
|
|
||||||
|
if (!module || (module->Flags & LDR_WINE_INTERNAL))
|
||||||
|
{
|
||||||
|
BOOL got_info = FALSE;
|
||||||
|
struct dwarf_eh_bases bases;
|
||||||
|
const struct dwarf_fde *fde = _Unwind_Find_FDE( (void *)(context->Rip - 1), &bases );
|
||||||
|
|
||||||
|
if (fde)
|
||||||
|
{
|
||||||
|
status = dwarf_virtual_unwind( context->Rip, &dispatch->EstablisherFrame, context, fde,
|
||||||
|
&bases, &dispatch->LanguageHandler, &dispatch->HandlerData );
|
||||||
|
if (status != STATUS_SUCCESS) return status;
|
||||||
|
got_info = TRUE;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_LIBUNWIND_H
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = libunwind_virtual_unwind( context->Rip, &got_info, &dispatch->EstablisherFrame,
|
||||||
|
context, &dispatch->LanguageHandler, &dispatch->HandlerData );
|
||||||
|
if (status != STATUS_SUCCESS) return status;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (got_info)
|
||||||
|
{
|
||||||
|
if (dispatch->LanguageHandler && !module)
|
||||||
|
{
|
||||||
|
FIXME( "calling personality routine in system library not supported yet\n" );
|
||||||
|
dispatch->LanguageHandler = NULL;
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else WARN( "exception data not found in %s\n", debugstr_w(module->BaseDllName.Buffer) );
|
||||||
|
|
||||||
|
/* no exception information, treat as a leaf function */
|
||||||
|
|
||||||
|
dispatch->EstablisherFrame = context->Rsp;
|
||||||
|
dispatch->LanguageHandler = NULL;
|
||||||
|
context->Rip = *(ULONG64 *)context->Rsp;
|
||||||
|
context->Rsp = context->Rsp + sizeof(ULONG64);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* dispatch_signal
|
* dispatch_signal
|
||||||
*/
|
*/
|
||||||
|
@ -2538,7 +2605,6 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex
|
||||||
UNWIND_HISTORY_TABLE table;
|
UNWIND_HISTORY_TABLE table;
|
||||||
DISPATCHER_CONTEXT dispatch;
|
DISPATCHER_CONTEXT dispatch;
|
||||||
CONTEXT context;
|
CONTEXT context;
|
||||||
LDR_MODULE *module;
|
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
context = *orig_context;
|
context = *orig_context;
|
||||||
|
@ -2547,64 +2613,8 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex
|
||||||
dispatch.HistoryTable = &table;
|
dispatch.HistoryTable = &table;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
/* FIXME: should use the history table to make things faster */
|
status = virtual_unwind( UNW_FLAG_EHANDLER, &dispatch, &context );
|
||||||
|
if (status != STATUS_SUCCESS) return status;
|
||||||
dispatch.ImageBase = 0;
|
|
||||||
dispatch.ControlPc = context.Rip;
|
|
||||||
dispatch.ScopeIndex = 0;
|
|
||||||
|
|
||||||
/* first look for PE exception information */
|
|
||||||
|
|
||||||
if ((dispatch.FunctionEntry = lookup_function_info( dispatch.ControlPc, &dispatch.ImageBase, &module )))
|
|
||||||
{
|
|
||||||
dispatch.LanguageHandler = RtlVirtualUnwind( UNW_FLAG_EHANDLER, dispatch.ImageBase,
|
|
||||||
dispatch.ControlPc, dispatch.FunctionEntry,
|
|
||||||
&context, &dispatch.HandlerData,
|
|
||||||
&dispatch.EstablisherFrame, NULL );
|
|
||||||
goto unwind_done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* then look for host system exception information */
|
|
||||||
|
|
||||||
if (!module || (module->Flags & LDR_WINE_INTERNAL))
|
|
||||||
{
|
|
||||||
BOOL got_info = FALSE;
|
|
||||||
struct dwarf_eh_bases bases;
|
|
||||||
const struct dwarf_fde *fde = _Unwind_Find_FDE( (void *)(dispatch.ControlPc - 1), &bases );
|
|
||||||
|
|
||||||
if (fde)
|
|
||||||
{
|
|
||||||
status = dwarf_virtual_unwind( dispatch.ControlPc, &dispatch.EstablisherFrame, &context,
|
|
||||||
fde, &bases, &dispatch.LanguageHandler, &dispatch.HandlerData );
|
|
||||||
if (status != STATUS_SUCCESS) return status;
|
|
||||||
got_info = TRUE;
|
|
||||||
}
|
|
||||||
#ifdef HAVE_LIBUNWIND_H
|
|
||||||
else
|
|
||||||
{
|
|
||||||
status = libunwind_virtual_unwind( dispatch.ControlPc, &got_info, &dispatch.EstablisherFrame, &context,
|
|
||||||
&dispatch.LanguageHandler, &dispatch.HandlerData );
|
|
||||||
if (status != STATUS_SUCCESS) return status;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (got_info)
|
|
||||||
{
|
|
||||||
dispatch.FunctionEntry = NULL;
|
|
||||||
if (dispatch.LanguageHandler && !module)
|
|
||||||
{
|
|
||||||
FIXME( "calling personality routine in system library not supported yet\n" );
|
|
||||||
dispatch.LanguageHandler = NULL;
|
|
||||||
}
|
|
||||||
goto unwind_done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else WARN( "exception data not found in %s\n", debugstr_w(module->BaseDllName.Buffer) );
|
|
||||||
|
|
||||||
context.Rip = *(ULONG64 *)context.Rsp;
|
|
||||||
context.Rsp = context.Rsp + sizeof(ULONG64);
|
|
||||||
dispatch.EstablisherFrame = context.Rsp;
|
|
||||||
dispatch.LanguageHandler = NULL;
|
|
||||||
|
|
||||||
unwind_done:
|
unwind_done:
|
||||||
if (!dispatch.EstablisherFrame) break;
|
if (!dispatch.EstablisherFrame) break;
|
||||||
|
@ -3840,7 +3850,6 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
|
||||||
EXCEPTION_RECORD record;
|
EXCEPTION_RECORD record;
|
||||||
DISPATCHER_CONTEXT dispatch;
|
DISPATCHER_CONTEXT dispatch;
|
||||||
CONTEXT new_context;
|
CONTEXT new_context;
|
||||||
LDR_MODULE *module;
|
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
DWORD i;
|
DWORD i;
|
||||||
|
|
||||||
|
@ -3880,66 +3889,8 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
/* FIXME: should use the history table to make things faster */
|
status = virtual_unwind( UNW_FLAG_UHANDLER, &dispatch, &new_context );
|
||||||
|
if (status != STATUS_SUCCESS) raise_status( status, rec );
|
||||||
dispatch.ImageBase = 0;
|
|
||||||
dispatch.ScopeIndex = 0;
|
|
||||||
dispatch.ControlPc = context->Rip;
|
|
||||||
|
|
||||||
/* first look for PE exception information */
|
|
||||||
|
|
||||||
if ((dispatch.FunctionEntry = lookup_function_info( context->Rip, &dispatch.ImageBase, &module )))
|
|
||||||
{
|
|
||||||
dispatch.LanguageHandler = RtlVirtualUnwind( UNW_FLAG_UHANDLER, dispatch.ImageBase,
|
|
||||||
context->Rip, dispatch.FunctionEntry,
|
|
||||||
&new_context, &dispatch.HandlerData,
|
|
||||||
&dispatch.EstablisherFrame, NULL );
|
|
||||||
goto unwind_done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* then look for host system exception information */
|
|
||||||
|
|
||||||
if (!module || (module->Flags & LDR_WINE_INTERNAL))
|
|
||||||
{
|
|
||||||
BOOL got_info = FALSE;
|
|
||||||
struct dwarf_eh_bases bases;
|
|
||||||
const struct dwarf_fde *fde = _Unwind_Find_FDE( (void *)(context->Rip - 1), &bases );
|
|
||||||
|
|
||||||
if (fde)
|
|
||||||
{
|
|
||||||
status = dwarf_virtual_unwind( context->Rip, &dispatch.EstablisherFrame, &new_context, fde,
|
|
||||||
&bases, &dispatch.LanguageHandler, &dispatch.HandlerData );
|
|
||||||
if (status != STATUS_SUCCESS) raise_status( status, rec );
|
|
||||||
got_info = TRUE;
|
|
||||||
}
|
|
||||||
#ifdef HAVE_LIBUNWIND_H
|
|
||||||
else
|
|
||||||
{
|
|
||||||
status = libunwind_virtual_unwind( context->Rip, &got_info, &dispatch.EstablisherFrame, &new_context,
|
|
||||||
&dispatch.LanguageHandler, &dispatch.HandlerData );
|
|
||||||
if (status != STATUS_SUCCESS) raise_status( status, rec );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (got_info)
|
|
||||||
{
|
|
||||||
dispatch.FunctionEntry = NULL;
|
|
||||||
if (dispatch.LanguageHandler && !module)
|
|
||||||
{
|
|
||||||
FIXME( "calling personality routine in system library not supported yet\n" );
|
|
||||||
dispatch.LanguageHandler = NULL;
|
|
||||||
}
|
|
||||||
goto unwind_done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else WARN( "exception data not found in %s\n", debugstr_w(module->BaseDllName.Buffer) );
|
|
||||||
|
|
||||||
/* no exception information, treat as a leaf function */
|
|
||||||
|
|
||||||
new_context.Rip = *(ULONG64 *)context->Rsp;
|
|
||||||
new_context.Rsp = context->Rsp + sizeof(ULONG64);
|
|
||||||
dispatch.EstablisherFrame = context->Rsp;
|
|
||||||
dispatch.LanguageHandler = NULL;
|
|
||||||
|
|
||||||
unwind_done:
|
unwind_done:
|
||||||
if (!dispatch.EstablisherFrame) break;
|
if (!dispatch.EstablisherFrame) break;
|
||||||
|
@ -4170,7 +4121,6 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
|
||||||
UNWIND_HISTORY_TABLE table;
|
UNWIND_HISTORY_TABLE table;
|
||||||
DISPATCHER_CONTEXT dispatch;
|
DISPATCHER_CONTEXT dispatch;
|
||||||
CONTEXT context;
|
CONTEXT context;
|
||||||
LDR_MODULE *module;
|
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
USHORT num_entries = 0;
|
USHORT num_entries = 0;
|
||||||
|
@ -4184,59 +4134,9 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer,
|
||||||
if (hash) *hash = 0;
|
if (hash) *hash = 0;
|
||||||
for (i = 0; i < skip + count; i++)
|
for (i = 0; i < skip + count; i++)
|
||||||
{
|
{
|
||||||
/* FIXME: should use the history table to make things faster */
|
status = virtual_unwind( UNW_FLAG_NHANDLER, &dispatch, &context );
|
||||||
|
if (status != STATUS_SUCCESS) return i;
|
||||||
|
|
||||||
dispatch.ImageBase = 0;
|
|
||||||
dispatch.ControlPc = context.Rip;
|
|
||||||
dispatch.ScopeIndex = 0;
|
|
||||||
|
|
||||||
/* first look for PE exception information */
|
|
||||||
|
|
||||||
if ((dispatch.FunctionEntry = lookup_function_info( dispatch.ControlPc, &dispatch.ImageBase, &module )))
|
|
||||||
{
|
|
||||||
RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase, dispatch.ControlPc,
|
|
||||||
dispatch.FunctionEntry, &context, &dispatch.HandlerData,
|
|
||||||
&dispatch.EstablisherFrame, NULL );
|
|
||||||
goto unwind_done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* then look for host system exception information */
|
|
||||||
|
|
||||||
if (!module || (module->Flags & LDR_WINE_INTERNAL))
|
|
||||||
{
|
|
||||||
BOOL got_info = FALSE;
|
|
||||||
struct dwarf_eh_bases bases;
|
|
||||||
const struct dwarf_fde *fde = _Unwind_Find_FDE( (void *)(dispatch.ControlPc - 1), &bases );
|
|
||||||
|
|
||||||
if (fde)
|
|
||||||
{
|
|
||||||
status = dwarf_virtual_unwind( dispatch.ControlPc, &dispatch.EstablisherFrame, &context,
|
|
||||||
fde, &bases, &dispatch.LanguageHandler, &dispatch.HandlerData );
|
|
||||||
if (status != STATUS_SUCCESS) return status;
|
|
||||||
got_info = TRUE;
|
|
||||||
}
|
|
||||||
#ifdef HAVE_LIBUNWIND_H
|
|
||||||
else
|
|
||||||
{
|
|
||||||
status = libunwind_virtual_unwind( dispatch.ControlPc, &got_info, &dispatch.EstablisherFrame, &context,
|
|
||||||
&dispatch.LanguageHandler, &dispatch.HandlerData );
|
|
||||||
if (status != STATUS_SUCCESS) return i;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (got_info)
|
|
||||||
{
|
|
||||||
dispatch.FunctionEntry = NULL;
|
|
||||||
goto unwind_done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else WARN( "exception data not found in %s\n", debugstr_w(module->BaseDllName.Buffer) );
|
|
||||||
|
|
||||||
context.Rip = *(ULONG64 *)context.Rsp;
|
|
||||||
context.Rsp = context.Rsp + sizeof(ULONG64);
|
|
||||||
dispatch.EstablisherFrame = context.Rsp;
|
|
||||||
|
|
||||||
unwind_done:
|
|
||||||
if (!dispatch.EstablisherFrame) break;
|
if (!dispatch.EstablisherFrame) break;
|
||||||
|
|
||||||
if ((dispatch.EstablisherFrame & 7) ||
|
if ((dispatch.EstablisherFrame & 7) ||
|
||||||
|
|
Loading…
Reference in New Issue