From: Dmitry Vyukov Date: Fri, 25 May 2012 11:15:04 +0000 (+0000) Subject: tsan: do not call into libc in symbolizer and in other code (this causes recursion... X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7339eb197ba3d5ddf58e91e9185a0a77b231b7fc;p=platform%2Fupstream%2Fllvm.git tsan: do not call into libc in symbolizer and in other code (this causes recursion and crashes) llvm-svn: 157466 --- diff --git a/compiler-rt/lib/tsan/rtl/tsan_defs.h b/compiler-rt/lib/tsan/rtl/tsan_defs.h index d68bc35..74ed733 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 8eac562..a117018 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 5b2e62c..3c94f46 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 64ba6a8..6bb62e4 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 a74c85a..5ed037e 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 7583754..49c8eca 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 #include #include -#include #include #include #include @@ -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 cc86a74..c754bba 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); }