diff options
Diffstat (limited to 'compiler-rt/lib/tsan/rtl')
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_interceptors.cc | 99 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_interface_java.cc | 13 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_interface_java.h | 6 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl.cc | 1 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl.h | 3 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_stat.cc | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_stat.h | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_suppressions.cc | 5 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_suppressions.h | 1 |
9 files changed, 76 insertions, 56 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index 0b6291a7c38..c4bde58f142 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -22,6 +22,7 @@ #include "interception/interception.h" #include "tsan_interface.h" #include "tsan_platform.h" +#include "tsan_suppressions.h" #include "tsan_rtl.h" #include "tsan_mman.h" #include "tsan_fd.h" @@ -126,18 +127,16 @@ struct SignalContext { SignalDesc pending_signals[kSigCount]; }; -// Used to ignore interceptors coming directly from libjvm.so. -atomic_uintptr_t libjvm_begin; -atomic_uintptr_t libjvm_end; +// The object is 64-byte aligned, because we want hot data to be located in +// a single cache line if possible (it's accessed in every interceptor). +static ALIGNED(64) char libignore_placeholder[sizeof(LibIgnore)]; +static LibIgnore *libignore() { + return reinterpret_cast<LibIgnore*>(&libignore_placeholder[0]); +} -static bool libjvm_check(uptr pc) { - uptr begin = atomic_load(&libjvm_begin, memory_order_relaxed); - if (begin != 0 && pc >= begin) { - uptr end = atomic_load(&libjvm_end, memory_order_relaxed); - if (end != 0 && pc < end) - return true; - } - return false; +void InitializeLibIgnore() { + libignore()->Init(*GetSuppressionContext()); + libignore()->OnLibraryLoaded(); } } // namespace __tsan @@ -162,12 +161,14 @@ class ScopedInterceptor { private: ThreadState *const thr_; const int in_rtl_; + bool in_ignored_lib_; }; ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc) : thr_(thr) - , in_rtl_(thr->in_rtl) { + , in_rtl_(thr->in_rtl) + , in_ignored_lib_(false) { if (thr_->in_rtl == 0) { Initialize(thr); FuncEntry(thr, pc); @@ -176,9 +177,18 @@ ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname, } else { thr_->in_rtl++; } + if (!thr_->in_ignored_lib && libignore()->IsIgnored(pc)) { + in_ignored_lib_ = true; + thr_->in_ignored_lib = true; + ThreadIgnoreBegin(thr_); + } } ScopedInterceptor::~ScopedInterceptor() { + if (in_ignored_lib_) { + thr_->in_ignored_lib = false; + ThreadIgnoreEnd(thr_); + } thr_->in_rtl--; if (thr_->in_rtl == 0) { FuncExit(thr_); @@ -203,7 +213,7 @@ ScopedInterceptor::~ScopedInterceptor() { Printf("FATAL: ThreadSanitizer: failed to intercept %s\n", #func); \ Die(); \ } \ - if (thr->in_rtl > 1 || libjvm_check(pc)) \ + if (thr->in_rtl > 1 || thr->in_ignored_lib) \ return REAL(func)(__VA_ARGS__); \ /**/ @@ -246,6 +256,28 @@ TSAN_INTERCEPTOR(int, nanosleep, void *req, void *rem) { return res; } +TSAN_INTERCEPTOR(void*, dlopen, const char *filename, int flag) { + SCOPED_INTERCEPTOR_RAW(dlopen, filename, flag); + // dlopen will execute global constructors, so it must be not in rtl. + CHECK_EQ(thr->in_rtl, 1); + thr->in_rtl = 0; + void *res = REAL(dlopen)(filename, flag); + thr->in_rtl = 1; + libignore()->OnLibraryLoaded(); + return res; +} + +TSAN_INTERCEPTOR(int, dlclose, void *handle) { + SCOPED_INTERCEPTOR_RAW(dlclose, handle); + // dlclose will execute global destructors, so it must be not in rtl. + CHECK_EQ(thr->in_rtl, 1); + thr->in_rtl = 0; + int res = REAL(dlclose)(handle); + thr->in_rtl = 1; + libignore()->OnLibraryUnloaded(); + return res; +} + class AtExitContext { public: AtExitContext() @@ -441,7 +473,7 @@ TSAN_INTERCEPTOR(void, siglongjmp, uptr *env, int val) { } TSAN_INTERCEPTOR(void*, malloc, uptr size) { - if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC())) + if (cur_thread()->in_symbolizer) return __libc_malloc(size); void *p = 0; { @@ -458,7 +490,7 @@ TSAN_INTERCEPTOR(void*, __libc_memalign, uptr align, uptr sz) { } TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) { - if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC())) + if (cur_thread()->in_symbolizer) return __libc_calloc(size, n); if (__sanitizer::CallocShouldReturnNullDueToOverflow(size, n)) return AllocatorReturnNull(); @@ -474,7 +506,7 @@ TSAN_INTERCEPTOR(void*, calloc, uptr size, uptr n) { } TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) { - if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC())) + if (cur_thread()->in_symbolizer) return __libc_realloc(p, size); if (p) invoke_free_hook(p); @@ -489,7 +521,7 @@ TSAN_INTERCEPTOR(void*, realloc, void *p, uptr size) { TSAN_INTERCEPTOR(void, free, void *p) { if (p == 0) return; - if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC())) + if (cur_thread()->in_symbolizer) return __libc_free(p); invoke_free_hook(p); SCOPED_INTERCEPTOR_RAW(free, p); @@ -499,7 +531,7 @@ TSAN_INTERCEPTOR(void, free, void *p) { TSAN_INTERCEPTOR(void, cfree, void *p) { if (p == 0) return; - if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC())) + if (cur_thread()->in_symbolizer) return __libc_free(p); invoke_free_hook(p); SCOPED_INTERCEPTOR_RAW(cfree, p); @@ -508,13 +540,11 @@ TSAN_INTERCEPTOR(void, cfree, void *p) { TSAN_INTERCEPTOR(uptr, malloc_usable_size, void *p) { SCOPED_INTERCEPTOR_RAW(malloc_usable_size, p); - if (libjvm_check(pc)) - return malloc_usable_size(p); return user_alloc_usable_size(thr, pc, p); } #define OPERATOR_NEW_BODY(mangled_name) \ - if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC())) \ + if (cur_thread()->in_symbolizer) \ return __libc_malloc(size); \ void *p = 0; \ { \ @@ -550,7 +580,7 @@ void *operator new[](__sanitizer::uptr size, std::nothrow_t const&) { #define OPERATOR_DELETE_BODY(mangled_name) \ if (ptr == 0) return; \ - if (cur_thread()->in_symbolizer || libjvm_check(GET_CALLER_PC())) \ + if (cur_thread()->in_symbolizer) \ return __libc_free(ptr); \ invoke_free_hook(ptr); \ SCOPED_INTERCEPTOR_RAW(mangled_name, ptr); \ @@ -684,15 +714,6 @@ TSAN_INTERCEPTOR(const char*, strstr, const char *s1, const char *s2) { TSAN_INTERCEPTOR(char*, strdup, const char *str) { SCOPED_TSAN_INTERCEPTOR(strdup, str); - if (libjvm_check(pc)) { - // The memory must come from libc malloc, - // and we must not instrument accesses in this case. - uptr n = internal_strlen(str) + 1; - void *p = __libc_malloc(n); - if (p == 0) - return 0; - return (char*)internal_memcpy(p, str, n); - } // strdup will call malloc, so no instrumentation is required here. return REAL(strdup)(str); } @@ -747,23 +768,23 @@ TSAN_INTERCEPTOR(int, munmap, void *addr, long_t sz) { } TSAN_INTERCEPTOR(void*, memalign, uptr align, uptr sz) { - SCOPED_TSAN_INTERCEPTOR(memalign, align, sz); + SCOPED_INTERCEPTOR_RAW(memalign, align, sz); return user_alloc(thr, pc, sz, align); } TSAN_INTERCEPTOR(void*, valloc, uptr sz) { - SCOPED_TSAN_INTERCEPTOR(valloc, sz); + SCOPED_INTERCEPTOR_RAW(valloc, sz); return user_alloc(thr, pc, sz, GetPageSizeCached()); } TSAN_INTERCEPTOR(void*, pvalloc, uptr sz) { - SCOPED_TSAN_INTERCEPTOR(pvalloc, sz); + SCOPED_INTERCEPTOR_RAW(pvalloc, sz); sz = RoundUp(sz, GetPageSizeCached()); return user_alloc(thr, pc, sz, GetPageSizeCached()); } TSAN_INTERCEPTOR(int, posix_memalign, void **memptr, uptr align, uptr sz) { - SCOPED_TSAN_INTERCEPTOR(posix_memalign, memptr, align, sz); + SCOPED_INTERCEPTOR_RAW(posix_memalign, memptr, align, sz); *memptr = user_alloc(thr, pc, sz, align); return 0; } @@ -852,7 +873,7 @@ extern "C" void *__tsan_thread_start_func(void *arg) { TSAN_INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*), void * param) { - SCOPED_TSAN_INTERCEPTOR(pthread_create, th, attr, callback, param); + SCOPED_INTERCEPTOR_RAW(pthread_create, th, attr, callback, param); __sanitizer_pthread_attr_t myattr; if (attr == 0) { pthread_attr_init(&myattr); @@ -886,7 +907,7 @@ TSAN_INTERCEPTOR(int, pthread_create, } TSAN_INTERCEPTOR(int, pthread_join, void *th, void **ret) { - SCOPED_TSAN_INTERCEPTOR(pthread_join, th, ret); + SCOPED_INTERCEPTOR_RAW(pthread_join, th, ret); int tid = ThreadTid(thr, pc, (uptr)th); int res = BLOCK_REAL(pthread_join)(th, ret); if (res == 0) { @@ -1820,7 +1841,7 @@ TSAN_INTERCEPTOR(int, munlockall, void) { } TSAN_INTERCEPTOR(int, fork, int fake) { - SCOPED_TSAN_INTERCEPTOR(fork, fake); + SCOPED_INTERCEPTOR_RAW(fork, fake); int pid = REAL(fork)(fake); if (pid == 0) { // child @@ -2174,6 +2195,8 @@ void InitializeInterceptors() { TSAN_INTERCEPT(munlockall); TSAN_INTERCEPT(fork); + TSAN_INTERCEPT(dlopen); + TSAN_INTERCEPT(dlclose); TSAN_INTERCEPT(on_exit); TSAN_INTERCEPT(__cxa_atexit); diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc b/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc index 2ac3249acf5..53f14cf07b5 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interface_java.cc @@ -96,8 +96,6 @@ class ScopedJavaFunc { static u64 jctx_buf[sizeof(JavaContext) / sizeof(u64) + 1]; static JavaContext *jctx; -extern atomic_uintptr_t libjvm_begin; -extern atomic_uintptr_t libjvm_end; static BlockDesc *getblock(uptr addr) { uptr i = (addr - jctx->heap_begin) / kHeapAlignment; @@ -166,17 +164,6 @@ SyncVar* GetAndRemoveJavaSync(ThreadState *thr, uptr pc, uptr addr) { ScopedJavaFunc scoped(thr, caller_pc); \ /**/ -void __tsan_java_preinit(const char *libjvm_path) { - SCOPED_JAVA_FUNC(__tsan_java_preinit); - if (libjvm_path) { - uptr begin, end; - if (GetCodeRangeForFile(libjvm_path, &begin, &end)) { - atomic_store(&libjvm_begin, begin, memory_order_relaxed); - atomic_store(&libjvm_end, end, memory_order_relaxed); - } - } -} - void __tsan_java_init(jptr heap_begin, jptr heap_size) { SCOPED_JAVA_FUNC(__tsan_java_init); DPrintf("#%d: java_init(%p, %p)\n", thr->tid, heap_begin, heap_size); diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_java.h b/compiler-rt/lib/tsan/rtl/tsan_interface_java.h index a4a05aa2f5b..9ac78e074bb 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interface_java.h +++ b/compiler-rt/lib/tsan/rtl/tsan_interface_java.h @@ -34,11 +34,7 @@ extern "C" { typedef unsigned long jptr; // NOLINT -// Must be called before any other callback from Java, right after dlopen -// of JVM shared lib. If libjvm_path is specified, then all interceptors -// coming directly from JVM will be ignored. -void __tsan_java_preinit(const char *libjvm_path) INTERFACE_ATTRIBUTE; -// Must be called after __tsan_java_preinit but before any other callback. +// Must be called before any other callback from Java. void __tsan_java_init(jptr heap_begin, jptr heap_size) INTERFACE_ATTRIBUTE; // Must be called when the application exits. // Not necessary the last callback (concurrently running threads are OK). diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc index dcd98b03244..aa8934adab4 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc @@ -214,6 +214,7 @@ void Initialize(ThreadState *thr) { __sanitizer_set_report_path(flags()->log_path); InitializeSuppressions(); #ifndef TSAN_GO + InitializeLibIgnore(); // Initialize external symbolizer before internal threads are started. const char *external_symbolizer = flags()->external_symbolizer_path; if (external_symbolizer != 0 && external_symbolizer[0] != '\0') { diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h index ed7b7edcc29..9169aeb400c 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -29,6 +29,7 @@ #include "sanitizer_common/sanitizer_allocator.h" #include "sanitizer_common/sanitizer_allocator_internal.h" #include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_libignore.h" #include "sanitizer_common/sanitizer_suppressions.h" #include "sanitizer_common/sanitizer_thread_registry.h" #include "tsan_clock.h" @@ -434,6 +435,7 @@ struct ThreadState { const int unique_id; int in_rtl; bool in_symbolizer; + bool in_ignored_lib; bool is_alive; bool is_freeing; bool is_vptr_access; @@ -598,6 +600,7 @@ void MapThreadTrace(uptr addr, uptr size); void DontNeedShadowFor(uptr addr, uptr size); void InitializeShadowMemory(); void InitializeInterceptors(); +void InitializeLibIgnore(); void InitializeDynamicAnnotations(); void ReportRace(ThreadState *thr); diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.cc b/compiler-rt/lib/tsan/rtl/tsan_stat.cc index 3a2173e2806..96d5ee48623 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_stat.cc @@ -371,6 +371,8 @@ void StatOutput(u64 *stat) { name[StatInt_sigprocmask] = " sigprocmask "; name[StatInt_backtrace] = " backtrace "; name[StatInt_backtrace_symbols] = " backtrace_symbols "; + name[StatInt_dlopen] = " dlopen "; + name[StatInt_dlclose] = " dlclose "; name[StatAnnotation] = "Dynamic annotations "; name[StatAnnotateHappensBefore] = " HappensBefore "; diff --git a/compiler-rt/lib/tsan/rtl/tsan_stat.h b/compiler-rt/lib/tsan/rtl/tsan_stat.h index 526190c2d28..43c6b1cca42 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_stat.h +++ b/compiler-rt/lib/tsan/rtl/tsan_stat.h @@ -366,6 +366,8 @@ enum StatType { StatInt_sigprocmask, StatInt_backtrace, StatInt_backtrace_symbols, + StatInt_dlopen, + StatInt_dlclose, // Dynamic annotations. StatAnnotation, diff --git a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc index 0a365b2dcc3..4b0ac04c48a 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc @@ -87,6 +87,11 @@ void InitializeSuppressions() { #endif } +SuppressionContext *GetSuppressionContext() { + CHECK_NE(g_ctx, 0); + return g_ctx; +} + SuppressionType conv(ReportType typ) { if (typ == ReportTypeRace) return SuppressionRace; diff --git a/compiler-rt/lib/tsan/rtl/tsan_suppressions.h b/compiler-rt/lib/tsan/rtl/tsan_suppressions.h index c618b3db4c2..fe7db588f50 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_suppressions.h +++ b/compiler-rt/lib/tsan/rtl/tsan_suppressions.h @@ -22,6 +22,7 @@ void InitializeSuppressions(); void PrintMatchedSuppressions(); uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp); uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp); +SuppressionContext *GetSuppressionContext(); } // namespace __tsan |

