summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/tsan
diff options
context:
space:
mode:
authorKuba Brecka <kuba.brecka@gmail.com>2016-03-16 15:39:20 +0000
committerKuba Brecka <kuba.brecka@gmail.com>2016-03-16 15:39:20 +0000
commit46bf454d184324ca2f6c96c82cb25b491ce46ce2 (patch)
tree31bd25607307c50d0388d4d4a904d3a679fcef04 /compiler-rt/lib/tsan
parent60228bdb80a836a8f3ea37e8e8a1d51d3e24a503 (diff)
downloadbcm5719-llvm-46bf454d184324ca2f6c96c82cb25b491ce46ce2.tar.gz
bcm5719-llvm-46bf454d184324ca2f6c96c82cb25b491ce46ce2.zip
[tsan] Detect uses of uninitialized, destroyed and invalid mutexes
This patch adds a new TSan report type, ReportTypeMutexInvalidAccess, which is triggered when pthread_mutex_lock or pthread_mutex_unlock returns EINVAL (this means the mutex is invalid, uninitialized or already destroyed). Differential Revision: http://reviews.llvm.org/D18132 llvm-svn: 263641
Diffstat (limited to 'compiler-rt/lib/tsan')
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_debugging.cc1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_interceptors.cc4
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_report.cc2
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_report.h1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl.h1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc8
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_suppressions.cc2
7 files changed, 19 insertions, 0 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_debugging.cc b/compiler-rt/lib/tsan/rtl/tsan_debugging.cc
index c43f78380f3..16d52a979fe 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_debugging.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_debugging.cc
@@ -25,6 +25,7 @@ static const char *ReportTypeDescription(ReportType typ) {
if (typ == ReportTypeThreadLeak) return "thread-leak";
if (typ == ReportTypeMutexDestroyLocked) return "locked-mutex-destroy";
if (typ == ReportTypeMutexDoubleLock) return "mutex-double-lock";
+ if (typ == ReportTypeMutexInvalidAccess) return "mutex-invalid-access";
if (typ == ReportTypeMutexBadUnlock) return "mutex-bad-unlock";
if (typ == ReportTypeMutexBadReadLock) return "mutex-bad-read-lock";
if (typ == ReportTypeMutexBadReadUnlock) return "mutex-bad-read-unlock";
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
index 3b7361f1371..029fe5c623d 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
@@ -2409,6 +2409,10 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
MutexRepair(((TsanInterceptorContext *)ctx)->thr, \
((TsanInterceptorContext *)ctx)->pc, (uptr)m)
+#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) \
+ MutexInvalidAccess(((TsanInterceptorContext *)ctx)->thr, \
+ ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
+
#if !SANITIZER_MAC
#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \
HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \
diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.cc b/compiler-rt/lib/tsan/rtl/tsan_report.cc
index 1b7a62ca247..5c018c8f7b9 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_report.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_report.cc
@@ -96,6 +96,8 @@ static const char *ReportTypeString(ReportType typ) {
return "destroy of a locked mutex";
if (typ == ReportTypeMutexDoubleLock)
return "double lock of a mutex";
+ if (typ == ReportTypeMutexInvalidAccess)
+ return "use of an invalid mutex (e.g. uninitialized or destroyed)";
if (typ == ReportTypeMutexBadUnlock)
return "unlock of an unlocked mutex (or by a wrong thread)";
if (typ == ReportTypeMutexBadReadLock)
diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.h b/compiler-rt/lib/tsan/rtl/tsan_report.h
index 3e344a048e4..bcdd72c4f08 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_report.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_report.h
@@ -27,6 +27,7 @@ enum ReportType {
ReportTypeThreadLeak,
ReportTypeMutexDestroyLocked,
ReportTypeMutexDoubleLock,
+ ReportTypeMutexInvalidAccess,
ReportTypeMutexBadUnlock,
ReportTypeMutexBadReadLock,
ReportTypeMutexBadReadUnlock,
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
index 9b9f29a1e49..057a3a6b751 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
@@ -695,6 +695,7 @@ void MutexReadLock(ThreadState *thr, uptr pc, uptr addr, bool try_lock = false);
void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr);
void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr);
void MutexRepair(ThreadState *thr, uptr pc, uptr addr); // call on EOWNERDEAD
+void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr);
void Acquire(ThreadState *thr, uptr pc, uptr addr);
// AcquireGlobal synchronizes the current thread with all other threads.
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
index 62ab7aa6b2b..c5682873af1 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cc
@@ -350,6 +350,14 @@ void MutexRepair(ThreadState *thr, uptr pc, uptr addr) {
s->mtx.Unlock();
}
+void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr) {
+ DPrintf("#%d: MutexInvalidAccess %zx\n", thr->tid, addr);
+ SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
+ u64 mid = s->GetId();
+ s->mtx.Unlock();
+ ReportMutexMisuse(thr, pc, ReportTypeMutexInvalidAccess, addr, mid);
+}
+
void Acquire(ThreadState *thr, uptr pc, uptr addr) {
DPrintf("#%d: Acquire %zx\n", thr->tid, addr);
if (thr->ignore_sync)
diff --git a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc
index 64a5a66728a..aea3cb978cb 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc
@@ -80,6 +80,8 @@ static const char *conv(ReportType typ) {
return kSuppressionMutex;
else if (typ == ReportTypeMutexDoubleLock)
return kSuppressionMutex;
+ else if (typ == ReportTypeMutexInvalidAccess)
+ return kSuppressionMutex;
else if (typ == ReportTypeMutexBadUnlock)
return kSuppressionMutex;
else if (typ == ReportTypeMutexBadReadLock)
OpenPOWER on IntegriCloud