From: Jacek Caban jacek@codeweavers.com
Instead of using inderect C calls, which need to go through the call dispatcher. --- dlls/ntdll/loader.c | 5 ++++- dlls/ntdll/ntdll.spec | 4 +++- dlls/ntdll/signal_arm64ec.c | 17 ++++++++++++++++- dlls/ntdll/unix/loader.c | 12 +++++++++++- dlls/winecrt0/unix_lib.c | 23 ++++++++++++++++++++++- include/wine/unixlib.h | 5 +++++ 6 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 6e3f67ef593..eaf57d92788 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -70,7 +70,6 @@ typedef DWORD (CALLBACK *DLLENTRYPROC)(HMODULE,DWORD,LPVOID); typedef void (CALLBACK *LDRENUMPROC)(LDR_DATA_TABLE_ENTRY *, void *, BOOLEAN *);
void (FASTCALL *pBaseThreadInitThunk)(DWORD,LPTHREAD_START_ROUTINE,void *) = NULL; -NTSTATUS (WINAPI *__wine_unix_call_dispatcher)( unixlib_handle_t, unsigned int, void * ) = __wine_unix_call;
static DWORD (WINAPI *pCtrlRoutine)(void *);
@@ -3317,11 +3316,15 @@ NTSTATUS WINAPI __wine_ctrl_routine( void *arg ) /*********************************************************************** * __wine_unix_call */ +#ifndef __arm64ec__ NTSTATUS WINAPI __wine_unix_call( unixlib_handle_t handle, unsigned int code, void *args ) { return __wine_unix_call_dispatcher( handle, code, args ); }
+NTSTATUS (WINAPI *__wine_unix_call_dispatcher)( unixlib_handle_t, unsigned int, void * ) = NULL; +#endif +
/*********************************************************************** * __wine_unix_spawnvp diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 13043130cf6..ecd54662254 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1719,11 +1719,13 @@ @ cdecl wine_server_handle_to_fd(long long ptr ptr)
# Unix interface -@ stdcall __wine_unix_call(int64 long ptr) +@ stdcall -arch=!arm64ec __wine_unix_call(int64 long ptr) +@ stdcall -arch=arm64ec __wine_unix_call(int64 long ptr) __wine_unix_call_arm64ec @ stdcall __wine_unix_spawnvp(long ptr) @ stdcall __wine_ctrl_routine(ptr) @ extern -private __wine_syscall_dispatcher @ extern -private __wine_unix_call_dispatcher +@ extern -private -arch=arm64ec __wine_unix_call_dispatcher_arm64ec @ extern -private __wine_unixlib_handle
# Debugging diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index 8caf4218ab9..b5a4d42e89b 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -2227,6 +2227,22 @@ ULONG WINAPI RtlWalkFrameChain( void **buffer, ULONG count, ULONG flags ) }
+/************************************************************************* + * __wine_unix_call_arm64ec (NTDLL.@) + */ +NTSTATUS __attribute__((naked)) __wine_unix_call_arm64ec( unixlib_handle_t handle, unsigned int code, void *args ) +{ + asm( ".seh_proc "#__wine_unix_call_arm64ec"\n\t" + "adrp x16, __wine_unix_call_dispatcher_arm64ec\n\t" + "ldr x16, [x16, #:lo12:__wine_unix_call_dispatcher_arm64ec]\n\t" + "br x16\n\t" + ".seh_endproc" ); +} + +NTSTATUS (WINAPI *__wine_unix_call_dispatcher)( unixlib_handle_t, unsigned int, void * ) = __wine_unix_call_arm64ec; +NTSTATUS (WINAPI *__wine_unix_call_dispatcher_arm64ec)( unixlib_handle_t, unsigned int, void * ) = NULL; + + static int code_match( BYTE *code, const BYTE *seq, size_t len ) { for ( ; len; len--, code++, seq++) if (*seq && *code != *seq) return 0; @@ -2262,7 +2278,6 @@ void *check_call( void **target, void *exit_thunk, void *dest )
for (;;) { - if (dest == __wine_unix_call_dispatcher) return dest; if (RtlIsEcCode( (ULONG_PTR)dest )) return dest; if (code_match( dest, jmp_sequence, sizeof(jmp_sequence) )) { diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 06959fa95df..0eeacae0865 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1537,8 +1537,18 @@ static void load_ntdll_functions( HMODULE module ) GET_FUNC( RtlUserThreadStart ); GET_FUNC( __wine_ctrl_routine ); GET_FUNC( __wine_syscall_dispatcher ); - GET_FUNC( __wine_unix_call_dispatcher ); GET_FUNC( __wine_unixlib_handle ); + if (!is_arm64ec()) + { + GET_FUNC( __wine_unix_call_dispatcher ); + } + else + { + p__wine_unix_call_dispatcher = (void *)find_named_export( module, exports, + "__wine_unix_call_dispatcher_arm64ec" ); + if (!p__wine_unix_call_dispatcher) + ERR( "__wine_unix_call_dispatcher_arm64ec not found\n" ); + } *p__wine_syscall_dispatcher = __wine_syscall_dispatcher; *p__wine_unix_call_dispatcher = __wine_unix_call_dispatcher; *p__wine_unixlib_handle = (UINT_PTR)unix_call_funcs; diff --git a/dlls/winecrt0/unix_lib.c b/dlls/winecrt0/unix_lib.c index 5b809b6949d..29091b6f6d1 100644 --- a/dlls/winecrt0/unix_lib.c +++ b/dlls/winecrt0/unix_lib.c @@ -46,6 +46,20 @@ static NTSTATUS WINAPI unix_call_fallback( unixlib_handle_t handle, unsigned int unixlib_handle_t __wine_unixlib_handle = 0; NTSTATUS (WINAPI *__wine_unix_call_dispatcher)( unixlib_handle_t, unsigned int, void * ) = unix_call_fallback;
+#ifdef __arm64ec__ +static NTSTATUS (WINAPI *__wine_unix_call_dispatcher_arm64ec)( unixlib_handle_t, unsigned int, void * ) = + unix_call_fallback; + +NTSTATUS __attribute__((naked)) __wine_unix_call_arm64ec( unixlib_handle_t handle, unsigned int code, void *args ) +{ + asm( ".seh_proc "#__wine_unix_call_arm64ec"\n\t" + "adrp x16, __wine_unix_call_dispatcher_arm64ec\n\t" + "ldr x16, [x16, #:lo12:__wine_unix_call_dispatcher_arm64ec]\n\t" + "br x16\n\t" + ".seh_endproc" ); +} +#endif + NTSTATUS WINAPI __wine_init_unix_call(void) { NTSTATUS status; @@ -55,6 +69,13 @@ NTSTATUS WINAPI __wine_init_unix_call(void) if (!p__wine_unix_call_dispatcher) return STATUS_DLL_NOT_FOUND; status = NtQueryVirtualMemory( GetCurrentProcess(), image_base(), MemoryWineUnixFuncs, &__wine_unixlib_handle, sizeof(__wine_unixlib_handle), NULL ); - if (!status) __wine_unix_call_dispatcher = *p__wine_unix_call_dispatcher; + if (!status) + { + __wine_unix_call_dispatcher = *p__wine_unix_call_dispatcher; +#ifdef __arm64ec__ + __wine_unix_call_dispatcher_arm64ec = + *(void **)GetProcAddress( module, "__wine_unix_call_dispatcher_arm64ec" ); +#endif + } return status; } diff --git a/include/wine/unixlib.h b/include/wine/unixlib.h index 95ff406d968..0b45ba9ef94 100644 --- a/include/wine/unixlib.h +++ b/include/wine/unixlib.h @@ -263,7 +263,12 @@ extern unixlib_handle_t __wine_unixlib_handle; extern NTSTATUS (WINAPI *__wine_unix_call_dispatcher)( unixlib_handle_t, unsigned int, void * ); extern NTSTATUS WINAPI __wine_init_unix_call(void);
+#ifdef __arm64ec__ +NTSTATUS WINAPI __wine_unix_call_arm64ec( unixlib_handle_t handle, unsigned int code, void *args ); +#define WINE_UNIX_CALL(code,args) __wine_unix_call_arm64ec( __wine_unixlib_handle, (code), (args) ) +#else #define WINE_UNIX_CALL(code,args) __wine_unix_call_dispatcher( __wine_unixlib_handle, (code), (args) ) +#endif
#endif /* WINE_UNIX_LIB */