[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