[compiler-rt] r181322 - [sanitizer] Move GetThreadStackAndTls from TSan to sanitizer_common.

Sergey Matveev earthdok at google.com
Tue May 7 07:41:43 PDT 2013


Author: smatveev
Date: Tue May  7 09:41:43 2013
New Revision: 181322

URL: http://llvm.org/viewvc/llvm-project?rev=181322&view=rev
Log:
[sanitizer] Move GetThreadStackAndTls from TSan to sanitizer_common.

Move this function to sanitizer_common because LSan uses it too. Also, fix a bug
where the TLS range reported for main thread was off by the size of the thread
descriptor from libc (TSan doesn't care much, but for LSan it's critical).

Removed:
    compiler-rt/trunk/lib/tsan/tests/unit/tsan_platform_test.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc
    compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_platform.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_platform_mac.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_platform_windows.cc
    compiler-rt/trunk/lib/tsan/tests/unit/CMakeLists.txt

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h?rev=181322&r1=181321&r2=181322&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Tue May  7 09:41:43 2013
@@ -45,6 +45,8 @@ uptr GetTid();
 uptr GetThreadSelf();
 void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
                                 uptr *stack_bottom);
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+                          uptr *tls_addr, uptr *tls_size);
 
 // Memory management
 void *MmapOrDie(uptr size, const char *mem_type);

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=181322&r1=181321&r2=181322&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc Tue May  7 09:41:43 2013
@@ -24,6 +24,7 @@
 #include "sanitizer_procmaps.h"
 #include "sanitizer_stacktrace.h"
 
+#include <asm/prctl.h>
 #include <dlfcn.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -63,6 +64,8 @@ const int FUTEX_WAKE = 1;
 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
 #endif
 
