Git at Google

commitf5c8041b5ad95d8f0011b78d96fda7a184d8249a[log][tgz]
authormseaborn@chromium.org <mseaborn@chromium.org@fcba33aa-ac0c-11dd-b9e7-8d5594d729c2>Wed Oct 20 10:51:02 2010 +0000
committermseaborn@chromium.org <mseaborn@chromium.org@fcba33aa-ac0c-11dd-b9e7-8d5594d729c2>Wed Oct 20 10:51:02 2010 +0000
tree8b5a755a31fcef664bb6cf46462a23676ff46d3a
parent0d08179e3b5240ca9c3be765aa3ebd59361c1bbd[diff]
Port x86-64 NaCl to Mac OS X: Implement the necessary TLS support

SConstruct: Update to pass "-m64" on Mac when building for x86-64.

nacl_tls_64.c: Add code to check that pthread_getspecific() has the
(very simple) implementation that we expect, because we are relying on
an internal detail of OS X's libpthread.

service_runtime/build.scons: Remove logic that was made unnecessary by
earlier changes that changed SConstruct to pass the correct options.

BUG=http://code.google.com/p/nativeclient/issues/detail?id=1051
TEST="./scons platform=x86-64 small_tests -k"
  -- all but 2 tests pass (though the plugin fails to build)

Review URL: http://codereview.chromium.org/3818006

git-svn-id: svn://svn.chromium.org/native_client/trunk/src/native_client@3506 fcba33aa-ac0c-11dd-b9e7-8d5594d729c2
diff --git a/SConstruct b/SConstruct
index 49989ea..52d3420 100644
--- a/SConstruct
+++ b/SConstruct
@@ -1398,17 +1398,28 @@
     PLUGIN_SUFFIX = '.bundle',
 )
 
+if mac_env['BUILD_SUBARCH'] == '64':
+  # OS X 10.5 was the first version to support x86-64.  We need to
+  # specify 10.5 rather than 10.4 here otherwise building
+  # get_plugin_dirname.mm gives the warning (converted to an error)
+  # "Mac OS X version 10.5 or later is needed for use of the new objc abi".
+  mac_env.Append(
+      CCFLAGS=['-mmacosx-version-min=10.5'],
+      LINKFLAGS=['-mmacosx-version-min=10.5'],
+      CPPDEFINES=[['MAC_OS_X_VERSION_MIN_REQUIRED', 'MAC_OS_X_VERSION_10_5']])
+else:
+  mac_env.Append(
+      CCFLAGS=['-mmacosx-version-min=10.4'],
+      LINKFLAGS=['-mmacosx-version-min=10.4'],
+      CPPDEFINES=[['MAC_OS_X_VERSION_MIN_REQUIRED', 'MAC_OS_X_VERSION_10_4']])
+subarch_flag = '-m%s' % mac_env['BUILD_SUBARCH']
 mac_env.Append(
-    # TODO(bradnelson): Update the hard-coded -m32 flags when we support
-    # 64-bit builds on the Mac.
-    CCFLAGS = ['-mmacosx-version-min=10.4', '-m32', '-fPIC'],
-    ASFLAGS = ['-m32'],
-    LINKFLAGS = ['-mmacosx-version-min=10.4', '-m32', '-fPIC'],
-    # TODO(bradnelson): remove UNIX_LIKE_CFLAGS when scons bug is fixed
+    CCFLAGS=[subarch_flag, '-fPIC'],
+    ASFLAGS=[subarch_flag],
+    LINKFLAGS=[subarch_flag, '-fPIC'],
     CPPDEFINES = [['NACL_WINDOWS', '0'],
                   ['NACL_OSX', '1'],
                   ['NACL_LINUX', '0'],
-                  ['MAC_OS_X_VERSION_MIN_REQUIRED', 'MAC_OS_X_VERSION_10_4'],
                   # defining _DARWIN_C_SOURCE breaks 10.4
                   #['_DARWIN_C_SOURCE', '1'],
                   #['__STDC_LIMIT_MACROS', '1']
diff --git a/src/trusted/service_runtime/arch/x86_64/nacl_syscall_64.S b/src/trusted/service_runtime/arch/x86_64/nacl_syscall_64.S
index 3c80081..6853902 100644
--- a/src/trusted/service_runtime/arch/x86_64/nacl_syscall_64.S
+++ b/src/trusted/service_runtime/arch/x86_64/nacl_syscall_64.S
@@ -63,6 +63,13 @@
 #if NACL_LINUX
         /* Linux uses TLS. */
         movl    %fs:nacl_thread_index@TPOFF, %eax
+#elif NACL_OSX
+        /*
+         * This assumes a particular implementation of OS X's
+         * pthread_getspecific(), which we check for in NaClTlsInit().
+         */
+        movl    _nacl_thread_index_tls_offset(%rip), %eax
+        movl    %gs:(%eax), %eax
 #elif NACL_WINDOWS
        /*
         * The Windows linker won't insert the correct offset for
@@ -90,8 +97,6 @@
         movq %gs:0x58, %rax
         movq (%rax,%rcx,8), %rax
         movl (%rdx,%rax), %eax
-#elif NACL_OSX
-# error "64-bit OSX is not a supported NaCl runtime target platform"
 #else
 # error "What OS/compiler is the service runtime being compiled with?"
 #endif
diff --git a/src/trusted/service_runtime/arch/x86_64/nacl_tls_64.c b/src/trusted/service_runtime/arch/x86_64/nacl_tls_64.c
index bda33af..616a805 100644
--- a/src/trusted/service_runtime/arch/x86_64/nacl_tls_64.c
+++ b/src/trusted/service_runtime/arch/x86_64/nacl_tls_64.c
@@ -4,9 +4,6 @@
  * be found in the LICENSE file.
  */
 
-/*
- * NB: 64-bit OSX support is not tested at this point.
- */
 #if NACL_OSX
 # include <pthread.h>
 #endif
@@ -94,9 +91,45 @@
 #if NACL_OSX
 
 pthread_key_t nacl_thread_info_key;
+uint32_t nacl_thread_index_tls_offset;
 
 int NaClTlsInit() {
   int errnum;
+
+  /*
+   * Unlike Linux and Windows, Mac OS X does not provide TLS variables
+   * that can be accessed via a TLS register without a function call,
+   * which we need in order to restore the thread's trusted stack in
+   * nacl_syscall_64.S.
+   *
+   * OS X only provides pthread_getspecific().  However, its code is
+   * trivial, so we can inline it.  Of course, this assumes a
+   * particular pthread implementation, so we check this assumption.
+   * If the pthread implementation changes, we will need to update
+   * this code.
+   *
+   * The current expected code is:
+   *   65 48 8b 04 fd 60 00 00 00  movq %gs:_PTHREAD_TSD_OFFSET(,%rdi,8),%rax
+   *   c3                          ret
+   * in which _PTHREAD_TSD_OFFSET == 0x60.
+   * But we accept other values of _PTHREAD_TSD_OFFSET below.
+   */
+  uint8_t *code = (uint8_t *) (uintptr_t) pthread_getspecific;
+  uint32_t pthread_tsd_offset;
+  if (!(code[0] == 0x65 &&
+        code[1] == 0x48 &&
+        code[2] == 0x8b &&
+        code[3] == 0x04 &&
+        code[4] == 0xfd &&
+        code[9] == 0xc3)) {
+    NaClLog(LOG_FATAL, "NaClTlsInit: Unexpected implementation of "
+            "pthread_getspecific().  NaCl requires porting to the version "
+            "of Mac OS X's pthread library on this system.\n");
+  }
+  pthread_tsd_offset = *(uint32_t *) (code + 5);
+  NaClLog(2, "NaClTlsInit: Found expected implementation of "
+          "pthread_getspecific(), and _PTHREAD_TSD_OFFSET=0x%"NACL_PRIx32"\n",
+          pthread_tsd_offset);
 
   NaClThreadStartupCheck();
 
@@ -111,6 +144,7 @@
             errnum);
     return 0;
   }
+  nacl_thread_index_tls_offset = pthread_tsd_offset + 8 * nacl_thread_info_key;
   return 1;
 }
 
