Tested by running chrome without no-sandbox successfully.
-- v2: ntdll: Force redirect all ARM64EC indirect calls until the JIT is ready. ntdll: Add arm64ec_get_module_metadata helper.
From: Billy Laws blaws05@gmail.com
--- dlls/ntdll/loader.c | 14 ++++++++++++++ dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/unwind.c | 12 ++---------- 3 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 38516115b38..d68f192f19f 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -329,6 +329,20 @@ static void update_hybrid_metadata( void *module, IMAGE_NT_HEADERS *nt, ERR( "module %p no section found for %lx\n", module, metadata->__os_arm64x_dispatch_call ); }
+IMAGE_ARM64EC_METADATA *arm64ec_get_module_metadata( HMODULE module ) +{ + IMAGE_LOAD_CONFIG_DIRECTORY *cfg; + ULONG size; + + if (!(cfg = RtlImageDirectoryEntryToData( module, TRUE, + IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &size ))) + return NULL; + + size = min( size, cfg->Size ); + if (size <= offsetof( IMAGE_LOAD_CONFIG_DIRECTORY, CHPEMetadataPointer )) return NULL; + return (IMAGE_ARM64EC_METADATA *)cfg->CHPEMetadataPointer; +} + #endif
/********************************************************************* diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index e58a07ba02a..d5161ee17f8 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 IMAGE_ARM64EC_METADATA *arm64ec_get_module_metadata( HMODULE module );
extern void *__os_arm64x_check_call; extern void *__os_arm64x_check_icall; diff --git a/dlls/ntdll/unwind.c b/dlls/ntdll/unwind.c index 91b07a7cc8c..c11bd9ddb9c 100644 --- a/dlls/ntdll/unwind.c +++ b/dlls/ntdll/unwind.c @@ -267,16 +267,8 @@ PRUNTIME_FUNCTION WINAPI RtlLookupFunctionTable( ULONG_PTR pc, ULONG_PTR *base, #ifdef __arm64ec__ if (RtlIsEcCode( 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; + IMAGE_ARM64EC_METADATA *metadata = arm64ec_get_module_metadata( module->DllBase ); + if (!metadata) return NULL; *len = metadata->ExtraRFETableSize; return (RUNTIME_FUNCTION *)(*base + metadata->ExtraRFETable); }
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; }
On Thu Nov 28 18:32:28 2024 +0000, Jacek Caban wrote:
If this patching should be ignored, we could probably resolve the redirection (and possibly others) in `arm64ec_process_init`.
Seems like that is the case from windows testing.
@julliard does this approach seem reasonable?