From f8c60f99727799ff3d5910e99155db0a356e4d77 Mon Sep 17 00:00:00 2001
From: Martin Storsjo <martin@martin.st>
Date: Wed, 16 Aug 2017 23:48:40 +0300
Subject: [PATCH] ntdll: Always restore TEB to x18 on aarch 64 on return from
 calls to builtins

This requires always enabling relaying of calls though.

This isn't enough for cases where builtin functions call back into
the user code though, but works well enough for all pratical cases
I've run so far.

This does give a bit of performance overhead, but it makes it
possible to run most real arm64 binaries (all I've tried).

Signed-off-by: Martin Storsjo <martin@martin.st>
---
 dlls/ntdll/loader.c | 8 +++++++-
 dlls/ntdll/relay.c  | 4 ++++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 42cdc628021..7b92330e874 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -1924,7 +1924,13 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name,
 
     if (image_info->image_flags & IMAGE_FLAGS_WineBuiltin)
     {
-        if (TRACE_ON(relay)) RELAY_SetupDLL( *module );
+#ifdef __aarch64__
+        /* Always enable relay entry points on aarch64, to allow restoring
+         * the TEB to x18. */
+#else
+        if (TRACE_ON(relay))
+#endif
+            RELAY_SetupDLL( *module );
     }
     else
     {
diff --git a/dlls/ntdll/relay.c b/dlls/ntdll/relay.c
index acccf088811..35dd4161d8b 100644
--- a/dlls/ntdll/relay.c
+++ b/dlls/ntdll/relay.c
@@ -705,8 +705,12 @@ static LONGLONG WINAPI relay_call( struct relay_descr *descr, unsigned int idx,
 {
     unsigned int nb_args;
     void *func = relay_trace_entry( descr, idx, stack, &nb_args );
+    void *teb;
     LONGLONG ret = call_entry_point( func, nb_args, stack );
     relay_trace_exit( descr, idx, stack[-1], ret );
+    teb = NtCurrentTeb();
+    /* Restore the TEB pointer, in case the builtin call clobbered it. */
+    __asm__ __volatile__( "mov x18, %0" : : "r" (teb) );
     return ret;
 }
 
-- 
2.27.0

