From 0dc47b652dfbe0d61d153eded02bae9487a7b539 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 21 Mar 2013 15:37:39 +0000 Subject: [PATCH] tsan: better reporting for races on vptr explicitly say "ctor/dtor vs virtual call" git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@177640 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/tsan/lit_tests/vptr_harmful_race.cc | 4 +++- .../{vptr_harmful_race.cc => vptr_harmful_race2.cc} | 2 ++ lib/tsan/rtl/tsan_interface.h | 1 + lib/tsan/rtl/tsan_interface_inl.h | 16 ++++++++++++++-- lib/tsan/rtl/tsan_report.cc | 2 ++ lib/tsan/rtl/tsan_report.h | 1 + lib/tsan/rtl/tsan_rtl.h | 1 + lib/tsan/rtl/tsan_rtl_report.cc | 7 ++++++- 8 files changed, 30 insertions(+), 4 deletions(-) copy lib/tsan/lit_tests/{vptr_harmful_race.cc => vptr_harmful_race2.cc} (95%) diff --git a/lib/tsan/lit_tests/vptr_harmful_race.cc b/lib/tsan/lit_tests/vptr_harmful_race.cc index f51ba7ee5..76d31c00a 100644 --- a/lib/tsan/lit_tests/vptr_harmful_race.cc +++ b/lib/tsan/lit_tests/vptr_harmful_race.cc @@ -2,6 +2,7 @@ #include #include #include +#include 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/lib/tsan/lit_tests/vptr_harmful_race.cc b/lib/tsan/lit_tests/vptr_harmful_race2.cc similarity index 95% copy from lib/tsan/lit_tests/vptr_harmful_race.cc copy to lib/tsan/lit_tests/vptr_harmful_race2.cc index f51ba7ee5..4bcf1a4d8 100644 --- a/lib/tsan/lit_tests/vptr_harmful_race.cc +++ b/lib/tsan/lit_tests/vptr_harmful_race2.cc @@ -2,6 +2,7 @@ #include #include #include +#include struct A { A() { @@ -28,6 +29,7 @@ struct B : A { static A *obj = new B; void *Thread1(void *x) { + sleep(1); obj->F(); obj->Done(); return NULL; diff --git a/lib/tsan/rtl/tsan_interface.h b/lib/tsan/rtl/tsan_interface.h index 28eea1421..24526615d 100644 --- a/lib/tsan/rtl/tsan_interface.h +++ b/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/lib/tsan/rtl/tsan_interface_inl.h b/lib/tsan/rtl/tsan_interface_inl.h index 29e2b21ea..0187e49d9 100644 --- a/lib/tsan/rtl/tsan_interface_inl.h +++ b/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/lib/tsan/rtl/tsan_report.cc b/lib/tsan/rtl/tsan_report.cc index b394c406d..30e5488c0 100644 --- a/lib/tsan/rtl/tsan_report.cc +++ b/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/lib/tsan/rtl/tsan_report.h b/lib/tsan/rtl/tsan_report.h index b2b7b5330..eacb10c81 100644 --- a/lib/tsan/rtl/tsan_report.h +++ b/lib/tsan/rtl/tsan_report.h @@ -20,6 +20,7 @@ namespace __tsan { enum ReportType { ReportTypeRace, + ReportTypeVptrRace, ReportTypeUseAfterFree, ReportTypeThreadLeak, ReportTypeMutexDestroyLocked, diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h index e57fcc735..c216a80f1 100644 --- a/lib/tsan/rtl/tsan_rtl.h +++ b/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/lib/tsan/rtl/tsan_rtl_report.cc b/lib/tsan/rtl/tsan_rtl_report.cc index 18ab18e0c..50c531177 100644 --- a/lib/tsan/rtl/tsan_rtl_report.cc +++ b/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); -- 2.11.4.GIT