Module: wine Branch: master Commit: 0b3d3ad2b7fa08e99ee6574c44b28a0ac64d9f7b URL: https://gitlab.winehq.org/wine/wine/-/commit/0b3d3ad2b7fa08e99ee6574c44b28a0...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Feb 13 21:18:12 2024 +0100
ntdll: Support ARM64EC code in RtlLookupFunctionEntry.
---
dlls/ntdll/signal_arm64ec.c | 41 ++++++++++++++++++++++++++++++- dlls/ntdll/tests/exception.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index bf1a705368b..5b97b7238b3 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -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; } diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index f01bb488a6a..c061edc46ed 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -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, ¶m, 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" );