[PATCH 1/2] ntdll: Support 64-bit Mac OS. (try 3)

Charles Davis cdavis5x at gmail.com
Thu Feb 5 14:28:58 CST 2015


Right now, Mac OS has absolutely no support for setting all 64 bits of
either %fs or %gs. In fact, setting %gs at all isn't supported, because
the kernel allocates the TSD area on behalf of the user-mode threading
support. This needs serious work on the OS side so we can set and use
%gs for the TEB. So, for now, we just use a pthread key.

Try 3: Avoid redefinition errors on non-Apple platforms.
---
 dlls/ntdll/ntdll.spec      |  2 +-
 dlls/ntdll/signal_x86_64.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/thread.c        | 20 ++++++++++++---
 include/winnt.h            |  2 +-
 4 files changed, 83 insertions(+), 5 deletions(-)

diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 51de6e7..a372dff 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -146,7 +146,7 @@
 @ stdcall NtCreateTimer(ptr long ptr long)
 @ stub NtCreateToken
 # @ stub NtCreateWaitablePort
-@ stdcall -arch=win32,arm64 NtCurrentTeb()
+@ stdcall -arch=win32,x86_64,arm64 NtCurrentTeb()
 # @ stub NtDebugActiveProcess
 # @ stub NtDebugContinue
 @ stdcall NtDelayExecution(long ptr)
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index 05581c2..757f3e9 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -236,6 +236,39 @@ static inline int arch_prctl( int func, void *ptr ) { return syscall( __NR_arch_
 #define ERROR_sig(context)  ((context)->uc_mcontext.__gregs[_REG_ERR])
 
 #define FPU_sig(context)   ((XMM_SAVE_AREA32 *)((context)->uc_mcontext.__fpregs))
+#elif defined (__APPLE__)
+static pthread_key_t teb_key;
+
+#define RAX_sig(context)     ((context)->uc_mcontext->__ss.__rax)
+#define RBX_sig(context)     ((context)->uc_mcontext->__ss.__rbx)
+#define RCX_sig(context)     ((context)->uc_mcontext->__ss.__rcx)
+#define RDX_sig(context)     ((context)->uc_mcontext->__ss.__rdx)
+#define RSI_sig(context)     ((context)->uc_mcontext->__ss.__rsi)
+#define RDI_sig(context)     ((context)->uc_mcontext->__ss.__rdi)
+#define RBP_sig(context)     ((context)->uc_mcontext->__ss.__rbp)
+#define R8_sig(context)      ((context)->uc_mcontext->__ss.__r8)
+#define R9_sig(context)      ((context)->uc_mcontext->__ss.__r9)
+#define R10_sig(context)     ((context)->uc_mcontext->__ss.__r10)
+#define R11_sig(context)     ((context)->uc_mcontext->__ss.__r11)
+#define R12_sig(context)     ((context)->uc_mcontext->__ss.__r12)
+#define R13_sig(context)     ((context)->uc_mcontext->__ss.__r13)
+#define R14_sig(context)     ((context)->uc_mcontext->__ss.__r14)
+#define R15_sig(context)     ((context)->uc_mcontext->__ss.__r15)
+
+#define CS_sig(context)      ((context)->uc_mcontext->__ss.__cs)
+#define FS_sig(context)      ((context)->uc_mcontext->__ss.__fs)
+#define GS_sig(context)      ((context)->uc_mcontext->__ss.__gs)
+
+#define EFL_sig(context)     ((context)->uc_mcontext->__ss.__rflags)
+
+#define RIP_sig(context)     (*((unsigned long*)&(context)->uc_mcontext->__ss.__rip))
+#define RSP_sig(context)     (*((unsigned long*)&(context)->uc_mcontext->__ss.__rsp))
+
+#define TRAP_sig(context)    ((context)->uc_mcontext->__es.__trapno)
+#define ERROR_sig(context)   ((context)->uc_mcontext->__es.__err)
+
+#define FPU_sig(context)     ((XMM_SAVE_AREA32 *)&(context)->uc_mcontext->__fs.__fpu_fcw)
+
 #else
 #error You must define the signal context functions for your platform
 #endif
@@ -2506,6 +2539,12 @@ void signal_free_thread( TEB *teb )
     NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE );
 }
 
