Alexandre Julliard : winebuild: Save/restore the %fs register in the syscall dispatcher on Linux.

Alexandre Julliard julliard at winehq.org
Tue Jul 6 18:09:35 CDT 2021


Module: wine
Branch: master
Commit: 216d2411781f4bf12edf2083a7ac84d2885bd404
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=216d2411781f4bf12edf2083a7ac84d2885bd404

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Jul  6 12:50:56 2021 +0200

winebuild: Save/restore the %fs register in the syscall dispatcher on Linux.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/unix/signal_x86_64.c | 11 +++++++++--
 tools/winebuild/import.c        | 22 ++++++++++++++++++++++
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c
index dab22c67021..93183794bf6 100644
--- a/dlls/ntdll/unix/signal_x86_64.c
+++ b/dlls/ntdll/unix/signal_x86_64.c
@@ -41,6 +41,9 @@
 #ifdef HAVE_MACHINE_SYSARCH_H
 # include <machine/sysarch.h>
 #endif
+#ifdef HAVE_SYS_AUXV_H
+# include <sys/auxv.h>
+#endif
 #ifdef HAVE_SYS_PARAM_H
 # include <sys/param.h>
 #endif
@@ -276,8 +279,10 @@ C_ASSERT( sizeof(XSTATE) == 0x140 );
 C_ASSERT( sizeof(struct stack_layout) == 0x590 ); /* Should match the size in call_user_exception_dispatcher(). */
 
 /* flags to control the behavior of the syscall dispatcher */
-#define SYSCALL_HAVE_XSAVE    1
-#define SYSCALL_HAVE_XSAVEC   2
+#define SYSCALL_HAVE_XSAVE       1
+#define SYSCALL_HAVE_XSAVEC      2
+#define SYSCALL_HAVE_PTHREAD_TEB 4
+#define SYSCALL_HAVE_WRFSGSBASE  8
 
 /* stack layout when calling an user apc function.
  * FIXME: match Windows ABI. */
@@ -2859,6 +2864,8 @@ void signal_init_process(void)
         if ((sel = alloc_fs_sel( -1, teb32 )) != -1)
         {
             fs32_sel = (sel << 3) | 3;
+            __wine_syscall_flags |= SYSCALL_HAVE_PTHREAD_TEB;
+            if (getauxval( AT_HWCAP2 ) & 2) __wine_syscall_flags |= SYSCALL_HAVE_WRFSGSBASE;
         }
         else ERR( "failed to allocate %%fs selector\n" );
     }
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index 6b03ff73f49..064ab1b4768 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -1597,6 +1597,21 @@ static void output_syscall_dispatcher(void)
         output( "\tjmp 3f\n" );
         output( "2:\tfxsave64 0xc0(%%rcx)\n" );
         output( "3:\tleaq 0x98(%%rcx),%%rbp\n" );
+        if (target_platform == PLATFORM_LINUX)
+        {
+            output( "\ttestl $12,%%r14d\n" );  /* SYSCALL_HAVE_PTHREAD_TEB | SYSCALL_HAVE_WRFSGSBASE */
+            output( "\tjz 2f\n" );
+            output( "\tmovq %%gs:0x330,%%rsi\n" );  /* amd64_thread_data()->pthread_teb */
+            output( "\ttestl $8,%%r14d\n" );  /* SYSCALL_HAVE_WRFSGSBASE */
+            output( "\tjz 1f\n" );
+            output( "\twrfsbase %%rsi\n" );
+            output( "\tjmp 2f\n" );
+            output( "1:\tmov $0x1002,%%edi\n" );      /* ARCH_SET_FS */
+            output( "\tmov $158,%%eax\n" );           /* SYS_arch_prctl */
+            output( "\tsyscall\n" );
+            output( "\tleaq -0x98(%%rbp),%%rcx\n" );
+            output( "2:\n" );
+        }
         output( "\tleaq 0x28(%%rsp),%%rsi\n" );   /* first argument */
         output( "\tmovq %%rcx,%%rsp\n" );
         output( "\tmovq 0x00(%%rcx),%%rax\n" );
@@ -1625,6 +1640,13 @@ static void output_syscall_dispatcher(void)
         output( "\tcallq *(%%r10,%%rax,8)\n" );
         output( "\tleaq -0x98(%%rbp),%%rcx\n" );
         output( "2:\tmovl 0x94(%%rcx),%%edx\n" );   /* frame->restore_flags */
+        if (target_platform == PLATFORM_LINUX)
+        {
+            output( "\ttestl $12,%%r14d\n" ); /* SYSCALL_HAVE_PTHREAD_TEB | SYSCALL_HAVE_WRFSGSBASE */
+            output( "\tjz 1f\n" );
+            output( "\tmovw 0x7e(%%rcx),%%fs\n" );
+            output( "1:\n" );
+        }
         output( "\ttestl $0x48,%%edx\n" );  /* CONTEXT_FLOATING_POINT | CONTEXT_XSTATE */
         output( "\tjz 4f\n" );
         output( "\ttestl $3,%%r14d\n" );  /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */




More information about the wine-cvs mailing list