+extern "C" int arch_prctl(int code, __sanitizer::uptr *addr);
+
 namespace __sanitizer {
 
 // --------------- sanitizer_libc.h
@@ -761,6 +764,50 @@ uptr GetTlsSize() {
   return g_tls_size;
 }
 
+// sizeof(struct thread) from glibc.
+#ifdef __x86_64__
+const uptr kThreadDescriptorSize = 2304;
+
+uptr ThreadDescriptorSize() {
+  return kThreadDescriptorSize;
+}
+#endif
+
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+                          uptr *tls_addr, uptr *tls_size) {
+#ifndef SANITIZER_GO
+#ifdef __x86_64__
+  arch_prctl(ARCH_GET_FS, tls_addr);
+  *tls_size = GetTlsSize();
+  *tls_addr -= *tls_size;
+  *tls_addr += kThreadDescriptorSize;
+#else
+  *tls_addr = 0;
+  *tls_size = 0;
+#endif
+
+  uptr stack_top, stack_bottom;
+  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
+  *stk_addr = stack_bottom;
+  *stk_size = stack_top - stack_bottom;
+
+  if (!main) {
+    // If stack and tls intersect, make them non-intersecting.
+    if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) {
+      CHECK_GT(*tls_addr + *tls_size, *stk_addr);
+      CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size);
+      *stk_size -= *tls_size;
+      *tls_addr = *stk_addr + *stk_size;
+    }
+  }
+#else  // SANITIZER_GO
+  *stk_addr = 0;
+  *stk_size = 0;
+  *tls_addr = 0;
+  *tls_size = 0;
+#endif  // SANITIZER_GO
+}
+
 void AdjustStackSizeLinux(void *attr_, int verbosity) {
   pthread_attr_t *attr = (pthread_attr_t *)attr_;
   uptr stackaddr = 0;

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h?rev=181322&r1=181321&r2=181322&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.h Tue May  7 09:41:43 2013
@@ -52,6 +52,9 @@ class ThreadLister {
 
 void AdjustStackSizeLinux(void *attr, int verbosity);
 
+// Exposed for testing.
+uptr ThreadDescriptorSize();
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_LINUX_H

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc?rev=181322&r1=181321&r2=181322&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc Tue May  7 09:41:43 2013
@@ -339,6 +339,16 @@ uptr GetTlsSize() {
 void InitTlsSize() {
 }
 
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+                          uptr *tls_addr, uptr *tls_size) {
+  uptr stack_top, stack_bottom;
+  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
+  *stk_addr = stack_bottom;
+  *stk_size = stack_top - stack_bottom;
+  *tls_addr = 0;
+  *tls_size = 0;
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_MAC

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc?rev=181322&r1=181321&r2=181322&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win.cc Tue May  7 09:41:43 2013
@@ -336,6 +336,16 @@ uptr GetTlsSize() {
 void InitTlsSize() {
 }
 
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+                          uptr *tls_addr, uptr *tls_size) {
+  uptr stack_top, stack_bottom;
+  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
+  *stk_addr = stack_bottom;
+  *stk_size = stack_top - stack_bottom;
+  *tls_addr = 0;
+  *tls_size = 0;
+}
+
 }  // namespace __sanitizer
 
 #endif  // _WIN32

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc?rev=181322&r1=181321&r2=181322&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_common_test.cc Tue May  7 09:41:43 2013
@@ -112,4 +112,49 @@ TEST(SanitizerCommon, InternalVector) {
   }
 }
 
+void TestThreadInfo(bool main) {
+  uptr stk_addr = 0;
+  uptr stk_size = 0;
+  uptr tls_addr = 0;
+  uptr tls_size = 0;
+  GetThreadStackAndTls(main, &stk_addr, &stk_size, &tls_addr, &tls_size);
+
+  int stack_var;
+  EXPECT_NE(stk_addr, (uptr)0);
+  EXPECT_NE(stk_size, (uptr)0);
+  EXPECT_GT((uptr)&stack_var, stk_addr);
+  EXPECT_LT((uptr)&stack_var, stk_addr + stk_size);
+
+#if defined(__linux__) && defined(__x86_64__)
+  static __thread int thread_var;
+  EXPECT_NE(tls_addr, (uptr)0);
+  EXPECT_NE(tls_size, (uptr)0);
+  EXPECT_GT((uptr)&thread_var, tls_addr);
+  EXPECT_LT((uptr)&thread_var, tls_addr + tls_size);
+
+  // Ensure that tls and stack do not intersect.
+  uptr tls_end = tls_addr + tls_size;
+  EXPECT_TRUE(tls_addr < stk_addr || tls_addr >= stk_addr + stk_size);
+  EXPECT_TRUE(tls_end  < stk_addr || tls_end  >=  stk_addr + stk_size);
+  EXPECT_TRUE((tls_addr < stk_addr) == (tls_end  < stk_addr));
+#endif
+}
+
+static void *WorkerThread(void *arg) {
+  TestThreadInfo(false);
+  return 0;
+}
+
+TEST(SanitizerCommon, ThreadStackTlsMain) {
+  InitTlsSize();
+  TestThreadInfo(true);
+}
+
+TEST(Platform, ThreadStackTlsWorker) {
+  InitTlsSize();
+  pthread_t t;
+  pthread_create(&t, 0, WorkerThread, 0);
+  pthread_join(t, 0);
+}
+
 }  // namespace __sanitizer

Modified: compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc?rev=181322&r1=181321&r2=181322&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/tests/sanitizer_linux_test.cc Tue May  7 09:41:43 2013
@@ -18,6 +18,9 @@
 
 #include "sanitizer_common/sanitizer_common.h"
 
+#ifdef __x86_64__
+#include <asm/prctl.h>
+#endif
 #include <pthread.h>
 #include <sched.h>
 #include <stdlib.h>
@@ -25,6 +28,10 @@
 #include <algorithm>
 #include <vector>
 
