1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00

ntdll: Move RtlLookupFunctionEntry() to the CPU backends.

This commit is contained in:
Alexandre Julliard 2024-02-13 11:25:43 +01:00
parent b9a985a677
commit 215a8e68d3
7 changed files with 155 additions and 113 deletions

View file

@ -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__ */

View file

@ -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 */

View file

@ -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, &params );
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
*

View file

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

View file

@ -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.@)
*/

View file

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

View file

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