[compiler-rt] r252738 - Implement some TLS support for PowerPC64.

Jay Foad via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 11 07:37:47 PST 2015


Author: foad
Date: Wed Nov 11 09:37:47 2015
New Revision: 252738

URL: http://llvm.org/viewvc/llvm-project?rev=252738&view=rev
Log:
Implement some TLS support for PowerPC64.

Summary: This is enough to get the asan static_tls.cc test case working.

Reviewers: eugenis, samsonov

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D14574

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.cc
    compiler-rt/trunk/test/asan/TestCases/Linux/static_tls.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc?rev=252738&r1=252737&r2=252738&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc Wed Nov 11 09:37:47 2015
@@ -166,11 +166,15 @@ static uptr g_tls_size;
 # define DL_INTERNAL_FUNCTION
 #endif
 
-#if defined(__mips__)
+#if defined(__mips__) || defined(__powerpc64__)
 // TlsPreTcbSize includes size of struct pthread_descr and size of tcb
 // head structure. It lies before the static tls blocks.
 static uptr TlsPreTcbSize() {
-  const uptr kTcbHead = 16;
+# if defined(__mips__)
+  const uptr kTcbHead = 16; // sizeof (tcbhead_t)
+# elif defined(__powerpc64__)
+  const uptr kTcbHead = 88; // sizeof (tcbhead_t)
+# endif
   const uptr kTlsAlign = 16;
   const uptr kTlsPreTcbSize =
     (ThreadDescriptorSize() + kTcbHead + kTlsAlign - 1) & ~(kTlsAlign - 1);
@@ -201,9 +205,9 @@ void InitTlsSize() {
 }
 
 #if (defined(__x86_64__) || defined(__i386__) || defined(__mips__) \
-    || defined(__aarch64__)) \
+    || defined(__aarch64__) || defined(__powerpc64__)) \
     && SANITIZER_LINUX && !SANITIZER_ANDROID
-// sizeof(struct thread) from glibc.
+// sizeof(struct pthread) from glibc.
 static atomic_uintptr_t kThreadDescriptorSize;
 
 uptr ThreadDescriptorSize() {
@@ -218,7 +222,7 @@ uptr ThreadDescriptorSize() {
     char *end;
     int minor = internal_simple_strtoll(buf + 8, &end, 10);
     if (end != buf + 8 && (*end == '\0' || *end == '.')) {
-      /* sizeof(struct thread) values from various glibc versions.  */
+      /* sizeof(struct pthread) values from various glibc versions.  */
       if (SANITIZER_X32)
         val = 1728;  // Assume only one particular version for x32.
       else if (minor <= 3)
@@ -254,6 +258,10 @@ uptr ThreadDescriptorSize() {
   val = 1776;
   atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed);
   return val;
+#elif defined(__powerpc64__)
+  val = 1776; // from glibc.ppc64le 2.20-8.fc21
+  atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed);
+  return val;
 #endif
   return 0;
 }
@@ -285,6 +293,15 @@ uptr ThreadSelf() {
   descr_addr = thread_pointer - kTlsTcbOffset - TlsPreTcbSize();
 # elif defined(__aarch64__)
   descr_addr = reinterpret_cast<uptr>(__builtin_thread_pointer());
+# elif defined(__powerpc64__)
+  // PPC64LE uses TLS variant I. The thread pointer (in GPR 13)
+  // points to the end of the TCB + 0x7000. The pthread_descr structure is
+  // immediately in front of the TCB. TlsPreTcbSize() includes the size of the
+  // TCB and the size of pthread_descr.
+  const uptr kTlsTcbOffset = 0x7000;
+  uptr thread_pointer;
+  asm("addi %0,13,%1" : "=r"(thread_pointer) : "I"(-kTlsTcbOffset));
+  descr_addr = thread_pointer - TlsPreTcbSize();
 # else
 #  error "unsupported CPU arch"
 # endif
@@ -320,7 +337,7 @@ static void GetTls(uptr *addr, uptr *siz
   *size = GetTlsSize();
   *addr -= *size;
   *addr += ThreadDescriptorSize();
-# elif defined(__mips__) || defined(__aarch64__)
+# elif defined(__mips__) || defined(__aarch64__) || defined(__powerpc64__)
   *addr = ThreadSelf();
   *size = GetTlsSize();
 # else

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.cc?rev=252738&r1=252737&r2=252738&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_tls_get_addr.cc Wed Nov 11 09:37:47 2015
@@ -78,6 +78,15 @@ void DTLS_Destroy() {
   DTLS_Deallocate(dtls.dtv, s);
 }
 
+#if defined(__powerpc64__)
+// This is glibc's TLS_DTV_OFFSET:
+// "Dynamic thread vector pointers point 0x8000 past the start of each
+//  TLS block."
+static const uptr kDtvOffset = 0x8000;
+#else
+static const uptr kDtvOffset = 0;
+#endif
+
 DTLS::DTV *DTLS_on_tls_get_addr(void *arg_void, void *res,
                                 uptr static_tls_begin, uptr static_tls_end) {
   if (!common_flags()->intercept_tls_get_addr) return 0;
@@ -87,7 +96,7 @@ DTLS::DTV *DTLS_on_tls_get_addr(void *ar
   DTLS_Resize(dso_id + 1);
   if (dtls.dtv[dso_id].beg) return 0;
   uptr tls_size = 0;
-  uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset;
+  uptr tls_beg = reinterpret_cast<uptr>(res) - arg->offset - kDtvOffset;
   VPrintf(2, "__tls_get_addr: %p {%p,%p} => %p; tls_beg: %p; sp: %p "
              "num_live_dtls %zd\n",
           arg, arg->dso_id, arg->offset, res, tls_beg, &tls_beg,

Modified: compiler-rt/trunk/test/asan/TestCases/Linux/static_tls.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/static_tls.cc?rev=252738&r1=252737&r2=252738&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/static_tls.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/static_tls.cc Wed Nov 11 09:37:47 2015
@@ -9,7 +9,7 @@
 // CHECK: __tls_get_addr: static tls
 // CHECK: after
 
-// XFAIL: powerpc64, aarch64
+// XFAIL: aarch64
 
 #ifndef SHARED
 #include <stdio.h>




More information about the llvm-commits mailing list