+#ifdef __x86_64__
+extern "C" int arch_prctl(int code, __sanitizer::uptr *addr);
+#endif
+
 namespace __sanitizer {
 
 struct TidReporterArgument {
@@ -194,6 +201,28 @@ TEST(SanitizerCommon, SetEnvTest) {
   EXPECT_EQ(0, getenv(kEnvName));
 }
 
+#ifdef __x86_64__
+// libpthread puts the thread descriptor (%fs:0x0) at the end of stack space.
+void *thread_descriptor_test_func(void *arg) {
+  uptr fs;
+  arch_prctl(ARCH_GET_FS, &fs);
+  pthread_attr_t attr;
+  pthread_getattr_np(pthread_self(), &attr);
+  void *stackaddr;
+  uptr stacksize;
+  pthread_attr_getstack(&attr, &stackaddr, &stacksize);
+  return (void *)((uptr)stackaddr + stacksize - fs);
+}
+
+TEST(SanitizerLinux, ThreadDescriptorSize) {
+  pthread_t tid;
+  void *result;
+  pthread_create(&tid, 0, thread_descriptor_test_func, 0);
+  ASSERT_EQ(0, pthread_join(tid, &result));
+  EXPECT_EQ((uptr)result, ThreadDescriptorSize());
+}
+#endif
+
 }  // namespace __sanitizer
 
 #endif  // __linux__

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_platform.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_platform.h?rev=181322&r1=181321&r2=181322&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_platform.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_platform.h Tue May  7 09:41:43 2013
@@ -154,8 +154,6 @@ void internal_start_thread(void(*func)(v
 // Says whether the addr relates to a global var.
 // Guesses with high probability, may yield both false positives and negatives.
 bool IsGlobalVar(uptr addr);
-void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
-                          uptr *tls_addr, uptr *tls_size);
 int ExtractResolvFDs(void *state, int *fds, int nfd);
 
 }  // namespace __tsan

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc?rev=181322&r1=181321&r2=181322&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc Tue May  7 09:41:43 2013
@@ -23,7 +23,6 @@
 #include "tsan_rtl.h"
 #include "tsan_flags.h"
 
-#include <asm/prctl.h>
 #include <fcntl.h>
 #include <pthread.h>
 #include <signal.h>
@@ -46,7 +45,6 @@
 #include <resolv.h>
 #include <malloc.h>
 
-extern "C" int arch_prctl(int code, __sanitizer::uptr *addr);
 extern "C" struct mallinfo __libc_mallinfo();
 
 namespace __tsan {
@@ -358,35 +356,6 @@ const char *InitializePlatform() {
   return GetEnv(kTsanOptionsEnv);
 }
 
-void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
-                          uptr *tls_addr, uptr *tls_size) {
-#ifndef TSAN_GO
-  arch_prctl(ARCH_GET_FS, tls_addr);
-  *tls_size = GetTlsSize();
-  *tls_addr -= *tls_size;
-
-  uptr stack_top, stack_bottom;
-  GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
-  *stk_addr = stack_bottom;
-  *stk_size = stack_top - stack_bottom;
-
-  if (!main) {
-    // If stack and tls intersect, make them non-intersecting.
-    if (*tls_addr > *stk_addr && *tls_addr < *stk_addr + *stk_size) {
-      CHECK_GT(*tls_addr + *tls_size, *stk_addr);
-      CHECK_LE(*tls_addr + *tls_size, *stk_addr + *stk_size);
-      *stk_size -= *tls_size;
-      *tls_addr = *stk_addr + *stk_size;
-    }
-  }
-#else
-  *stk_addr = 0;
-  *stk_size = 0;
-  *tls_addr = 0;
-  *tls_size = 0;
-#endif
-}
-
 bool IsGlobalVar(uptr addr) {
   return g_data_start && addr >= g_data_start && addr < g_data_end;
 }

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_platform_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_platform_mac.cc?rev=181322&r1=181321&r2=181322&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_platform_mac.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_platform_mac.cc Tue May  7 09:41:43 2013
@@ -90,14 +90,6 @@ void FinalizePlatform() {
   fflush(0);
 }
 
-void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
-                          uptr *tls_addr, uptr *tls_size) {
-  *stk_addr = 0;
-  *stk_size = 0;
-  *tls_addr = 0;
-  *tls_size = 0;
-}
-
 }  // namespace __tsan
 
 #endif  // SANITIZER_MAC

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_platform_windows.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_platform_windows.cc?rev=181322&r1=181321&r2=181322&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_platform_windows.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_platform_windows.cc Tue May  7 09:41:43 2013
@@ -42,14 +42,6 @@ void FinalizePlatform() {
   fflush(0);
 }
 
