[PATCH] ntdll, kernel32: Set x18 before calling the native entry points on arm64

Martin Storsjo martin at martin.st
Fri Aug 14 06:15:44 CDT 2020


For cases where the builtin DLLs still are built as ELF as opposed
to PE, there's a risk of x18 being clobbered anywhere, after
the point where x18 is initialized at the moment, before entering
native code, if the surrounding operating system ABI doesn't treat
x18 as reserved.

Set the register in assembly code, to avoid the risk of any compiler
generated code (potentially calling helper functions) between setting
x18 and calling the native code entry points.

Signed-off-by: Martin Storsjo <martin at martin.st>
---
Something similar was already done for some functions as part of
e91e6cc9bdb4846.
---
 dlls/kernel32/process.c   | 14 ++++++++++++++
 dlls/ntdll/loader.c       | 16 ++++++++++++++++
 dlls/ntdll/signal_arm64.c |  9 +++++++--
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index b2bd5980fd..f32c588c26 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -118,6 +118,20 @@ __ASM_GLOBAL_FUNC( __wine_start_process,
                    "pushl %ebx\n\t"  /* arg */
                    "pushl %eax\n\t"  /* entry */
                    "call " __ASM_NAME("start_process") )
+#elif defined(__aarch64__)
+extern DWORD call_process_entry( PEB *peb, LPTHREAD_START_ROUTINE entry );
+__ASM_GLOBAL_FUNC( call_process_entry,
+                   "stp x0,  x1,  [sp, #-32]!\n\t"
+                   "stp x29, x30, [sp, #16]\n\t"
+                   "add x29, sp, #16\n\t"
+                   __ASM_CFI(".cfi_def_cfa w29, 16\n\t")
+                   __ASM_CFI(".cfi_offset w30, -8\n\t")
+                   __ASM_CFI(".cfi_offset w29, -16\n\t")
+                   "bl  " __ASM_NAME("NtCurrentTeb") "\n\t"
+                   "mov x18, x0\n\t"
+                   "ldp x29, x30, [sp, #16]\n\t"
+                   "ldp x0,  x1,  [sp], #32\n\t"
+                   "br  x1\n\t")
 #else
 static inline DWORD call_process_entry( PEB *peb, LPTHREAD_START_ROUTINE entry )
 {
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 6290cbcb4e..1779bcb136 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -284,6 +284,22 @@ __ASM_GLOBAL_FUNC(call_dll_entry_point,
                   __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
                   __ASM_CFI(".cfi_same_value %ebp\n\t")
                   "ret" )
+#elif defined(__aarch64__)
+extern BOOL call_dll_entry_point( DLLENTRYPROC proc, void *module, UINT reason, void *reserved );
+__ASM_GLOBAL_FUNC(call_dll_entry_point,
+                   "stp x29, x30, [sp, #-48]!\n\t"
+                   "stp x0,  x1,  [sp, #16]\n\t"
+                   "stp x2,  x3,  [sp, #32]\n\t"
+                   "mov x29, sp\n\t"
+                   __ASM_CFI(".cfi_def_cfa w29, 48\n\t")
+                   __ASM_CFI(".cfi_offset w30, -40\n\t")
+                   __ASM_CFI(".cfi_offset w29, -48\n\t")
+                   "bl  " __ASM_NAME("NtCurrentTeb") "\n\t"
+                   "mov x18, x0\n\t"
+                   "ldp x3,  x0,  [sp, #16]\n\t"
+                   "ldp x1,  x2,  [sp, #32]\n\t"
+                   "ldp x29, x30, [sp], #48\n\t"
+                   "br  x3\n\t")
 #else /* __i386__ */
 static inline BOOL call_dll_entry_point( DLLENTRYPROC proc, void *module,
                                          UINT reason, void *reserved )
diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c
index 573eaef0f6..928ff07cf6 100644
--- a/dlls/ntdll/signal_arm64.c
+++ b/dlls/ntdll/signal_arm64.c
@@ -198,6 +198,11 @@ static DWORD __cdecl unwind_exception_handler( EXCEPTION_RECORD *rec, EXCEPTION_
     return ExceptionCollidedUnwind;
 }
 
+extern DWORD call_language_handler_wrapper( EXCEPTION_RECORD *rec, void *frame, CONTEXT *context, DISPATCHER_CONTEXT *dispatch, PEXCEPTION_ROUTINE handler, TEB *teb );
+__ASM_GLOBAL_FUNC( call_language_handler_wrapper,
+                   "mov x18, x5\n\t"
+                   "br x4\n\t")
+
 /**********************************************************************
  *           call_unwind_handler
  *
@@ -214,7 +219,7 @@ static DWORD call_unwind_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dis
 
     TRACE( "calling handler %p (rec=%p, frame=0x%lx context=%p, dispatch=%p)\n",
          dispatch->LanguageHandler, rec, dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch );
-    res = dispatch->LanguageHandler( rec, (void *)dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch );
+    res = call_language_handler_wrapper( rec, (void *)dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch, dispatch->LanguageHandler, NtCurrentTeb() );
     TRACE( "handler %p returned %x\n", dispatch->LanguageHandler, res );
 
     __wine_pop_frame( &frame.frame );
@@ -288,7 +293,7 @@ static DWORD call_handler( EXCEPTION_RECORD *rec, CONTEXT *context, DISPATCHER_C
 
     TRACE( "calling handler %p (rec=%p, frame=0x%lx context=%p, dispatch=%p)\n",
            dispatch->LanguageHandler, rec, dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch );
-    res = dispatch->LanguageHandler( rec, (void *)dispatch->EstablisherFrame, context, dispatch );
+    res = call_language_handler_wrapper( rec, (void *)dispatch->EstablisherFrame, context, dispatch, dispatch->LanguageHandler, NtCurrentTeb() );
     TRACE( "handler at %p returned %u\n", dispatch->LanguageHandler, res );
 
     __wine_pop_frame( &frame );
-- 
2.17.1




More information about the wine-devel mailing list