ntdll: Support ARM64EC code in RtlLookupFunctionEntry.

This commit is contained in:
Alexandre Julliard 2024-02-13 21:18:12 +01:00
parent ab69f71912
commit 0b3d3ad2b7
2 changed files with 97 additions and 1 deletions

View file

@ -252,6 +252,30 @@ static RUNTIME_FUNCTION *find_function_info( ULONG_PTR pc, ULONG_PTR base,
}
static ARM64_RUNTIME_FUNCTION *find_function_info_arm64( ULONG_PTR pc, ULONG_PTR base,
ARM64_RUNTIME_FUNCTION *func, ULONG size )
{
int min = 0;
int max = size - 1;
while (min <= max)
{
int pos = (min + max) / 2;
ULONG_PTR start = base + func[pos].BeginAddress;
if (pc >= start)
{
ULONG len = func[pos].Flag ? func[pos].FunctionLength :
((IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA *)(base + func[pos].UnwindData))->FunctionLength;
if (pc < start + 4 * len) return func + pos;
min = pos + 1;
}
else max = pos - 1;
}
return NULL;
}
/*******************************************************************
* syscalls
*/
@ -1844,11 +1868,26 @@ PRUNTIME_FUNCTION WINAPI RtlLookupFunctionEntry( ULONG_PTR pc, ULONG_PTR *base,
ULONG size;
if ((func = RtlLookupFunctionTable( pc, base, &size )))
{
if (RtlIsEcCode( (void *)pc ))
{
ARM64_RUNTIME_FUNCTION *arm64func = (ARM64_RUNTIME_FUNCTION *)func;
size /= sizeof(*arm64func);
return (RUNTIME_FUNCTION *)find_function_info_arm64( pc, *base, arm64func, 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 );
RUNTIME_FUNCTION *ret;
if (RtlIsEcCode( (void *)pc ))
ret = (RUNTIME_FUNCTION *)find_function_info_arm64( pc, dynbase,
(ARM64_RUNTIME_FUNCTION *)func, size );
else
ret = find_function_info( pc, dynbase, func, size );
if (ret) *base = dynbase;
return ret;
}

View file

@ -186,6 +186,7 @@ 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 NTSTATUS (WINAPI *pNtAllocateVirtualMemoryEx)(HANDLE,PVOID*,SIZE_T*,ULONG,ULONG,MEM_EXTENDED_PARAMETER*,ULONG);
static int (CDECL *p_setjmp)(_JUMP_BUFFER*);
#endif
@ -2994,6 +2995,9 @@ static void test_dynamic_unwind(void)
{
static const BYTE fast_forward[] = { 0x48, 0x8b, 0xc4, 0x48, 0x89, 0x58, 0x20, 0x55, 0x5d, 0xe9 };
IMAGE_ARM64EC_METADATA *metadata;
ARM64_RUNTIME_FUNCTION *arm64func = (ARM64_RUNTIME_FUNCTION *)buf;
MEM_EXTENDED_PARAMETER param = { 0 };
SIZE_T size = 0x1000;
if (!memcmp( pRtlLookupFunctionEntry, fast_forward, sizeof(fast_forward) ))
{
@ -3012,6 +3016,58 @@ static void test_dynamic_unwind(void)
ok( len == metadata->ExtraRFETableSize, "RtlLookupFunctionTable wrong len, got: %lu / %lu\n",
len, metadata->ExtraRFETableSize );
}
arm64func->BeginAddress = code_offset;
arm64func->Flag = 1;
arm64func->FunctionLength = 4;
arm64func->RegF = 1;
arm64func->RegI = 1;
arm64func->H = 1;
arm64func->CR = 1;
arm64func->FrameSize = 1;
arm64func++;
arm64func->BeginAddress = code_offset + 16;
arm64func->Flag = 1;
arm64func->FunctionLength = 4;
arm64func->RegF = 1;
arm64func->RegI = 1;
arm64func->H = 1;
arm64func->CR = 1;
arm64func->FrameSize = 1;
param.Type = MemExtendedParameterAttributeFlags;
param.ULong64 = MEM_EXTENDED_PARAMETER_EC_CODE;
ptr = NULL;
status = pNtAllocateVirtualMemoryEx( GetCurrentProcess(), &ptr, &size, MEM_RESERVE | MEM_COMMIT,
PAGE_EXECUTE_READWRITE, &param, 1 );
ok( !status, "NtAllocateVirtualMemoryEx failed %lx\n", status );
growable_table = NULL;
status = pRtlAddGrowableFunctionTable( &growable_table, (RUNTIME_FUNCTION *)buf,
2, 2, (ULONG_PTR)ptr, (ULONG_PTR)ptr + code_offset + 64 );
ok( !status, "RtlAddGrowableFunctionTable failed %lx\n", status );
base = 0xdeadbeef;
func = pRtlLookupFunctionEntry( (ULONG_PTR)ptr + code_offset + 8, &base, NULL );
ok( func == (RUNTIME_FUNCTION *)buf, "RtlLookupFunctionEntry expected func: %p, got: %p\n",
buf, func );
ok( base == (ULONG_PTR)ptr, "RtlLookupFunctionEntry expected base: %Ix, got: %Ix\n",
(ULONG_PTR)ptr, base );
base = 0xdeadbeef;
func = pRtlLookupFunctionEntry( (ULONG_PTR)ptr + code_offset + 16, &base, NULL );
ok( func == (RUNTIME_FUNCTION *)(buf + sizeof(*arm64func)),
"RtlLookupFunctionEntry expected func: %p, got: %p\n", buf + sizeof(*arm64func), func );
ok( base == (ULONG_PTR)ptr, "RtlLookupFunctionEntry expected base: %Ix, got: %Ix\n",
(ULONG_PTR)ptr, base );
base = 0xdeadbeef;
func = pRtlLookupFunctionEntry( (ULONG_PTR)ptr + code_offset + 32, &base, NULL );
ok( !func, "RtlLookupFunctionEntry got: %p\n", func );
ok( base == 0xdeadbeef, "RtlLookupFunctionEntry got: %Ix\n", base );
pRtlDeleteGrowableFunctionTable( growable_table );
VirtualFree( ptr, 0, MEM_FREE );
}
}
@ -13057,6 +13113,7 @@ START_TEST(exception)
X(RtlWow64SetThreadContext);
X(RtlWow64GetCpuAreaInfo);
X(RtlGetNativeSystemInformation);
X(NtAllocateVirtualMemoryEx);
#undef X
p_setjmp = (void *)GetProcAddress( hmsvcrt, "_setjmp" );