diff options
-rw-r--r-- | compiler-rt/lib/lsan/lsan_common.cc | 28 | ||||
-rw-r--r-- | compiler-rt/lib/lsan/lsan_common_mac.cc | 7 | ||||
-rw-r--r-- | compiler-rt/lib/lsan/lsan_flags.inc | 2 | ||||
-rw-r--r-- | compiler-rt/lib/sanitizer_common/sanitizer_mac.cc | 25 | ||||
-rw-r--r-- | compiler-rt/test/lsan/TestCases/many_tls_keys.cc | 94 |
5 files changed, 22 insertions, 134 deletions
diff --git a/compiler-rt/lib/lsan/lsan_common.cc b/compiler-rt/lib/lsan/lsan_common.cc index 9f862ac96f1..a6b3453f5a0 100644 --- a/compiler-rt/lib/lsan/lsan_common.cc +++ b/compiler-rt/lib/lsan/lsan_common.cc @@ -265,21 +265,19 @@ static void ProcessThreads(SuspendedThreadsList const &suspended_threads, } if (flags()->use_tls) { - if (tls_begin) { - LOG_THREADS("TLS at %p-%p.\n", tls_begin, tls_end); - // If the tls and cache ranges don't overlap, scan full tls range, - // otherwise, only scan the non-overlapping portions - if (cache_begin == cache_end || tls_end < cache_begin || - tls_end > cache_end) { - ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable); - } else { - if (tls_begin < cache_begin) - ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS", - kReachable); - if (tls_end > cache_end) - ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", - kReachable); - } + LOG_THREADS("TLS at %p-%p.\n", tls_begin, tls_end); + if (cache_begin == cache_end) { + ScanRangeForPointers(tls_begin, tls_end, frontier, "TLS", kReachable); + } else { + // Because LSan should not be loaded with dlopen(), we can assume + // that allocator cache will be part of static TLS image. + CHECK_LE(tls_begin, cache_begin); + CHECK_GE(tls_end, cache_end); + if (tls_begin < cache_begin) + ScanRangeForPointers(tls_begin, cache_begin, frontier, "TLS", + kReachable); + if (tls_end > cache_end) + ScanRangeForPointers(cache_end, tls_end, frontier, "TLS", kReachable); } if (dtls && !DTLSInDestruction(dtls)) { for (uptr j = 0; j < dtls->dtv_size; ++j) { diff --git a/compiler-rt/lib/lsan/lsan_common_mac.cc b/compiler-rt/lib/lsan/lsan_common_mac.cc index 839dea4ad3b..5ee1e228691 100644 --- a/compiler-rt/lib/lsan/lsan_common_mac.cc +++ b/compiler-rt/lib/lsan/lsan_common_mac.cc @@ -91,7 +91,12 @@ LoadedModule *GetLinker() { return nullptr; } // Required on Linux for initialization of TLS behavior, but should not be // required on Darwin. -void InitializePlatformSpecificModules() {} +void InitializePlatformSpecificModules() { + if (flags()->use_tls) { + Report("use_tls=1 is not supported on Darwin.\n"); + Die(); + } +} // Scans global variables for heap pointers. void ProcessGlobalRegions(Frontier *frontier) { diff --git a/compiler-rt/lib/lsan/lsan_flags.inc b/compiler-rt/lib/lsan/lsan_flags.inc index e390e2ae5a1..8135bdcff01 100644 --- a/compiler-rt/lib/lsan/lsan_flags.inc +++ b/compiler-rt/lib/lsan/lsan_flags.inc @@ -30,7 +30,7 @@ LSAN_FLAG(bool, use_globals, true, "Root set: include global variables (.data and .bss)") LSAN_FLAG(bool, use_stacks, true, "Root set: include thread stacks") LSAN_FLAG(bool, use_registers, true, "Root set: include thread registers") -LSAN_FLAG(bool, use_tls, true, +LSAN_FLAG(bool, use_tls, !SANITIZER_MAC, "Root set: include TLS and thread-specific storage") LSAN_FLAG(bool, use_root_regions, true, "Root set: include regions added via __lsan_register_root_region().") diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc index 6fa2e4a661d..2f990b805ff 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc @@ -370,27 +370,6 @@ uptr GetTlsSize() { void InitTlsSize() { } -uptr TlsBaseAddr() { - uptr segbase = 0; -#if defined(__x86_64__) - asm("movq %%gs:0,%0" : "=r"(segbase)); -#elif defined(__i386__) - asm("movl %%gs:0,%0" : "=r"(segbase)); -#endif - return segbase; -} - -// The size of the tls on darwin does not appear to be well documented, -// however the vm memory map suggests that it is 1024 uptrs in size, -// with a size of 0x2000 bytes on x86_64 and 0x1000 bytes on i386. -uptr TlsSize() { -#if defined(__x86_64__) || defined(__i386__) - return 1024 * sizeof(uptr); -#else - return 0; -#endif -} - void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, uptr *tls_addr, uptr *tls_size) { #if !SANITIZER_GO @@ -398,8 +377,8 @@ void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size, GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom); *stk_addr = stack_bottom; *stk_size = stack_top - stack_bottom; - *tls_addr = TlsBaseAddr(); - *tls_size = TlsSize(); + *tls_addr = 0; + *tls_size = 0; #else *stk_addr = 0; *stk_size = 0; diff --git a/compiler-rt/test/lsan/TestCases/many_tls_keys.cc b/compiler-rt/test/lsan/TestCases/many_tls_keys.cc deleted file mode 100644 index ae577677023..00000000000 --- a/compiler-rt/test/lsan/TestCases/many_tls_keys.cc +++ /dev/null @@ -1,94 +0,0 @@ -// Test that lsan handles tls correctly for many threads -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" -// RUN: %clangxx_lsan %s -DUSE_THREAD -o %t-thread -// RUN: %clangxx_lsan %s -DUSE_PTHREAD -o %t-pthread -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t-thread 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t-thread 2>&1 -// RUN: %env_lsan_opts="" %run %t-thread 2>&1 -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t-pthread 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t-pthread 2>&1 -// RUN: %env_lsan_opts="" %run %t-pthread 2>&1 - -#include <assert.h> -#include <limits.h> -#include <pthread.h> -#include <stdlib.h> -#include <unistd.h> - -static const int NUM_THREADS = 10; - -pthread_cond_t cond = PTHREAD_COND_INITIALIZER; -pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -int finished = 0; - -#if USE_THREAD -__thread void *ptr1; -__thread void *ptr2; -__thread void *ptr3; -__thread void *ptr4; -__thread void *ptr5; - -void alloc() { - ptr1 = malloc(1111); - ptr2 = malloc(2222); - ptr3 = malloc(3333); - ptr4 = malloc(4444); - ptr5 = malloc(5555); -} - -#elif USE_PTHREAD -// We won't be able to create the maximum number of keys, due to other users -// of the tls, but we'll use as many keys as we can before failing to create -// a new key. -pthread_key_t keys[PTHREAD_KEYS_MAX]; -static const int PTHREAD_KEY_INVALID = 0xffffffff; - -void alloc() { - for (int i = 0; i < PTHREAD_KEYS_MAX; ++i) { - void *ptr = malloc(123); - if ((keys[i] == PTHREAD_KEY_INVALID) || pthread_setspecific(keys[i], ptr)) { - free(ptr); - break; - } - } -} - -void pthread_destructor(void *arg) { - assert(0 && "pthread destructors shouldn't be called"); -} -#endif - -void *thread_start(void *arg) { - alloc(); - - pthread_mutex_lock(&mutex); - finished++; - pthread_mutex_unlock(&mutex); - - // don't exit, to intentionally leak tls data - while (1) - sleep(100); -} - -int main() { -#if USE_PTHREAD - for (int i = 0; i < PTHREAD_KEYS_MAX; ++i) { - if (pthread_key_create(&keys[i], pthread_destructor)) { - keys[i] = PTHREAD_KEY_INVALID; - break; - } - } -#endif - - pthread_t thread[NUM_THREADS]; - for (int i = 0; i < NUM_THREADS; ++i) { - assert(0 == pthread_create(&thread[i], 0, thread_start, 0)); - } - // spin until all threads have finished - while (finished < NUM_THREADS) - sleep(1); - exit(0); -} - -// CHECK: LeakSanitizer: detected memory leaks -// CHECK: SUMMARY: {{(Leak|Address)}}Sanitizer: |