From: Martin Storsjo Subject: [PATCH] ntdll: Always restore TEB to x18 on aarch 64 on return from calls to builtins Message-Id: <1507881160-2093-1-git-send-email-martin@martin.st> Date: Fri, 13 Oct 2017 10:52:40 +0300 This requires always enabling relaying of calls though. This isn't enough for cases where builtin functions call back into the user code though. Signed-off-by: Martin Storsjo --- I'm pretty sure this approach has been suggested and dismissed before, so I'm not sincerely trying to get this patch merged; I'm using it locally and posting it for reference, if someone else is interested in locally patching their builds. The previous attempts of disabling use of x18 within the wine codebase worked fine for some of the test binaries from the windows 10 SDK, however as pointed out by Alexandre before, this is futile as long as the rest of the host environment can clobber x18 in any call to system functions. This fixes running binaries built by Visual C++ for ARM64 (which finally is out publicly now) on a normal debian aarch64 userland. Visual C++ uses the TEB while clang for windows/arm64 hasn't (so far). --- 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 9c89d57..ad15a15 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1687,7 +1687,13 @@ static void load_builtin_callback( void *module, const char *filename ) SERVER_END_REQ; /* setup relay debugging entry points */ - 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 ); } diff --git a/dlls/ntdll/relay.c b/dlls/ntdll/relay.c index f16b4fc..9156c08 100644 --- a/dlls/ntdll/relay.c +++ b/dlls/ntdll/relay.c @@ -577,8 +577,12 @@ static LONGLONG WINAPI relay_call( struct relay_descr *descr, unsigned int idx, BYTE nb_args = LOBYTE(HIWORD(idx)); BYTE flags = HIBYTE(HIWORD(idx)); void *func = relay_trace_entry( descr, idx, stack + 3 ); + void *teb; LONGLONG ret = call_entry_point( func, nb_args, stack + 4, flags ); relay_trace_exit( descr, idx, stack + 3, ret ); + teb = NtCurrentTeb(); + /* Restore the TEB pointer, in case the builtin call clobbered it. */ + __asm__ __volatile__( "mov x18, %0" : : "r" (teb) ); return ret; } -- 2.7.4