-void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
-                          uptr *tls_addr, uptr *tls_size) {
-  *stk_addr = 0;
-  *stk_size = 0;
-  *tls_addr = 0;
-  *tls_size = 0;
-}
-
 }  // namespace __tsan
 
 #endif  // SANITIZER_WINDOWS

Modified: compiler-rt/trunk/lib/tsan/tests/unit/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/tests/unit/CMakeLists.txt?rev=181322&r1=181321&r2=181322&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/tests/unit/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/tsan/tests/unit/CMakeLists.txt Tue May  7 09:41:43 2013
@@ -3,7 +3,6 @@ set(TSAN_UNIT_TESTS
   tsan_flags_test.cc
   tsan_mman_test.cc
   tsan_mutex_test.cc
-  tsan_platform_test.cc
   tsan_shadow_test.cc
   tsan_stack_test.cc
   tsan_suppressions_test.cc

Removed: compiler-rt/trunk/lib/tsan/tests/unit/tsan_platform_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/tests/unit/tsan_platform_test.cc?rev=181321&view=auto
==============================================================================
--- compiler-rt/trunk/lib/tsan/tests/unit/tsan_platform_test.cc (original)
+++ compiler-rt/trunk/lib/tsan/tests/unit/tsan_platform_test.cc (removed)
@@ -1,64 +0,0 @@
-//===-- tsan_platform_test.cc ---------------------------------------------===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of ThreadSanitizer (TSan), a race detector.
-//
-//===----------------------------------------------------------------------===//
-#include "sanitizer_common/sanitizer_libc.h"
-#include "tsan_platform.h"
-#include "tsan_rtl.h"
-#include "gtest/gtest.h"
-
-namespace __tsan {
-
-static void TestThreadInfo(bool main) {
-  ScopedInRtl in_rtl;
-  uptr stk_addr = 0;
-  uptr stk_size = 0;
-  uptr tls_addr = 0;
-  uptr tls_size = 0;
-  GetThreadStackAndTls(main, &stk_addr, &stk_size, &tls_addr, &tls_size);
-  // Printf("stk=%zx-%zx(%zu)\n", stk_addr, stk_addr + stk_size, stk_size);
-  // Printf("tls=%zx-%zx(%zu)\n", tls_addr, tls_addr + tls_size, tls_size);
-
-  int stack_var;
-  EXPECT_NE(stk_addr, (uptr)0);
-  EXPECT_NE(stk_size, (uptr)0);
-  EXPECT_GT((uptr)&stack_var, stk_addr);
-  EXPECT_LT((uptr)&stack_var, stk_addr + stk_size);
-
-  static __thread int thread_var;
-  EXPECT_NE(tls_addr, (uptr)0);
-  EXPECT_NE(tls_size, (uptr)0);
-  EXPECT_GT((uptr)&thread_var, tls_addr);
-  EXPECT_LT((uptr)&thread_var, tls_addr + tls_size);
-
-  // Ensure that tls and stack do not intersect.
-  uptr tls_end = tls_addr + tls_size;
-  EXPECT_TRUE(tls_addr < stk_addr || tls_addr >= stk_addr + stk_size);
-  EXPECT_TRUE(tls_end  < stk_addr || tls_end  >=  stk_addr + stk_size);
-  EXPECT_TRUE((tls_addr < stk_addr) == (tls_end  < stk_addr));
-}
-
-static void *WorkerThread(void *arg) {
-  TestThreadInfo(false);
-  return 0;
-}
-
-TEST(Platform, ThreadInfoMain) {
-  TestThreadInfo(true);
-}
-
-TEST(Platform, ThreadInfoWorker) {
-  pthread_t t;
-  pthread_create(&t, 0, WorkerThread, 0);
-  pthread_join(t, 0);
-}
-
-}  // namespace __tsan





More information about the llvm-commits mailing list