ntdll: Implement RtlLookupFunctionTable.

This commit is contained in:
Alexandre Julliard 2024-02-12 18:55:29 +01:00
parent 165830c317
commit de492f9a34
8 changed files with 120 additions and 9 deletions

View file

@ -640,15 +640,9 @@ RUNTIME_FUNCTION *lookup_function_info( ULONG_PTR pc, ULONG_PTR *base, LDR_DATA_
ULONG size;
/* PE module or wine module */
if (!LdrFindEntryForAddress( (void *)pc, module ))
if ((func = RtlLookupFunctionTable( pc, base, &size )))
{
*base = (ULONG_PTR)(*module)->DllBase;
if ((func = RtlImageDirectoryEntryToData( (*module)->DllBase, TRUE,
IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size )))
{
/* lookup in function table */
func = find_function_info( pc, (ULONG_PTR)(*module)->DllBase, func, size/sizeof(*func) );
}
func = find_function_info( pc, (ULONG_PTR)(*module)->DllBase, func, size/sizeof(*func) );
}
else
{

View file

@ -878,6 +878,7 @@
@ stdcall RtlLookupElementGenericTable(ptr ptr)
# @ stub RtlLookupElementGenericTableAvl
@ stdcall -arch=!i386 RtlLookupFunctionEntry(long ptr ptr)
@ stdcall -arch=!i386 RtlLookupFunctionTable(long ptr ptr)
@ stdcall RtlMakeSelfRelativeSD(ptr ptr ptr)
@ stdcall RtlMapGenericMask(ptr ptr)
# @ stub RtlMapSecurityErrorToNtStatus

View file

@ -1191,6 +1191,19 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG_PTR base, ULONG_PTR pc,
}
/**********************************************************************
* RtlLookupFunctionTable (NTDLL.@)
*/
PRUNTIME_FUNCTION WINAPI RtlLookupFunctionTable( ULONG_PTR pc, ULONG_PTR *base, ULONG *len )
{
LDR_DATA_TABLE_ENTRY *module;
if (LdrFindEntryForAddress( (void *)pc, &module )) return NULL;
*base = (ULONG_PTR)module->DllBase;
return RtlImageDirectoryEntryToData( module->DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION, len );
}
/**********************************************************************
* call_consolidate_callback
*

View file

@ -1070,6 +1070,20 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG_PTR base, ULONG_PTR pc,
return handler;
}
/**********************************************************************
* RtlLookupFunctionTable (NTDLL.@)
*/
PRUNTIME_FUNCTION WINAPI RtlLookupFunctionTable( ULONG_PTR pc, ULONG_PTR *base, ULONG *len )
{
LDR_DATA_TABLE_ENTRY *module;
if (LdrFindEntryForAddress( (void *)pc, &module )) return NULL;
*base = (ULONG_PTR)module->DllBase;
return RtlImageDirectoryEntryToData( module->DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION, len );
}
/**********************************************************************
* call_consolidate_callback
*

View file

@ -1782,6 +1782,35 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc,
}
/**********************************************************************
* RtlLookupFunctionTable (NTDLL.@)
*/
PRUNTIME_FUNCTION WINAPI RtlLookupFunctionTable( ULONG_PTR pc, ULONG_PTR *base, ULONG *len )
{
LDR_DATA_TABLE_ENTRY *module;
if (LdrFindEntryForAddress( (void *)pc, &module )) return NULL;
*base = (ULONG_PTR)module->DllBase;
if (RtlIsEcCode( (void *)pc ))
{
IMAGE_LOAD_CONFIG_DIRECTORY *cfg;
IMAGE_ARM64EC_METADATA *metadata;
ULONG size;
if (!(cfg = RtlImageDirectoryEntryToData( module->DllBase, TRUE,
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &size )))
return NULL;
size = min( size, cfg->Size );
if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY, CHPEMetadataPointer )) return NULL;
metadata = (IMAGE_ARM64EC_METADATA *)cfg->CHPEMetadataPointer;
*len = metadata->ExtraRFETableSize;
return (RUNTIME_FUNCTION *)(*base + metadata->ExtraRFETable);
}
return RtlImageDirectoryEntryToData( module->DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION, len );
}
/*******************************************************************
* RtlUnwindEx (NTDLL.@)
*/

