ntdll: Move RtlLookupFunctionEntry() to the CPU backends.
This commit is contained in:
parent
b9a985a677
commit
215a8e68d3
7 changed files with 155 additions and 113 deletions
|
@ -595,9 +595,41 @@ BOOLEAN CDECL RtlDeleteFunctionTable( RUNTIME_FUNCTION *table )
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* lookup_dynamic_function_table
|
||||
*/
|
||||
RUNTIME_FUNCTION *lookup_dynamic_function_table( ULONG_PTR pc, ULONG_PTR *base, ULONG *count )
|
||||
{
|
||||
struct dynamic_unwind_entry *entry;
|
||||
RUNTIME_FUNCTION *ret = NULL;
|
||||
|
||||
RtlEnterCriticalSection( &dynamic_unwind_section );
|
||||
LIST_FOR_EACH_ENTRY( entry, &dynamic_unwind_list, struct dynamic_unwind_entry, entry )
|
||||
{
|
||||
if (pc >= entry->base && pc < entry->end)
|
||||
{
|
||||
*base = entry->base;
|
||||
if (entry->callback)
|
||||
{
|
||||
ret = entry->callback( pc, entry->context );
|
||||
*count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = entry->table;
|
||||
*count = entry->count;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
RtlLeaveCriticalSection( &dynamic_unwind_section );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* helper for lookup_function_info() */
|
||||
static RUNTIME_FUNCTION *find_function_info( ULONG_PTR pc, ULONG_PTR base,
|
||||
RUNTIME_FUNCTION *func, ULONG size )
|
||||
RUNTIME_FUNCTION *find_function_info( ULONG_PTR pc, ULONG_PTR base,
|
||||
RUNTIME_FUNCTION *func, ULONG size )
|
||||
{
|
||||
int min = 0;
|
||||
int max = size - 1;
|
||||
|
@ -630,63 +662,6 @@ static RUNTIME_FUNCTION *find_function_info( ULONG_PTR pc, ULONG_PTR base,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* lookup_function_info
|
||||
*/
|
||||
RUNTIME_FUNCTION *lookup_function_info( ULONG_PTR pc, ULONG_PTR *base, LDR_DATA_TABLE_ENTRY **module )
|
||||
{
|
||||
RUNTIME_FUNCTION *func = NULL;
|
||||
struct dynamic_unwind_entry *entry;
|
||||
ULONG size;
|
||||
|
||||
/* PE module or wine module */
|
||||
if ((func = RtlLookupFunctionTable( pc, base, &size )))
|
||||
{
|
||||
func = find_function_info( pc, (ULONG_PTR)(*module)->DllBase, func, size/sizeof(*func) );
|
||||
}
|
||||
else
|
||||
{
|
||||
*module = NULL;
|
||||
|
||||
RtlEnterCriticalSection( &dynamic_unwind_section );
|
||||
LIST_FOR_EACH_ENTRY( entry, &dynamic_unwind_list, struct dynamic_unwind_entry, entry )
|
||||
{
|
||||
if (pc >= entry->base && pc < entry->end)
|
||||
{
|
||||
*base = entry->base;
|
||||
/* use callback or lookup in function table */
|
||||
if (entry->callback)
|
||||
func = entry->callback( pc, entry->context );
|
||||
else
|
||||
func = find_function_info( pc, entry->base, entry->table, entry->count );
|
||||
break;
|
||||
}
|
||||
}
|
||||
RtlLeaveCriticalSection( &dynamic_unwind_section );
|
||||
}
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* RtlLookupFunctionEntry (NTDLL.@)
|
||||
*/
|
||||
PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG_PTR pc, ULONG_PTR *base,
|
||||
UNWIND_HISTORY_TABLE *table )
|
||||
{
|
||||
LDR_DATA_TABLE_ENTRY *module;
|
||||
RUNTIME_FUNCTION *func;
|
||||
|
||||
/* FIXME: should use the history table to make things faster */
|
||||
|
||||
if (!(func = lookup_function_info( pc, base, &module )))
|
||||
{
|
||||
*base = 0;
|
||||
WARN( "no exception table found for %Ix\n", pc );
|
||||
}
|
||||
return func;
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ || __arm__ || __aarch64__ */
|
||||
|
||||
|
||||
|
|
|
@ -85,7 +85,8 @@ extern void WINAPI KiUserCallbackDispatcherReturn(void);
|
|||
extern void (WINAPI *pWow64PrepareForException)( EXCEPTION_RECORD *rec, CONTEXT *context );
|
||||
|
||||
#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
|
||||
extern RUNTIME_FUNCTION *lookup_function_info( ULONG_PTR pc, ULONG_PTR *base, LDR_DATA_TABLE_ENTRY **module );
|
||||
extern RUNTIME_FUNCTION *lookup_dynamic_function_table( ULONG_PTR pc, ULONG_PTR *base, ULONG *count );
|
||||
extern RUNTIME_FUNCTION *find_function_info( ULONG_PTR pc, ULONG_PTR base, RUNTIME_FUNCTION *func, ULONG size );
|
||||
#endif
|
||||
|
||||
/* debug helpers */
|
||||
|
|
|
@ -117,7 +117,6 @@ __ASM_GLOBAL_FUNC( RtlCaptureContext,
|
|||
*/
|
||||
static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEXT *context )
|
||||
{
|
||||
LDR_DATA_TABLE_ENTRY *module;
|
||||
NTSTATUS status;
|
||||
DWORD pc;
|
||||
|
||||
|
@ -128,57 +127,23 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
|
|||
dispatch->ControlPcIsUnwound = (context->ContextFlags & CONTEXT_UNWOUND_TO_CALL) != 0;
|
||||
pc = context->Pc - (dispatch->ControlPcIsUnwound ? 2 : 0);
|
||||
|
||||
/* first look for PE exception information */
|
||||
|
||||
if ((dispatch->FunctionEntry = lookup_function_info(pc,
|
||||
(ULONG_PTR*)&dispatch->ImageBase, &module )))
|
||||
if ((dispatch->FunctionEntry = RtlLookupFunctionEntry( pc, (DWORD_PTR *)&dispatch->ImageBase,
|
||||
dispatch->HistoryTable )))
|
||||
{
|
||||
dispatch->LanguageHandler = RtlVirtualUnwind( type, dispatch->ImageBase, pc,
|
||||
dispatch->FunctionEntry, context,
|
||||
&dispatch->HandlerData, (ULONG_PTR *)&dispatch->EstablisherFrame,
|
||||
NULL );
|
||||
&dispatch->HandlerData,
|
||||
(ULONG_PTR *)&dispatch->EstablisherFrame, NULL );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* then look for host system exception information */
|
||||
|
||||
if (!module || (module->Flags & LDR_WINE_INTERNAL))
|
||||
{
|
||||
struct unwind_builtin_dll_params params = { type, dispatch, context };
|
||||
|
||||
status = WINE_UNIX_CALL( unix_unwind_builtin_dll, ¶ms );
|
||||
if (status != STATUS_SUCCESS) return status;
|
||||
|
||||
if (dispatch->EstablisherFrame)
|
||||
{
|
||||
dispatch->FunctionEntry = NULL;
|
||||
if (dispatch->LanguageHandler && !module)
|
||||
{
|
||||
FIXME( "calling personality routine in system library not supported yet\n" );
|
||||
dispatch->LanguageHandler = NULL;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = context->Pc != context->Lr ?
|
||||
STATUS_SUCCESS : STATUS_INVALID_DISPOSITION;
|
||||
WARN( "exception data not found in %s for %p, LR %p, status %lx\n",
|
||||
debugstr_w(module->BaseDllName.Buffer), (void*) context->Pc,
|
||||
(void*) context->Lr, status );
|
||||
dispatch->EstablisherFrame = context->Sp;
|
||||
dispatch->LanguageHandler = NULL;
|
||||
context->Pc = context->Lr;
|
||||
context->ContextFlags |= CONTEXT_UNWOUND_TO_CALL;
|
||||
return status;
|
||||
}
|
||||
|
||||
WARN( "exception data not found for pc %p, lr %p\n", (void *)context->Pc, (void *)context->Lr );
|
||||
status = context->Pc != context->Lr ? STATUS_SUCCESS : STATUS_INVALID_DISPOSITION;
|
||||
dispatch->EstablisherFrame = context->Sp;
|
||||
dispatch->LanguageHandler = NULL;
|
||||
context->Pc = context->Lr;
|
||||
context->ContextFlags |= CONTEXT_UNWOUND_TO_CALL;
|
||||
return STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1192,6 +1157,31 @@ PRUNTIME_FUNCTION WINAPI RtlLookupFunctionTable( ULONG_PTR pc, ULONG_PTR *base,
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* RtlLookupFunctionEntry (NTDLL.@)
|
||||
*/
|
||||
PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG_PTR pc, ULONG_PTR *base,
|
||||
UNWIND_HISTORY_TABLE *table )
|
||||
{
|
||||
RUNTIME_FUNCTION *func;
|
||||
ULONG_PTR dynbase;
|
||||
ULONG size;
|
||||
|
||||
if ((func = RtlLookupFunctionTable( pc, base, &size )))
|
||||
return find_function_info( pc, *base, func, size / sizeof(*func));
|
||||
|
||||
if ((func = lookup_dynamic_function_table( pc, &dynbase, &size )))
|
||||
{
|
||||
RUNTIME_FUNCTION *ret = find_function_info( pc, dynbase, func, size );
|
||||
if (ret) *base = dynbase;
|
||||
return ret;
|
||||
}
|
||||
|
||||
*base = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* call_consolidate_callback
|
||||
*
|
||||
|
|
|
@ -148,7 +148,6 @@ __ASM_GLOBAL_FUNC( RtlCaptureContext,
|
|||
*/
|
||||
static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEXT *context )
|
||||
{
|
||||
LDR_DATA_TABLE_ENTRY *module;
|
||||
NTSTATUS status;
|
||||
DWORD64 pc;
|
||||
|
||||
|
@ -159,7 +158,8 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
|
|||
dispatch->ControlPcIsUnwound = (context->ContextFlags & CONTEXT_UNWOUND_TO_CALL) != 0;
|
||||
pc = context->Pc - (dispatch->ControlPcIsUnwound ? 4 : 0);
|
||||
|
||||
if ((dispatch->FunctionEntry = lookup_function_info( pc, &dispatch->ImageBase, &module )))
|
||||
if ((dispatch->FunctionEntry = RtlLookupFunctionEntry( pc, &dispatch->ImageBase,
|
||||
dispatch->HistoryTable )))
|
||||
{
|
||||
dispatch->LanguageHandler = RtlVirtualUnwind( type, dispatch->ImageBase, pc,
|
||||
dispatch->FunctionEntry, context,
|
||||
|
@ -168,13 +168,8 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
WARN( "exception data not found for pc %p, lr %p\n", (void *)context->Pc, (void *)context->Lr );
|
||||
status = context->Pc != context->Lr ? STATUS_SUCCESS : STATUS_INVALID_DISPOSITION;
|
||||
if (module)
|
||||
WARN( "exception data not found in %s for pc %p, lr %p\n",
|
||||
debugstr_w(module->BaseDllName.Buffer), (void *)context->Pc, (void *)context->Lr );
|
||||
else
|
||||
WARN( "no module found for pc %p, lr %p\n",
|
||||
(void *)context->Pc, (void *)context->Lr );
|
||||
dispatch->EstablisherFrame = context->Sp;
|
||||
dispatch->LanguageHandler = NULL;
|
||||
context->Pc = context->Lr;
|
||||
|
@ -1063,6 +1058,31 @@ PRUNTIME_FUNCTION WINAPI RtlLookupFunctionTable( ULONG_PTR pc, ULONG_PTR *base,
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* RtlLookupFunctionEntry (NTDLL.@)
|
||||
*/
|
||||
PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG_PTR pc, ULONG_PTR *base,
|
||||
UNWIND_HISTORY_TABLE *table )
|
||||
{
|
||||
RUNTIME_FUNCTION *func;
|
||||
ULONG_PTR dynbase;
|
||||
ULONG size;
|
||||
|
||||
if ((func = RtlLookupFunctionTable( pc, base, &size )))
|
||||
return find_function_info( pc, *base, func, size / sizeof(*func));
|
||||
|
||||
if ((func = lookup_dynamic_function_table( pc, &dynbase, &size )))
|
||||
{
|
||||
RUNTIME_FUNCTION *ret = find_function_info( pc, dynbase, func, size );
|
||||
if (ret) *base = dynbase;
|
||||
return ret;
|
||||
}
|
||||
|
||||
*base = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* call_consolidate_callback
|
||||
*
|
||||
|
|
|
@ -1811,6 +1811,31 @@ PRUNTIME_FUNCTION WINAPI RtlLookupFunctionTable( ULONG_PTR pc, ULONG_PTR *base,
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* RtlLookupFunctionEntry (NTDLL.@)
|
||||
*/
|
||||
PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG_PTR pc, ULONG_PTR *base,
|
||||
UNWIND_HISTORY_TABLE *table )
|
||||
{
|
||||
RUNTIME_FUNCTION *func;
|
||||
ULONG_PTR dynbase;
|
||||
ULONG size;
|
||||
|
||||
if ((func = RtlLookupFunctionTable( pc, base, &size )))
|
||||
return find_function_info( pc, *base, func, size / sizeof(*func));
|
||||
|
||||
if ((func = lookup_dynamic_function_table( pc, &dynbase, &size )))
|
||||
{
|
||||
RUNTIME_FUNCTION *ret = find_function_info( pc, dynbase, func, size );
|
||||
if (ret) *base = dynbase;
|
||||
return ret;
|
||||
}
|
||||
|
||||
*base = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* RtlUnwindEx (NTDLL.@)
|
||||
*/
|
||||
|
|
|
@ -264,7 +264,8 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
|
|||
|
||||
/* first look for PE exception information */
|
||||
|
||||
if ((dispatch->FunctionEntry = lookup_function_info( context->Rip, &dispatch->ImageBase, &module )))
|
||||
if ((dispatch->FunctionEntry = RtlLookupFunctionEntry( context->Rip, &dispatch->ImageBase,
|
||||
dispatch->HistoryTable )))
|
||||
{
|
||||
dispatch->LanguageHandler = RtlVirtualUnwind( type, dispatch->ImageBase, context->Rip,
|
||||
dispatch->FunctionEntry, context,
|
||||
|
@ -275,7 +276,7 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
|
|||
|
||||
/* then look for host system exception information */
|
||||
|
||||
if (!module || (module->Flags & LDR_WINE_INTERNAL))
|
||||
if (LdrFindEntryForAddress( (void *)context->Rip, &module ) || (module->Flags & LDR_WINE_INTERNAL))
|
||||
{
|
||||
struct unwind_builtin_dll_params params = { type, dispatch, context };
|
||||
|
||||
|
@ -287,10 +288,10 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
|
|||
}
|
||||
if (status != STATUS_UNSUCCESSFUL) return status;
|
||||
}
|
||||
else WARN( "exception data not found in %s\n", debugstr_w(module->BaseDllName.Buffer) );
|
||||
|
||||
/* no exception information, treat as a leaf function */
|
||||
|
||||
WARN( "exception data not found for pc %p\n", (void *)context->Rip );
|
||||
dispatch->EstablisherFrame = context->Rsp;
|
||||
dispatch->LanguageHandler = NULL;
|
||||
context->Rip = *(ULONG64 *)context->Rsp;
|
||||
|
@ -1031,6 +1032,31 @@ PRUNTIME_FUNCTION WINAPI RtlLookupFunctionTable( ULONG_PTR pc, ULONG_PTR *base,
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* RtlLookupFunctionEntry (NTDLL.@)
|
||||
*/
|
||||
PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG_PTR pc, ULONG_PTR *base,
|
||||
UNWIND_HISTORY_TABLE *table )
|
||||
{
|
||||
RUNTIME_FUNCTION *func;
|
||||
ULONG_PTR dynbase;
|
||||
ULONG size;
|
||||
|
||||
if ((func = RtlLookupFunctionTable( pc, base, &size )))
|
||||
return find_function_info( pc, *base, func, size / sizeof(*func));
|
||||
|
||||
if ((func = lookup_dynamic_function_table( pc, &dynbase, &size )))
|
||||
{
|
||||
RUNTIME_FUNCTION *ret = find_function_info( pc, dynbase, func, size );
|
||||
if (ret) *base = dynbase;
|
||||
return ret;
|
||||
}
|
||||
|
||||
*base = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct unwind_exception_frame
|
||||
{
|
||||
EXCEPTION_REGISTRATION_RECORD frame;
|
||||
|
|
|
@ -2968,6 +2968,11 @@ static void test_dynamic_unwind(void)
|
|||
ok( base == (ULONG_PTR)code_mem,
|
||||
"RtlLookupFunctionEntry returned invalid base, expected: %Ix, got: %Ix\n", (ULONG_PTR)code_mem, base );
|
||||
|
||||
base = 0xdeadbeef;
|
||||
func = pRtlLookupFunctionEntry( (ULONG_PTR)code_mem + code_offset + 32, &base, NULL );
|
||||
ok( func == NULL, "RtlLookupFunctionEntry got %p\n", func );
|
||||
ok( base == 0xdeadbeef, "RtlLookupFunctionTable wrong base, got: %Ix\n", base );
|
||||
|
||||
base = 0xdeadbeef;
|
||||
func = pRtlLookupFunctionTable( (ULONG_PTR)code_mem + code_offset + 8, &base, &len );
|
||||
ok( func == NULL, "RtlLookupFunctionTable wrong table, got: %p\n", func );
|
||||
|
|
Loading…
Add table
Reference in a new issue