@@ -154,13 +188,28 @@
 
 
 void NaClTlsSetIdx(uint32_t tls_idx) {
+  uint32_t tls_idx_check;
+
 #if 1  /* PARANOIA */
   if (NULL != pthread_getspecific(nacl_thread_info_key)) {
     NaClLog(LOG_WARNING,
             "NaClSetThreadInfo invoked twice for the same thread\n");
   }
 #endif
-  pthread_setspecific(nacl_thread_info_key, (void *) tls_idx);
+  pthread_setspecific(nacl_thread_info_key, (void *) (uintptr_t) tls_idx);
+
+  /*
+   * Sanity check:  Make sure that reading back the value using our
+   * knowledge of Mac OS X's TLS internals gives us the correct value.
+   * This checks that we inferred _PTHREAD_TSD_OFFSET correctly earlier.
+   */
+  asm("movl %%gs:(%1), %0"
+      : "=r"(tls_idx_check)
+      : "r"(nacl_thread_index_tls_offset));
+  if (tls_idx_check != tls_idx) {
+    NaClLog(LOG_FATAL, "NaClTlsSetIdx: Sanity check failed: "
+            "TLS offset must be wrong\n");
+  }
 }
 
 
diff --git a/src/trusted/service_runtime/build.scons b/src/trusted/service_runtime/build.scons
index 75a88b3..2911442 100644
--- a/src/trusted/service_runtime/build.scons
+++ b/src/trusted/service_runtime/build.scons
@@ -65,19 +65,6 @@
             )
 
 
-# On Linux, only turn on 32-bit flags (like -m32) when needed.
-# On Mac, force 32-bit always (even on 10.6 where 64-bit is the default).
-# (Note from jrg on 5/11/10: this only appears relevant on Mac).
-if not env.Bit('windows'):
-  if ((env['BUILD_ARCHITECTURE'] == 'x86' and env['TARGET_SUBARCH'] == '32') or
-      env.Bit('mac')):
-    env.FilterOut(ASFLAGS=['-m64'])
-    env.FilterOut(CCFLAGS=['-m64'])
-    env.FilterOut(LINKFLAGS = ['-m64', '-L/usr/lib64'])
-    env.Prepend(ASFLAGS = ['-m32', ],
-                CCFLAGS = ['-m32', ],
-                LINKFLAGS = ['-m32', '-L/usr/lib32'])
-
 # ----------------------------------------------------------
 # TODO(robertm): this library is too big and needs to be split up
 #                for easier unit testing