+#ifdef __APPLE__
+static void init_teb_key(void)
+{
+    pthread_key_create( &teb_key, NULL );
+}
+#endif
 
 /**********************************************************************
  *		signal_init_thread
@@ -2515,12 +2554,20 @@ void signal_init_thread( TEB *teb )
     const WORD fpu_cw = 0x27f;
     stack_t ss;
 
+#ifdef __APPLE__
+    static pthread_once_t init_once = PTHREAD_ONCE_INIT;
+#endif
+
 #if defined __linux__
     arch_prctl( ARCH_SET_GS, teb );
 #elif defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
     amd64_set_gsbase( teb );
 #elif defined(__NetBSD__)
     sysarch( X86_64_SET_GSBASE, &teb );
+#elif defined (__APPLE__)
+    /* FIXME: Actually setting %gs needs support from the OS */
+    pthread_once( &init_once, init_teb_key );
+    pthread_setspecific( teb_key, teb );
 #else
 # error Please define setting %gs for your architecture
 #endif
@@ -3425,4 +3472,21 @@ __ASM_STDCALL_FUNC( DbgBreakPoint, 0, "int $3; ret")
  */
 __ASM_STDCALL_FUNC( DbgUserBreakPoint, 0, "int $3; ret")
 
+/**********************************************************************
+ *              NtCurrentTeb  (NTDLL.@)
+ *
+ * FIXME: This isn't exported from NTDLL on real NT.  This should be
+ *        removed if and when we can set the GSBASE MSR on Mac OS X.
+ */
+#ifdef __APPLE__
+TEB * WINAPI NtCurrentTeb(void)
+{
+    return pthread_getspecific( teb_key );
+}
+#elif defined(__GNUC__)
+__ASM_STDCALL_FUNC( NtCurrentTeb, 0, ".byte 0x65\n\tmovq 0x30,%rax\n\tret" )
+#else
+# error Please define retrieving the current TEB for your platform
+#endif
+
 #endif  /* __x86_64__ */
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 7dd13f2..3696c8e 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -189,9 +189,9 @@ done:
 #include <mach/mach.h>
 #include <mach/mach_error.h>
 
-static ULONG get_dyld_image_info_addr(void)
+static ULONG64 get_dyld_image_info_addr(void)
 {
-    ULONG ret = 0;
+    ULONG64 ret = 0;
 #ifdef TASK_DYLD_INFO
     struct task_dyld_info dyld_info;
     mach_msg_type_number_t size = TASK_DYLD_INFO_COUNT;
@@ -219,6 +219,9 @@ HANDLE thread_init(void)
     NTSTATUS status;
     struct ntdll_thread_data *thread_data;
     static struct debug_info debug_info;  /* debug info for initial thread */
+#ifdef __APPLE__
+    ULONG64 dyld_image_info;
+#endif
 
     virtual_init();
 
@@ -263,7 +266,18 @@ HANDLE thread_init(void)
     InitializeListHead( &ldr.InMemoryOrderModuleList );
     InitializeListHead( &ldr.InInitializationOrderModuleList );
 #ifdef __APPLE__
-    peb->Reserved[0] = get_dyld_image_info_addr();
+    dyld_image_info = get_dyld_image_info_addr();
+#ifdef __LP64__
+#ifdef WORDS_BIGENDIAN
+    peb->Reserved[1] = dyld_image_info & 0xFFFFFFFF;
+    peb->Reserved[0] = dyld_image_info >> 32;
+#else
+    peb->Reserved[0] = dyld_image_info & 0xFFFFFFFF;
+    peb->Reserved[1] = dyld_image_info >> 32;
+#endif
+#else
+    peb->Reserved[0] = dyld_image_info & 0xFFFFFFFF;
+#endif
 #endif
 
     /* allocate and initialize the initial TEB */
diff --git a/include/winnt.h b/include/winnt.h
index 709a93f..4b06b2c 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -2284,7 +2284,7 @@ static FORCEINLINE struct _TEB * WINAPI NtCurrentTeb(void)
   __asm mov teb, eax;
   return teb;
 }
-#elif defined(__x86_64__) && defined(__GNUC__)
+#elif defined(__x86_64__) && defined(__GNUC__) && !defined(__APPLE__)
 static FORCEINLINE struct _TEB * WINAPI NtCurrentTeb(void)
 {
     struct _TEB *teb;
-- 
2.2.2




More information about the wine-patches mailing list