summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2013-03-21 15:37:39 +0000
committerDmitry Vyukov <dvyukov@google.com>2013-03-21 15:37:39 +0000
commit0851fa881969d5f16540155bd85ce0cd2df95da3 (patch)
treef8289002528b1a894d4fdd5a9a96dfefc2708ecf
parent2c3b919ad3dc38fb1a86a43526f009a6fdeeb6bc (diff)
downloadbcm5719-llvm-0851fa881969d5f16540155bd85ce0cd2df95da3.tar.gz
bcm5719-llvm-0851fa881969d5f16540155bd85ce0cd2df95da3.zip
tsan: better reporting for races on vptr
explicitly say "ctor/dtor vs virtual call" llvm-svn: 177640
-rw-r--r--compiler-rt/lib/tsan/lit_tests/vptr_harmful_race.cc4
-rw-r--r--compiler-rt/lib/tsan/lit_tests/vptr_harmful_race2.cc51
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_interface.h1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_interface_inl.h16
-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_report.cc7
8 files changed, 79 insertions, 4 deletions
diff --git a/compiler-rt/lib/tsan/lit_tests/vptr_harmful_race.cc b/compiler-rt/lib/tsan/lit_tests/vptr_harmful_race.cc
index f51ba7ee57f..76d31c00ad4 100644
--- a/compiler-rt/lib/tsan/lit_tests/vptr_harmful_race.cc
+++ b/compiler-rt/lib/tsan/lit_tests/vptr_harmful_race.cc
@@ -2,6 +2,7 @@
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
+#include <unistd.h>
struct A {
A() {
@@ -34,6 +35,7 @@ void *Thread1(void *x) {
}
void *Thread2(void *x) {
+ sleep(1);
delete obj;
return NULL;
}
@@ -46,4 +48,4 @@ int main() {
pthread_join(t[1], NULL);
}
-// CHECK: WARNING: ThreadSanitizer: data race
+// CHECK: WARNING: ThreadSanitizer: data race on vptr
diff --git a/compiler-rt/lib/tsan/lit_tests/vptr_harmful_race2.cc b/compiler-rt/lib/tsan/lit_tests/vptr_harmful_race2.cc
new file mode 100644
index 00000000000..4bcf1a4d8b8
--- /dev/null
+++ b/compiler-rt/lib/tsan/lit_tests/vptr_harmful_race2.cc
@@ -0,0 +1,51 @@
+// RUN: %clangxx_tsan -O1 %s -o %t && %t 2>&1 | FileCheck %s
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <unistd.h>
+
+struct A {
+ A() {
+ sem_init(&sem_, 0, 0);
+ }
+ virtual void F() {
+ }
+ void Done() {
+ sem_post(&sem_);
+ }
+ virtual ~A() {
+ sem_wait(&sem_);
+ sem_destroy(&sem_);
+ }
+ sem_t sem_;
+};
+
+struct B : A {
+ virtual void F() {
+ }
+ virtual ~B() { }
+};
+
+static A *obj = new B;
+
+void *Thread1(void *x) {
+ sleep(1);
+ obj->F();
+ obj->Done();
+ return NULL;
+}
+
+void *Thread2(void *x) {
+ delete obj;
+ return NULL;
+}
+
+int main() {
+ pthread_t t[2];
+ pthread_create(&t[0], NULL, Thread1, NULL);
+ pthread_create(&t[1], NULL, Thread2, NULL);
+ pthread_join(t[0], NULL);
+ pthread_join(t[1], NULL);
+}
+
+// CHECK: WARNING: ThreadSanitizer: data race
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface.h b/compiler-rt/lib/tsan/rtl/tsan_interface.h
index 28eea14210d..24526615db8 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interface.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_interface.h
@@ -41,6 +41,7 @@ void __tsan_write4(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
void __tsan_write8(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
void __tsan_write16(void *addr) SANITIZER_INTERFACE_ATTRIBUTE;
+void __tsan_vptr_read(void **vptr_p) SANITIZER_INTERFACE_ATTRIBUTE;
void __tsan_vptr_update(void **vptr_p, void *new_val)
SANITIZER_INTERFACE_ATTRIBUTE;
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_inl.h b/compiler-rt/lib/tsan/rtl/tsan_interface_inl.h
index 29e2b21ea9c..0187e49d96e 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interface_inl.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_interface_inl.h
@@ -52,8 +52,20 @@ void __tsan_write8(void *addr) {
void __tsan_vptr_update(void **vptr_p, void *new_val) {
CHECK_EQ(sizeof(vptr_p), 8);
- if (*vptr_p != new_val)
- MemoryWrite(cur_thread(), CALLERPC, (uptr)vptr_p, kSizeLog8);
+ if (*vptr_p != new_val) {
+ ThreadState *thr = cur_thread();
+ thr->is_vptr_access = true;
+ MemoryWrite(thr, CALLERPC, (uptr)vptr_p, kSizeLog8);
+ thr->is_vptr_access = false;
+ }
+}
+
+void __tsan_vptr_read(void **vptr_p) {
+ CHECK_EQ(sizeof(vptr_p), 8);
+ ThreadState *thr = cur_thread();
+ thr->is_vptr_access = true;
+ MemoryRead(thr, CALLERPC, (uptr)vptr_p, kSizeLog8);
+ thr->is_vptr_access = false;
}
void __tsan_func_entry(void *pc) {
diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.cc b/compiler-rt/lib/tsan/rtl/tsan_report.cc
index b394c406dcc..30e5488c02d 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_report.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_report.cc
@@ -46,6 +46,8 @@ const char *thread_name(char *buf, int tid) {
static const char *ReportTypeString(ReportType typ) {
if (typ == ReportTypeRace)
return "data race";
+ if (typ == ReportTypeVptrRace)
+ return "data race on vptr (ctor/dtor vs virtual call)";
if (typ == ReportTypeUseAfterFree)
return "heap-use-after-free";
if (typ == ReportTypeThreadLeak)
diff --git a/compiler-rt/lib/tsan/rtl/tsan_report.h b/compiler-rt/lib/tsan/rtl/tsan_report.h
index b2b7b53306d..eacb10c819d 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_report.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_report.h
@@ -20,6 +20,7 @@ namespace __tsan {
enum ReportType {
ReportTypeRace,
+ ReportTypeVptrRace,
ReportTypeUseAfterFree,
ReportTypeThreadLeak,
ReportTypeMutexDestroyLocked,
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
index e57fcc735d1..c216a80f1da 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
@@ -426,6 +426,7 @@ struct ThreadState {
bool in_symbolizer;
bool is_alive;
bool is_freeing;
+ bool is_vptr_access;
const uptr stk_addr;
const uptr stk_size;
const uptr tls_addr;
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc
index 18ab18e0cbf..50c531177dc 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc
@@ -616,7 +616,12 @@ void ReportRace(ThreadState *thr) {
Context *ctx = CTX();
ThreadRegistryLock l0(ctx->thread_registry);
- ScopedReport rep(freed ? ReportTypeUseAfterFree : ReportTypeRace);
+ ReportType typ = ReportTypeRace;
+ if (thr->is_vptr_access)
+ typ = ReportTypeVptrRace;
+ else if (freed)
+ typ = ReportTypeUseAfterFree;
+ ScopedReport rep(typ);
const uptr kMop = 2;
StackTrace traces[kMop];
const uptr toppc = TraceTopPC(thr);
OpenPOWER on IntegriCloud