summaryrefslogtreecommitdiff
path: root/lib/tsan
diff options
context:
space:
mode:
authorKuba Mracek <mracek@apple.com>2017-01-11 00:54:26 +0000
committerKuba Mracek <mracek@apple.com>2017-01-11 00:54:26 +0000
commit3a14afa51320e5583712a81e148896583065ed7b (patch)
tree94aeb371533d04463d411157ca1d6d6b7545fd8d /lib/tsan
parentcfd8d3e358eaed534a6ce5e6ce56f40b5550ec4e (diff)
[tsan] Implement a 'ignore_noninstrumented_modules' flag to better suppress false positive races
On Darwin, we currently use 'ignore_interceptors_accesses', which is a heavy-weight solution that simply turns of race detection in all interceptors. This was done to suppress false positives coming from system libraries (non-instrumented code), but it also silences a lot of real races. This patch implements an alternative approach that should allow us to enable interceptors and report races coming from them, but only if they are called directly from instrumented code. The patch matches the caller PC in each interceptors. For non-instrumented code, we call ThreadIgnoreBegin. The assumption here is that the number of instrumented modules is low. Most likely there's only one (the instrumented main executable) and all the other modules are system libraries (non-instrumented). Differential Revision: https://reviews.llvm.org/D28264 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@291631 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan')
-rw-r--r--lib/tsan/rtl/tsan_flags.inc3
-rw-r--r--lib/tsan/rtl/tsan_interceptors.cc55
-rw-r--r--lib/tsan/rtl/tsan_interceptors.h9
3 files changed, 33 insertions, 34 deletions
diff --git a/lib/tsan/rtl/tsan_flags.inc b/lib/tsan/rtl/tsan_flags.inc
index 071cf427d..a48545c43 100644
--- a/lib/tsan/rtl/tsan_flags.inc
+++ b/lib/tsan/rtl/tsan_flags.inc
@@ -79,5 +79,8 @@ TSAN_FLAG(bool, die_after_fork, true,
TSAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
TSAN_FLAG(bool, ignore_interceptors_accesses, false,
"Ignore reads and writes from all interceptors.")
+TSAN_FLAG(bool, ignore_noninstrumented_modules, false,
+ "Interceptors should only detect races when called from instrumented "
+ "modules.")
TSAN_FLAG(bool, shared_ptr_interceptor, true,
"Track atomic reference counting in libc++ shared_ptr and weak_ptr.")
diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc
index a3a50e13f..898f32df1 100644
--- a/lib/tsan/rtl/tsan_interceptors.cc
+++ b/lib/tsan/rtl/tsan_interceptors.cc
@@ -231,6 +231,8 @@ void InitializeLibIgnore() {
if (0 == internal_strcmp(s->type, kSuppressionLib))
libignore()->AddIgnoredLibrary(s->templ);
}
+ if (flags()->ignore_noninstrumented_modules)
+ libignore()->IgnoreNoninstrumentedModules(true);
libignore()->OnLibraryLoaded(0);
}
@@ -252,31 +254,20 @@ static unsigned g_thread_finalize_key;
ScopedInterceptor::ScopedInterceptor(ThreadState *thr, const char *fname,
uptr pc)
- : thr_(thr)
- , pc_(pc)
- , in_ignored_lib_(false) {
+ : thr_(thr), pc_(pc), in_ignored_lib_(false), ignoring_(false) {
Initialize(thr);
- if (!thr_->is_inited)
- return;
- if (!thr_->ignore_interceptors)
- FuncEntry(thr, pc);
+ if (!thr_->is_inited) return;
+ if (!thr_->ignore_interceptors) FuncEntry(thr, pc);
DPrintf("#%d: intercept %s()\n", thr_->tid, fname);
- if (!thr_->in_ignored_lib && libignore()->IsIgnored(pc)) {
- in_ignored_lib_ = true;
- thr_->in_ignored_lib = true;
- ThreadIgnoreBegin(thr_, pc_);
- }
- if (flags()->ignore_interceptors_accesses) ThreadIgnoreBegin(thr_, pc_);
+ ignoring_ =
+ !thr_->in_ignored_lib && (flags()->ignore_interceptors_accesses ||
+ libignore()->IsIgnored(pc, &in_ignored_lib_));
+ EnableIgnores();
}
ScopedInterceptor::~ScopedInterceptor() {
- if (!thr_->is_inited)
- return;
- if (flags()->ignore_interceptors_accesses) ThreadIgnoreEnd(thr_, pc_);
- if (in_ignored_lib_) {
- thr_->in_ignored_lib = false;
- ThreadIgnoreEnd(thr_, pc_);
- }
+ if (!thr_->is_inited) return;
+ DisableIgnores();
if (!thr_->ignore_interceptors) {
ProcessPendingSignals(thr_);
FuncExit(thr_);
@@ -284,20 +275,24 @@ ScopedInterceptor::~ScopedInterceptor() {
}
}
-void ScopedInterceptor::UserCallbackStart() {
- if (flags()->ignore_interceptors_accesses) ThreadIgnoreEnd(thr_, pc_);
- if (in_ignored_lib_) {
- thr_->in_ignored_lib = false;
- ThreadIgnoreEnd(thr_, pc_);
+void ScopedInterceptor::EnableIgnores() {
+ if (ignoring_) {
+ ThreadIgnoreBegin(thr_, pc_);
+ if (in_ignored_lib_) {
+ DCHECK(!thr_->in_ignored_lib);
+ thr_->in_ignored_lib = true;
+ }
}
}
-void ScopedInterceptor::UserCallbackEnd() {
- if (in_ignored_lib_) {
- thr_->in_ignored_lib = true;
- ThreadIgnoreBegin(thr_, pc_);
+void ScopedInterceptor::DisableIgnores() {
+ if (ignoring_) {
+ ThreadIgnoreEnd(thr_, pc_);
+ if (in_ignored_lib_) {
+ DCHECK(thr_->in_ignored_lib);
+ thr_->in_ignored_lib = false;
+ }
}
- if (flags()->ignore_interceptors_accesses) ThreadIgnoreBegin(thr_, pc_);
}
#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
diff --git a/lib/tsan/rtl/tsan_interceptors.h b/lib/tsan/rtl/tsan_interceptors.h
index a0f9a0753..72534f4a2 100644
--- a/lib/tsan/rtl/tsan_interceptors.h
+++ b/lib/tsan/rtl/tsan_interceptors.h
@@ -10,12 +10,13 @@ class ScopedInterceptor {
public:
ScopedInterceptor(ThreadState *thr, const char *fname, uptr pc);
~ScopedInterceptor();
- void UserCallbackStart();
- void UserCallbackEnd();
+ void DisableIgnores();
+ void EnableIgnores();
private:
ThreadState *const thr_;
const uptr pc_;
bool in_ignored_lib_;
+ bool ignoring_;
};
} // namespace __tsan
@@ -39,10 +40,10 @@ class ScopedInterceptor {
/**/
#define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_START() \
- si.UserCallbackStart();
+ si.DisableIgnores();
#define SCOPED_TSAN_INTERCEPTOR_USER_CALLBACK_END() \
- si.UserCallbackEnd();
+ si.EnableIgnores();
#define TSAN_INTERCEPTOR(ret, func, ...) INTERCEPTOR(ret, func, __VA_ARGS__)