diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2016-06-03 11:48:27 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2016-06-03 11:48:27 +0000 |
commit | 031c1e40660c8eaaa418ce84b16b82b37ca32652 (patch) | |
tree | eb00e9d649aa7a2a8f7e5c4f3e7754d40729efab /lib/tsan | |
parent | 009632990e8c5b96eb0973782381fa0e778858ae (diff) |
tsan: rely on AnnotateRWLockCreateStatic to detect linker-initialized mutexes
The new annotation was added a while ago, but was not actually used.
Use the annotation to detect linker-initialized mutexes instead
of the broken IsGlobalVar which has both false positives and false
negatives. Remove IsGlobalVar mess.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@271663 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan')
-rw-r--r-- | lib/tsan/rtl/tsan_platform.h | 4 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_platform_linux.cc | 48 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_platform_mac.cc | 4 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl_mutex.cc | 29 |
4 files changed, 15 insertions, 70 deletions
diff --git a/lib/tsan/rtl/tsan_platform.h b/lib/tsan/rtl/tsan_platform.h index 118e01b09..2bd6637d0 100644 --- a/lib/tsan/rtl/tsan_platform.h +++ b/lib/tsan/rtl/tsan_platform.h @@ -757,10 +757,6 @@ void CheckAndProtect(); void InitializeShadowMemoryPlatform(); void FlushShadowMemory(); void WriteMemoryProfile(char *buf, uptr buf_size, uptr nthread, uptr nlive); - -// Says whether the addr relates to a global var. -// Guesses with high probability, may yield both false positives and negatives. -bool IsGlobalVar(uptr addr); int ExtractResolvFDs(void *state, int *fds, int nfd); int ExtractRecvmsgFDs(void *msg, int *fds, int nfd); diff --git a/lib/tsan/rtl/tsan_platform_linux.cc b/lib/tsan/rtl/tsan_platform_linux.cc index c10fce563..d7182fdc1 100644 --- a/lib/tsan/rtl/tsan_platform_linux.cc +++ b/lib/tsan/rtl/tsan_platform_linux.cc @@ -69,9 +69,6 @@ void *__libc_stack_end = 0; namespace __tsan { -static uptr g_data_start; -static uptr g_data_end; - #ifdef TSAN_RUNTIME_VMA // Runtime detected VMA size. uptr vmaSize; @@ -204,46 +201,6 @@ void InitializeShadowMemoryPlatform() { MapRodata(); } -static void InitDataSeg() { - MemoryMappingLayout proc_maps(true); - uptr start, end, offset; - char name[128]; -#if SANITIZER_FREEBSD - // On FreeBSD BSS is usually the last block allocated within the - // low range and heap is the last block allocated within the range - // 0x800000000-0x8ffffffff. - while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name), - /*protection*/ 0)) { - DPrintf("%p-%p %p %s\n", start, end, offset, name); - if ((start & 0xffff00000000ULL) == 0 && (end & 0xffff00000000ULL) == 0 && - name[0] == '\0') { - g_data_start = start; - g_data_end = end; - } - } -#else - bool prev_is_data = false; - while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name), - /*protection*/ 0)) { - DPrintf("%p-%p %p %s\n", start, end, offset, name); - bool is_data = offset != 0 && name[0] != 0; - // BSS may get merged with [heap] in /proc/self/maps. This is not very - // reliable. - bool is_bss = offset == 0 && - (name[0] == 0 || internal_strcmp(name, "[heap]") == 0) && prev_is_data; - if (g_data_start == 0 && is_data) - g_data_start = start; - if (is_bss) - g_data_end = end; - prev_is_data = is_data; - } -#endif - DPrintf("guessed data_start=%p data_end=%p\n", g_data_start, g_data_end); - CHECK_LT(g_data_start, g_data_end); - CHECK_GE((uptr)&g_data_start, g_data_start); - CHECK_LT((uptr)&g_data_start, g_data_end); -} - #endif // #ifndef SANITIZER_GO void InitializePlatformEarly() { @@ -315,14 +272,9 @@ void InitializePlatform() { #ifndef SANITIZER_GO CheckAndProtect(); InitTlsSize(); - InitDataSeg(); #endif } -bool IsGlobalVar(uptr addr) { - return g_data_start && addr >= g_data_start && addr < g_data_end; -} - #ifndef SANITIZER_GO // Extract file descriptors passed to glibc internal __res_iclose function. // This is required to properly "close" the fds, because we do not see internal diff --git a/lib/tsan/rtl/tsan_platform_mac.cc b/lib/tsan/rtl/tsan_platform_mac.cc index 7a906d524..4a8b92177 100644 --- a/lib/tsan/rtl/tsan_platform_mac.cc +++ b/lib/tsan/rtl/tsan_platform_mac.cc @@ -189,10 +189,6 @@ int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m, } #endif -bool IsGlobalVar(uptr addr) { - return false; -} - } // namespace __tsan #endif // SANITIZER_MAC diff --git a/lib/tsan/rtl/tsan_rtl_mutex.cc b/lib/tsan/rtl/tsan_rtl_mutex.cc index b5125b39b..3d700d824 100644 --- a/lib/tsan/rtl/tsan_rtl_mutex.cc +++ b/lib/tsan/rtl/tsan_rtl_mutex.cc @@ -84,21 +84,14 @@ void MutexCreate(ThreadState *thr, uptr pc, uptr addr, void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) { DPrintf("#%d: MutexDestroy %zx\n", thr->tid, addr); StatInc(thr, StatMutexDestroy); -#ifndef SANITIZER_GO - // Global mutexes not marked as LINKER_INITIALIZED - // cause tons of not interesting reports, so just ignore it. - if (IsGlobalVar(addr)) - return; -#endif - if (IsAppMem(addr)) { - CHECK(!thr->is_freeing); - thr->is_freeing = true; - MemoryWrite(thr, pc, addr, kSizeLog1); - thr->is_freeing = false; - } SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr); if (s == 0) return; + if (s->is_linker_init) { + // Destroy is no-op for linker-initialized mutexes. + s->mtx.Unlock(); + return; + } if (common_flags()->detect_deadlocks) { Callback cb(thr, pc); ctx->dd->MutexDestroy(&cb, &s->dd); @@ -128,8 +121,7 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) { rep.AddStack(trace, true); rep.AddLocation(addr, 1); OutputReport(thr, rep); - } - if (unlock_locked) { + SyncVar *s = ctx->metamap.GetIfExistsAndLock(addr); if (s != 0) { s->Reset(thr->proc()); @@ -137,6 +129,15 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) { } } thr->mset.Remove(mid); + // Imitate a memory write to catch unlock-destroy races. + // Do this outside of sync mutex, because it can report a race which locks + // sync mutexes. + if (IsAppMem(addr)) { + CHECK(!thr->is_freeing); + thr->is_freeing = true; + MemoryWrite(thr, pc, addr, kSizeLog1); + thr->is_freeing = false; + } // s will be destroyed and freed in MetaMap::FreeBlock. } |