summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/tsan/rtl
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib/tsan/rtl')
-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
6 files changed, 25 insertions, 3 deletions
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