From: Billy Laws blaws05@gmail.com
--- dlls/ntdll/loader.c | 22 +++++++++++++++++++--- dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/signal_arm64ec.c | 25 +++++++++++++++++++++---- 3 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index d68f192f19f..09a9a2b6c8b 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -306,11 +306,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 ); @@ -343,6 +343,22 @@ IMAGE_ARM64EC_METADATA *arm64ec_get_module_metadata( HMODULE module ) return (IMAGE_ARM64EC_METADATA *)cfg->CHPEMetadataPointer; }
+void *arm64ec_redirect_module_ptr( HMODULE module, void *ptr, const IMAGE_ARM64EC_METADATA *metadata ) +{ + const IMAGE_ARM64EC_REDIRECTION_ENTRY *map = get_rva( module, metadata->RedirectionMetadata ); + int min = 0, max = metadata->RedirectionMetadataCount - 1; + ULONG_PTR rva = (ULONG_PTR)ptr - (ULONG_PTR)module; + + while (min <= max) + { + int pos = (min + max) / 2; + if (map[pos].Source == rva) return get_rva(module, map[pos].Destination); + if (map[pos].Source < rva) min = pos + 1; + else max = pos - 1; + } + return ptr; +} + #endif
/********************************************************************* diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index d5161ee17f8..d2f6f2f45c9 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -166,6 +166,7 @@ extern NTSTATUS arm64ec_process_init( HMODULE module ); extern NTSTATUS arm64ec_thread_init(void); extern void invoke_arm64ec_syscall(void); extern IMAGE_ARM64EC_METADATA *arm64ec_get_module_metadata( HMODULE module ); +extern void *arm64ec_redirect_module_ptr( HMODULE module, void *ptr, const IMAGE_ARM64EC_METADATA *metadata );
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 a2811c91af5..365e9e52f47 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -155,6 +155,8 @@ static BOOL send_cross_process_notification( HANDLE process, UINT id, const void }
+static void arm64x_check_call(void); + /******************************************************************* * arm64ec_process_init */ @@ -162,12 +164,14 @@ NTSTATUS arm64ec_process_init( HMODULE module ) { NTSTATUS status = STATUS_SUCCESS; CHPEV2_PROCESS_INFO *info = (CHPEV2_PROCESS_INFO *)(RtlGetCurrentPeb() + 1); + const IMAGE_ARM64EC_METADATA *metadata = arm64ec_get_module_metadata( module );
__os_arm64x_dispatch_call_no_redirect = RtlFindExportedRoutineByName( module, "ExitToX64" ); __os_arm64x_dispatch_fptr = RtlFindExportedRoutineByName( module, "DispatchJump" ); __os_arm64x_dispatch_ret = RtlFindExportedRoutineByName( module, "RetToEntryThunk" );
-#define GET_PTR(name) p ## name = RtlFindExportedRoutineByName( module, #name ) +#define GET_PTR(name) p ## name = arm64ec_redirect_module_ptr( module, \ + RtlFindExportedRoutineByName( module, #name ), metadata ) GET_PTR( BTCpu64FlushInstructionCache ); GET_PTR( BTCpu64IsProcessorFeaturePresent ); GET_PTR( BTCpu64NotifyMemoryDirty ); @@ -202,6 +206,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; }
@@ -1714,6 +1721,16 @@ 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;
+static void __attribute__((naked)) arm64x_check_call_early(void) +{ + asm( "mov x11, x9\n\t" + "ret\n\t" ); +} + +static void __attribute__((naked)) arm64x_check_icall_early(void) +{ + asm( "ret\n\t" ); +}
/************************************************************************** * arm64x_check_call @@ -1941,9 +1958,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_icall_early; + __os_arm64x_check_icall_cfg = arm64x_check_icall_early; __os_arm64x_get_x64_information = LdrpGetX64Information; __os_arm64x_set_x64_information = LdrpSetX64Information; }