From: Billy Laws blaws05@gmail.com
--- dlls/ntdll/loader.c | 6 ++-- dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/signal_arm64ec.c | 61 ++++++++++++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 7 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 2f2a7fe5427..057849466fa 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -303,11 +303,11 @@ static void update_hybrid_metadata( void *module, IMAGE_NT_HEADERS *nt, NtProtectVirtualMemory( NtCurrentProcess(), &base, &size, PAGE_READWRITE, &protect_old );
#define SET_FUNC(func,val) update_hybrid_pointer( module, sec, metadata->func, val ) - SET_FUNC( __os_arm64x_dispatch_call, __os_arm64x_check_call ); + SET_FUNC( __os_arm64x_dispatch_call, arm64x_check_call ); SET_FUNC( __os_arm64x_dispatch_call_no_redirect, __os_arm64x_dispatch_call_no_redirect ); SET_FUNC( __os_arm64x_dispatch_fptr, __os_arm64x_dispatch_fptr ); - SET_FUNC( __os_arm64x_dispatch_icall, __os_arm64x_check_icall ); - SET_FUNC( __os_arm64x_dispatch_icall_cfg, __os_arm64x_check_icall_cfg ); + SET_FUNC( __os_arm64x_dispatch_icall, arm64x_check_call ); + SET_FUNC( __os_arm64x_dispatch_icall_cfg, arm64x_check_call ); SET_FUNC( __os_arm64x_dispatch_ret, __os_arm64x_dispatch_ret ); SET_FUNC( __os_arm64x_helper3, __os_arm64x_helper3 ); SET_FUNC( __os_arm64x_helper4, __os_arm64x_helper4 ); diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index e58a07ba02a..891856fc4e6 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -165,6 +165,7 @@ extern void heap_thread_detach(void); extern NTSTATUS arm64ec_process_init( HMODULE module ); extern NTSTATUS arm64ec_thread_init(void); extern void invoke_arm64ec_syscall(void); +extern void arm64x_check_call(void);
extern void *__os_arm64x_check_call; extern void *__os_arm64x_check_icall; diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index 438dfe8d439..f3e96ebaab2 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -202,6 +202,9 @@ NTSTATUS arm64ec_process_init( HMODULE module ) } if (!status && pThreadInit) status = pThreadInit(); leave_syscall_callback(); + __os_arm64x_check_call = arm64x_check_call; + __os_arm64x_check_icall = arm64x_check_call; + __os_arm64x_check_icall_cfg = arm64x_check_call; return status; }
@@ -1704,13 +1707,63 @@ NTSTATUS __attribute__((naked)) __wine_unix_call_arm64ec( unixlib_handle_t handl
NTSTATUS (WINAPI *__wine_unix_call_dispatcher_arm64ec)( unixlib_handle_t, unsigned int, void * ) = __wine_unix_call_arm64ec;
+extern const IMAGE_ARM64EC_METADATA __chpe_metadata; +extern IMAGE_DOS_HEADER __ImageBase; + +void *redirect_ntdll_ptr( void *dest ) +{ + const IMAGE_ARM64EC_REDIRECTION_ENTRY *map = (void *)((ULONG_PTR)&__ImageBase + __chpe_metadata.RedirectionMetadata); + int min = 0, max = __chpe_metadata.RedirectionMetadataCount - 1; + ULONG_PTR rva = (ULONG_PTR)dest - (ULONG_PTR)&__ImageBase; + + while (min <= max) + { + int pos = (min + max) / 2; + if (map[pos].Source == rva) return (BYTE *)&__ImageBase + map[pos].Destination; + if (map[pos].Source < rva) min = pos + 1; + else max = pos - 1; + } + + return dest; +} + +static void __attribute__((naked)) arm64x_check_call_early(void) +{ + asm( "stp x29, x30, [sp,#-0xb0]!\n\t" + "mov x29, sp\n\t" + "stp x0, x1, [sp, #0x10]\n\t" + "stp x2, x3, [sp, #0x20]\n\t" + "stp x4, x5, [sp, #0x30]\n\t" + "stp x6, x7, [sp, #0x40]\n\t" + "stp x8, x9, [sp, #0x50]\n\t" + "stp x10, x15, [sp, #0x60]\n\t" + "stp d0, d1, [sp, #0x70]\n\t" + "stp d2, d3, [sp, #0x80]\n\t" + "stp d4, d5, [sp, #0x90]\n\t" + "stp d6, d7, [sp, #0xa0]\n\t" + "mov x0, x11\n\t" /* x0 = dest */ + "bl "#redirect_ntdll_ptr"\n\t" + "mov x11, x0\n\t" + "ldp x0, x1, [sp, #0x10]\n\t" + "ldp x2, x3, [sp, #0x20]\n\t" + "ldp x4, x5, [sp, #0x30]\n\t" + "ldp x6, x7, [sp, #0x40]\n\t" + "ldp x8, x9, [sp, #0x50]\n\t" + "ldp x10, x15, [sp, #0x60]\n\t" + "ldp d0, d1, [sp, #0x70]\n\t" + "ldp d2, d3, [sp, #0x80]\n\t" + "ldp d4, d5, [sp, #0x90]\n\t" + "ldp d6, d7, [sp, #0xa0]\n\t" + "ldp x29, x30, [sp], #0xb0\n\t" + "b "#arm64x_check_call"\n\t"); +}
/************************************************************************** * arm64x_check_call * * Implementation of __os_arm64x_check_call. */ -static void __attribute__((naked)) arm64x_check_call(void) +void __attribute__((naked)) arm64x_check_call(void) { asm( ".seh_proc "#arm64x_check_call"\n\t" ".seh_endprologue\n\t" @@ -1931,9 +1984,9 @@ void WINAPI LdrInitializeThunk( CONTEXT *arm_context, ULONG_PTR unk2, ULONG_PTR
if (!__os_arm64x_check_call) { - __os_arm64x_check_call = arm64x_check_call; - __os_arm64x_check_icall = arm64x_check_call; - __os_arm64x_check_icall_cfg = arm64x_check_call; + __os_arm64x_check_call = arm64x_check_call_early; + __os_arm64x_check_icall = arm64x_check_call_early; + __os_arm64x_check_icall_cfg = arm64x_check_call_early; __os_arm64x_get_x64_information = LdrpGetX64Information; __os_arm64x_set_x64_information = LdrpSetX64Information; }