diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2012-05-25 11:15:04 +0000 | 
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2012-05-25 11:15:04 +0000 | 
| commit | 7339eb197ba3d5ddf58e91e9185a0a77b231b7fc (patch) | |
| tree | 9e6f2c1f3e35d33788079508024428e54c1692bf | |
| parent | e86497ee1c2df7f88a49b4792dade697a8f4f5fa (diff) | |
| download | bcm5719-llvm-7339eb197ba3d5ddf58e91e9185a0a77b231b7fc.tar.gz bcm5719-llvm-7339eb197ba3d5ddf58e91e9185a0a77b231b7fc.zip  | |
tsan: do not call into libc in symbolizer and in other code (this causes recursion and crashes)
llvm-svn: 157466
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_defs.h | 1 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_interceptors.cc | 9 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_platform.h | 3 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc | 88 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_symbolize_addr2line_linux.cc | 28 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/unit_tests/tsan_platform_test.cc | 12 | 
7 files changed, 105 insertions, 38 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_defs.h b/compiler-rt/lib/tsan/rtl/tsan_defs.h index d68bc354482..74ed733afd3 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_defs.h +++ b/compiler-rt/lib/tsan/rtl/tsan_defs.h @@ -169,6 +169,7 @@ uptr internal_strlen(const char *s);  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]; diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index 8eac562a29e..a1170183a82 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -138,10 +138,7 @@ class ScopedInterceptor {  /**/  #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 @@ const char *internal_strchr(const char *where, char what) {    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); diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h index 5b2e62c9405..3c94f46f769 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform.h +++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h @@ -83,10 +83,11 @@ void internal_close(fd_t fd);  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 diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc index 64ba6a8e0b5..6bb62e45710 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc @@ -79,6 +79,11 @@ static void *my_mmap(void *addr, size_t length, int prot, int flags,  # 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 @@ uptr internal_write(fd_t fd, const void *p, uptr size) {    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 @@ uptr GetTlsSize() {    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; +    }    }  } diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc index a74c85a632c..5ed037e3992 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc @@ -138,7 +138,7 @@ void ThreadStart(ThreadState *thr, int tid) {    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); diff --git a/compiler-rt/lib/tsan/rtl/tsan_symbolize_addr2line_linux.cc b/compiler-rt/lib/tsan/rtl/tsan_symbolize_addr2line_linux.cc index 7583754011c..49c8eca886f 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_symbolize_addr2line_linux.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_symbolize_addr2line_linux.cc @@ -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 @@ static void NOINLINE InitModule(ModuleDesc *m) {    }    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 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {    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 *SymbolizeCode(uptr addr) {    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); diff --git a/compiler-rt/lib/tsan/unit_tests/tsan_platform_test.cc b/compiler-rt/lib/tsan/unit_tests/tsan_platform_test.cc index cc86a74420c..c754bba9cbf 100644 --- a/compiler-rt/lib/tsan/unit_tests/tsan_platform_test.cc +++ b/compiler-rt/lib/tsan/unit_tests/tsan_platform_test.cc @@ -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 @@ static void *TestThreadInfo(void *arg) {    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);  }  | 

