Tested by running chrome without no-sandbox successfully.
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; }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=149859
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 0000000000D500EC, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032 win.c:4070: Test failed: Expected active window 0000000002690148, got 0000000000000000. win.c:4071: Test failed: Expected focus window 0000000002690148, got 0000000000000000.
I guess it's about internal ntdll syscalls (that use `hybrid_patchable`) and calls from jit? `hybrid_patchable` passes additionally `hp_target` symbol in `x9`, early `__os_arm64x_dispatch_call` could just jump to it. Early `__os_arm64x_dispatch_icall` could probably just assume that the target is ARM64EC. For calls from the jit module, I imagine that auxiliary IAT support could be useful. We could then somehow special-case jit to never revert it, even if patching is detected.
This is just for calls within ntdll as CEF patches syscall entrypoints before starting the thread, the JIT is expected to install its own call checker that redirects functions itself afaict (I needed one for fex to work under Windows). Will give what you suggested a go though if it's preferred over the generic solution
@jacek So I gave this a test, it fails for calls into the JIT (`pProcessInit` etc) as they don't end up getting redirected. Will give this a test on Windows to see what behaviour happens exactly if they are patched.
On Sun Nov 24 11:44:37 2024 +0000, Billy Laws wrote:
@jacek So I gave this a test, it fails for calls into the JIT (`pProcessInit` etc) as they don't end up getting redirected. Will give this a test on Windows to see what behaviour happens exactly if they are patched.
If this patching should be ignored, we could probably resolve the redirection (and possibly others) in `arm64ec_process_init`.