[llvm-commits] [compiler-rt] r157466 - in /compiler-rt/trunk/lib/tsan: rtl/tsan_defs.h rtl/tsan_interceptors.cc rtl/tsan_platform.h rtl/tsan_platform_linux.cc rtl/tsan_rtl_thread.cc rtl/tsan_symbolize_addr2line_linux.cc unit_tests/tsan_platform_test.cc

Dmitry Vyukov dvyukov at google.com
Fri May 25 04:15:04 PDT 2012


Author: dvyukov
Date: Fri May 25 06:15:04 2012
New Revision: 157466

URL: http://llvm.org/viewvc/llvm-project?rev=157466&view=rev
Log:
tsan: do not call into libc in symbolizer and in other code (this causes recursion and crashes)

Modified:
    compiler-rt/trunk/lib/tsan/rtl/tsan_defs.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.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_rtl_thread.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize_addr2line_linux.cc
    compiler-rt/trunk/lib/tsan/unit_tests/tsan_platform_test.cc

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_defs.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_defs.h?rev=157466&r1=157465&r2=157466&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_defs.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_defs.h Fri May 25 06:15:04 2012
@@ -169,6 +169,7 @@
 char* internal_strdup(const char *s);
 const char *internal_strstr(const char *where, const char *what);
 const char *internal_strchr(const char *where, char what);
+const char *internal_strrchr(const char *where, char what);
 
 struct MD5Hash {
   u64 hash[2];

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=157466&r1=157465&r2=157466&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Fri May 25 06:15:04 2012
@@ -138,10 +138,7 @@
 /**/
 
 #define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__)
-#define TSAN_INTERCEPT(func) \
-    if (!INTERCEPT_FUNCTION(func) && flags()->verbosity) \
-      Printf("ThreadSanitizer: failed to intercept '" #func "' function\n"); \
-/**/
+#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
 
 // May be overriden by front-end.
 extern "C" void WEAK __tsan_malloc_hook(void *ptr, uptr size) {
@@ -1551,6 +1548,10 @@
   return (const char*)REAL(strchr)((void*)where, what);
 }
 
+const char *internal_strrchr(const char *where, char what) {
+  return (const char*)REAL(strrchr)((void*)where, what);
+}
+
 void internal_start_thread(void(*func)(void *arg), void *arg) {
   void *th;
   REAL(pthread_create)(&th, 0, (void*(*)(void *arg))func, arg);

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=157466&r1=157465&r2=157466&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_platform.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_platform.h Fri May 25 06:15:04 2012
@@ -83,10 +83,11 @@
 uptr internal_filesize(fd_t fd);  // -1 on error.
 uptr internal_read(fd_t fd, void *p, uptr size);
 uptr internal_write(fd_t fd, const void *p, uptr size);
+int internal_dup2(int oldfd, int newfd);
 const char *internal_getpwd();
 
 uptr GetTlsSize();
-void GetThreadStackAndTls(uptr *stk_addr, uptr *stk_size,
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
                           uptr *tls_addr, uptr *tls_size);
 
 }  // 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=157466&r1=157465&r2=157466&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc Fri May 25 06:15:04 2012
@@ -79,6 +79,11 @@
 # endif
 }
 
+static void my_munmap(void *addr, size_t length) {
+  ScopedInRtl in_rtl;
+  syscall(__NR_munmap, addr, length);
+}
+
 void internal_yield() {
   ScopedInRtl in_rtl;
   syscall(__NR_sched_yield);
@@ -116,6 +121,11 @@
   return syscall(__NR_write, fd, p, size);
 }
 
+int internal_dup2(int oldfd, int newfd) {
+  ScopedInRtl in_rtl;
+  return syscall(__NR_dup2, oldfd, newfd);
+}
+
 const char *internal_getpwd() {
   return getenv("PWD");
 }
@@ -230,25 +240,75 @@
   return g_tls_size;
 }
 
-void GetThreadStackAndTls(uptr *stk_addr, uptr *stk_size,
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
                           uptr *tls_addr, uptr *tls_size) {
-  *stk_addr = 0;
-  *stk_size = 0;
-  pthread_attr_t attr;
-  if (pthread_getattr_np(pthread_self(), &attr) == 0) {
-    pthread_attr_getstack(&attr, (void**)stk_addr, (size_t*)stk_size);
-    pthread_attr_destroy(&attr);
-  }
   arch_prctl(ARCH_GET_FS, tls_addr);
   *tls_addr -= g_tls_size;
   *tls_size = g_tls_size;
 
-  // 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;
+  if (main) {
+    uptr kBufSize = 1 << 20;
+    char *buf = (char*)my_mmap(0, kBufSize, PROT_READ | PROT_WRITE,
+                               MAP_PRIVATE | MAP_ANON, -1, 0);
+    fd_t maps = internal_open("/proc/self/maps", false);
+    if (maps == kInvalidFd) {
+      Printf("Failed to open /proc/self/maps\n");
+      Die();
+    }
+    char *end = buf;
+    while (end + kPageSize < buf + kBufSize) {
+      uptr read = internal_read(maps, end, kPageSize);
+      if ((int)read <= 0)
+        break;
+      end += read;
+    }
+    end[0] = 0;
+    end = (char*)internal_strstr(buf, "[stack]");
+    if (end == 0) {
+      Printf("Can't find [stack] in /proc/self/maps\n");
+      Die();
+    }
+    end[0] = 0;
+    char *pos = (char*)internal_strrchr(buf, '\n');
+    if (pos == 0) {
+      Printf("Can't find [stack] in /proc/self/maps\n");
+      Die();
+    }
+    uptr stack = 0;
+    for (; pos++;) {
+      uptr num = 0;
+      if (pos[0] >= '0' && pos[0] <= '9')
+        num = pos[0] - '0';
+      else if (pos[0] >= 'a' && pos[0] <= 'f')
+        num = pos[0] - 'a' + 10;
+      else
+        break;
+      stack = stack * 16 + num;
+    }
+    internal_close(maps);
+    my_munmap(buf, kBufSize);
+
+    struct rlimit rl;
+    CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
+
+    *stk_addr = stack;
+    *stk_size = rl.rlim_cur;
+  } else {
+    *stk_addr = 0;
+    *stk_size = 0;
+    pthread_attr_t attr;
+    if (pthread_getattr_np(pthread_self(), &attr) == 0) {
+      pthread_attr_getstack(&attr, (void**)stk_addr, (size_t*)stk_size);
+      pthread_attr_destroy(&attr);
+    }
+
+    // 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;
+    }
   }
 }
 

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc?rev=157466&r1=157465&r2=157466&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_thread.cc Fri May 25 06:15:04 2012
@@ -138,7 +138,7 @@
   uptr stk_size = 0;
   uptr tls_addr = 0;
   uptr tls_size = 0;