View file

@ -1029,6 +1029,20 @@ PVOID WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc,
return (char *)base + handler_data->handler;
}
/**********************************************************************
* RtlLookupFunctionTable (NTDLL.@)
*/
PRUNTIME_FUNCTION WINAPI RtlLookupFunctionTable( ULONG_PTR pc, ULONG_PTR *base, ULONG *len )
{
LDR_DATA_TABLE_ENTRY *module;
if (LdrFindEntryForAddress( (void *)pc, &module )) return NULL;
*base = (ULONG_PTR)module->DllBase;
return RtlImageDirectoryEntryToData( module->DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION, len );
}
struct unwind_exception_frame
{
EXCEPTION_REGISTRATION_RECORD frame;

View file

@ -187,6 +187,7 @@ typedef struct _UNWIND_INFO
static BOOLEAN (CDECL *pRtlInstallFunctionTableCallback)(DWORD64, DWORD64, DWORD, PGET_RUNTIME_FUNCTION_CALLBACK, PVOID, PCWSTR);
static PRUNTIME_FUNCTION (WINAPI *pRtlLookupFunctionEntry)(ULONG64, ULONG64*, UNWIND_HISTORY_TABLE*);
static PRUNTIME_FUNCTION (WINAPI *pRtlLookupFunctionTable)(ULONG64, ULONG64*, ULONG*);
static DWORD (WINAPI *pRtlAddGrowableFunctionTable)(void**, RUNTIME_FUNCTION*, DWORD, DWORD, ULONG_PTR, ULONG_PTR);
static void (WINAPI *pRtlGrowFunctionTable)(void*, DWORD);
static void (WINAPI *pRtlDeleteGrowableFunctionTable)(void*);
@ -196,6 +197,7 @@ static VOID (CDECL *pRtlRestoreContext)(CONTEXT*, EXCEPTION_RECORD*);
static NTSTATUS (WINAPI *pRtlWow64GetThreadContext)(HANDLE, WOW64_CONTEXT *);
static NTSTATUS (WINAPI *pRtlWow64SetThreadContext)(HANDLE, const WOW64_CONTEXT *);
static NTSTATUS (WINAPI *pRtlWow64GetCpuAreaInfo)(WOW64_CPURESERVED*,ULONG,WOW64_CPU_AREA_INFO*);
static NTSTATUS (WINAPI *pRtlGetNativeSystemInformation)(SYSTEM_INFORMATION_CLASS,void*,ULONG,ULONG*);
static int (CDECL *p_setjmp)(_JUMP_BUFFER*);
#endif
@ -2793,11 +2795,13 @@ static void test_dynamic_unwind(void)
{
static const int code_offset = 1024;
char buf[2 * sizeof(RUNTIME_FUNCTION) + 4];
SYSTEM_CPU_INFORMATION info;
RUNTIME_FUNCTION *runtime_func, *func;
ULONG_PTR table, base;
void *growable_table;
void *growable_table, *ptr;
NTSTATUS status;
DWORD count;
ULONG len, len2;
if (!pRtlInstallFunctionTableCallback || !pRtlLookupFunctionEntry)
{
@ -2976,7 +2980,46 @@ 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 = pRtlLookupFunctionTable( (ULONG_PTR)code_mem + code_offset + 8, &base, &len );
ok( func == NULL, "RtlLookupFunctionTable wrong table, got: %p\n", func );
ok( base == 0xdeadbeef, "RtlLookupFunctionTable wrong base, got: %Ix\n", base );
base = 0xdeadbeef;
func = pRtlLookupFunctionTable( (ULONG_PTR)pRtlLookupFunctionEntry, &base, &len );
ok( base == (ULONG_PTR)GetModuleHandleA("ntdll.dll"),
"RtlLookupFunctionTable wrong base, got: %Ix / %p\n", base, GetModuleHandleA("ntdll.dll") );
ptr = RtlImageDirectoryEntryToData( (void *)base, TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &len2 );
ok( func == ptr, "RtlLookupFunctionTable wrong table, got: %p / %p\n", func, ptr );
ok( len == len2, "RtlLookupFunctionTable wrong len, got: %lu / %lu\n", len, len2 );
pRtlDeleteGrowableFunctionTable( growable_table );
if (pRtlGetNativeSystemInformation &&
!pRtlGetNativeSystemInformation( SystemCpuInformation, &info, sizeof(info), &len ) &&
info.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64)
{
static const BYTE fast_forward[] = { 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x20, 0x55, 0x5d, 0xe9 };
IMAGE_ARM64EC_METADATA *metadata;
if (!memcmp( pRtlLookupFunctionEntry, fast_forward, sizeof(fast_forward) ))
{
ptr = (char *)pRtlLookupFunctionEntry + sizeof(fast_forward);
ptr = (char *)ptr + 4 + *(int *)ptr;
base = 0xdeadbeef;
func = pRtlLookupFunctionTable( (ULONG_PTR)ptr, &base, &len );
ok( base == (ULONG_PTR)GetModuleHandleA("ntdll.dll"),
"RtlLookupFunctionTable wrong base, got: %Ix / %p\n", base, GetModuleHandleA("ntdll.dll") );
ptr = RtlImageDirectoryEntryToData( (void *)base, TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &len2 );
ok( func != ptr, "RtlLookupFunctionTable wrong table, got: %p / %p\n", func, ptr );
ptr = RtlImageDirectoryEntryToData( (void *)base, TRUE, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &len2 );
metadata = (void *)((IMAGE_LOAD_CONFIG_DIRECTORY *)ptr)->CHPEMetadataPointer;
ok( (char *)func == (char *)base + metadata->ExtraRFETable,
"RtlLookupFunctonTable wrong table, got: %p / %p\n", func, (char *)base + metadata->ExtraRFETable );
ok( len == metadata->ExtraRFETableSize, "RtlLookupFunctionTable wrong len, got: %lu / %lu\n",
len, metadata->ExtraRFETableSize );
}
}
}
static int termination_handler_called;
@ -13006,6 +13049,7 @@ START_TEST(exception)
#define X(f) p##f = (void*)GetProcAddress(hntdll, #f)
X(RtlInstallFunctionTableCallback);
X(RtlLookupFunctionEntry);
X(RtlLookupFunctionTable);
X(RtlAddGrowableFunctionTable);
X(RtlGrowFunctionTable);
X(RtlDeleteGrowableFunctionTable);
@ -13015,6 +13059,7 @@ START_TEST(exception)
X(RtlWow64GetThreadContext);
X(RtlWow64SetThreadContext);
X(RtlWow64GetCpuAreaInfo);
X(RtlGetNativeSystemInformation);
#undef X
p_setjmp = (void *)GetProcAddress( hmsvcrt, "_setjmp" );

View file

@ -2074,6 +2074,7 @@ NTSYSAPI void WINAPI RtlDeleteGrowableFunctionTable(void*);
NTSYSAPI void WINAPI RtlGrowFunctionTable(void*,DWORD);
NTSYSAPI BOOLEAN CDECL RtlInstallFunctionTableCallback(DWORD_PTR,DWORD_PTR,DWORD,PGET_RUNTIME_FUNCTION_CALLBACK,PVOID,PCWSTR);
NTSYSAPI PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry(DWORD_PTR,DWORD_PTR*,UNWIND_HISTORY_TABLE*);
NTSYSAPI PRUNTIME_FUNCTION WINAPI RtlLookupFunctionTable(DWORD_PTR,DWORD_PTR*,ULONG*);
NTSYSAPI void WINAPI RtlUnwindEx(PVOID,PVOID,struct _EXCEPTION_RECORD*,PVOID,CONTEXT*,UNWIND_HISTORY_TABLE*);
NTSYSAPI PVOID WINAPI RtlVirtualUnwind(DWORD,ULONG_PTR,ULONG_PTR,RUNTIME_FUNCTION*,CONTEXT*,PVOID*,ULONG_PTR*,KNONVOLATILE_CONTEXT_POINTERS*);