-  GetThreadStackAndTls(&stk_addr, &stk_size, &tls_addr, &tls_size);
+  GetThreadStackAndTls(tid == 0, &stk_addr, &stk_size, &tls_addr, &tls_size);
 
   MemoryResetRange(thr, /*pc=*/ 1, stk_addr, stk_size);
 

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize_addr2line_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize_addr2line_linux.cc?rev=157466&r1=157465&r2=157466&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize_addr2line_linux.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize_addr2line_linux.cc Fri May 25 06:15:04 2012
@@ -18,7 +18,6 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
-#include <string.h>
 #include <errno.h>
 #include <link.h>
 #include <linux/limits.h>
@@ -59,22 +58,23 @@
   }
   int pid = fork();
   if (pid == 0) {
-    close(STDOUT_FILENO);
-    close(STDIN_FILENO);
-    dup2(outfd[0], STDIN_FILENO);
-    dup2(infd[1], STDOUT_FILENO);
-    close(outfd[0]);
-    close(outfd[1]);
-    close(infd[0]);
-    close(infd[1]);
+    flags()->log_fileno = STDERR_FILENO;
+    internal_close(STDOUT_FILENO);
+    internal_close(STDIN_FILENO);
+    internal_dup2(outfd[0], STDIN_FILENO);
+    internal_dup2(infd[1], STDOUT_FILENO);
+    internal_close(outfd[0]);
+    internal_close(outfd[1]);
+    internal_close(infd[0]);
+    internal_close(infd[1]);
     execl("/usr/bin/addr2line", "/usr/bin/addr2line", "-Cfe", m->fullname, 0);
     _exit(0);
   } else if (pid < 0) {
     Printf("ThreadSanitizer: failed to fork symbolizer\n");
     Die();
   }
-  close(outfd[0]);
-  close(infd[1]);
+  internal_close(outfd[0]);
+  internal_close(infd[1]);
   m->inp_fd = infd[0];
   m->out_fd = outfd[1];
 }
@@ -92,7 +92,7 @@
   ModuleDesc *m = (ModuleDesc*)internal_alloc(MBlockReportStack,
                                               sizeof(ModuleDesc));
   m->fullname = internal_strdup(info->dlpi_name);
-  m->name = strrchr(m->fullname, '/');  // FIXME: internal_strrchr
+  m->name = internal_strrchr(m->fullname, '/');
   if (m->name)
     m->name += 1;
   else
@@ -173,12 +173,12 @@
   ReportStack *res = NewFrame(addr);
   res->module = internal_strdup(m->name);
   res->offset = offset;
-  char *pos = strchr(func, '\n');
+  char *pos = (char*)internal_strchr(func, '\n');
   if (pos && func[0] != '?') {
     res->func = (char*)internal_alloc(MBlockReportStack, pos - func + 1);
     internal_memcpy(res->func, func, pos - func);
     res->func[pos - func] = 0;
-    char *pos2 = strchr(pos, ':');
+    char *pos2 = (char*)internal_strchr(pos, ':');
     if (pos2) {
       res->file = (char*)internal_alloc(MBlockReportStack, pos2 - pos - 1 + 1);
       internal_memcpy(res->file, pos + 1, pos2 - pos - 1);

Modified: compiler-rt/trunk/lib/tsan/unit_tests/tsan_platform_test.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/unit_tests/tsan_platform_test.cc?rev=157466&r1=157465&r2=157466&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/unit_tests/tsan_platform_test.cc (original)
+++ compiler-rt/trunk/lib/tsan/unit_tests/tsan_platform_test.cc Fri May 25 06:15:04 2012
@@ -15,13 +15,13 @@
 
 namespace __tsan {
 
-static void *TestThreadInfo(void *arg) {
+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(&stk_addr, &stk_size, &tls_addr, &tls_size);
+  GetThreadStackAndTls(main, &stk_addr, &stk_size, &tls_addr, &tls_size);
   // Printf("stk=%lx-%lx(%lu)\n", stk_addr, stk_addr + stk_size, stk_size);
   // Printf("tls=%lx-%lx(%lu)\n", tls_addr, tls_addr + tls_size, tls_size);
 
@@ -42,16 +42,20 @@
   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(0);
+  TestThreadInfo(true);
 }
 
 TEST(Platform, ThreadInfoWorker) {
   pthread_t t;
-  pthread_create(&t, 0, TestThreadInfo, 0);
+  pthread_create(&t, 0, WorkerThread, 0);
   pthread_join(t, 0);
 }
 





More information about the llvm-commits mailing list