diff options
Diffstat (limited to 'libsanitizer/tsan/tsan_rtl_report.cc')
-rw-r--r-- | libsanitizer/tsan/tsan_rtl_report.cc | 71 |
1 files changed, 57 insertions, 14 deletions
diff --git a/libsanitizer/tsan/tsan_rtl_report.cc b/libsanitizer/tsan/tsan_rtl_report.cc index c4256da412a..ff1d43bc9e8 100644 --- a/libsanitizer/tsan/tsan_rtl_report.cc +++ b/libsanitizer/tsan/tsan_rtl_report.cc @@ -13,6 +13,7 @@ #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_common.h" +#include "sanitizer_common/sanitizer_stacktrace.h" #include "tsan_platform.h" #include "tsan_rtl.h" #include "tsan_suppressions.h" @@ -27,12 +28,15 @@ namespace __tsan { using namespace __sanitizer; // NOLINT +static ReportStack *SymbolizeStack(const StackTrace& trace); + void TsanCheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2) { ScopedInRtl in_rtl; Printf("FATAL: ThreadSanitizer CHECK failed: " "%s:%d \"%s\" (0x%zx, 0x%zx)\n", file, line, cond, (uptr)v1, (uptr)v2); + PrintCurrentStackSlow(); Die(); } @@ -144,7 +148,8 @@ void ScopedReport::AddMemoryAccess(uptr addr, Shadow s, mop->tid = s.tid(); mop->addr = addr + s.addr0(); mop->size = s.size(); - mop->write = s.is_write(); + mop->write = s.IsWrite(); + mop->atomic = s.IsAtomic(); mop->stack = SymbolizeStack(*stack); for (uptr i = 0; i < mset->Size(); i++) { MutexSet::Desc d = mset->Get(i); @@ -458,9 +463,12 @@ static void AddRacyStacks(ThreadState *thr, const StackTrace (&traces)[2], bool OutputReport(Context *ctx, const ScopedReport &srep, - const ReportStack *suppress_stack) { + const ReportStack *suppress_stack1, + const ReportStack *suppress_stack2) { const ReportDesc *rep = srep.GetReport(); - const uptr suppress_pc = IsSuppressed(rep->typ, suppress_stack); + uptr suppress_pc = IsSuppressed(rep->typ, suppress_stack1); + if (suppress_pc == 0) + suppress_pc = IsSuppressed(rep->typ, suppress_stack2); if (suppress_pc != 0) { FiredSuppression supp = {srep.GetReport()->typ, suppress_pc}; ctx->fired_suppressions.PushBack(supp); @@ -486,6 +494,13 @@ bool IsFiredSuppression(Context *ctx, return false; } +bool FrameIsInternal(const ReportStack *frame) { + return frame != 0 && frame->file != 0 + && (internal_strstr(frame->file, "tsan_interceptors.cc") || + internal_strstr(frame->file, "sanitizer_common_interceptors.inc") || + internal_strstr(frame->file, "tsan_interface_")); +} + // On programs that use Java we see weird reports like: // WARNING: ThreadSanitizer: data race (pid=22512) // Read of size 8 at 0x7d2b00084318 by thread 100: @@ -495,22 +510,20 @@ bool IsFiredSuppression(Context *ctx, // #0 strncpy tsan_interceptors.cc:501 (foo+0x00000d8e0919) // #1 <null> <null>:0 (0x7f7ad9b42707) static bool IsJavaNonsense(const ReportDesc *rep) { +#ifndef TSAN_GO for (uptr i = 0; i < rep->mops.Size(); i++) { ReportMop *mop = rep->mops[i]; ReportStack *frame = mop->stack; - if (frame != 0 && frame->func != 0 - && (internal_strcmp(frame->func, "memset") == 0 - || internal_strcmp(frame->func, "memcpy") == 0 - || internal_strcmp(frame->func, "memmove") == 0 - || internal_strcmp(frame->func, "strcmp") == 0 - || internal_strcmp(frame->func, "strncpy") == 0 - || internal_strcmp(frame->func, "strlen") == 0 - || internal_strcmp(frame->func, "free") == 0 - || internal_strcmp(frame->func, "pthread_mutex_lock") == 0)) { + if (frame == 0 + || (frame->func == 0 && frame->file == 0 && frame->line == 0 + && frame->module == 0)) { + return true; + } + if (FrameIsInternal(frame)) { frame = frame->next; if (frame == 0 || (frame->func == 0 && frame->file == 0 && frame->line == 0 - && frame->module == 0)) { + && frame->module == 0)) { if (frame) { FiredSuppression supp = {rep->typ, frame->pc}; CTX()->fired_suppressions.PushBack(supp); @@ -519,6 +532,20 @@ static bool IsJavaNonsense(const ReportDesc *rep) { } } } +#endif + return false; +} + +static bool RaceBetweenAtomicAndFree(ThreadState *thr) { + Shadow s0(thr->racy_state[0]); + Shadow s1(thr->racy_state[1]); + CHECK(!(s0.IsAtomic() && s1.IsAtomic())); + if (!s0.IsAtomic() && !s1.IsAtomic()) + return true; + if (s0.IsAtomic() && s1.IsFreed()) + return true; + if (s1.IsAtomic() && thr->is_freeing) + return true; return false; } @@ -527,6 +554,9 @@ void ReportRace(ThreadState *thr) { return; ScopedInRtl in_rtl; + if (!flags()->report_atomic_races && !RaceBetweenAtomicAndFree(thr)) + return; + if (thr->in_signal_handler) Printf("ThreadSanitizer: printing report from signal handler." " Can crash or hang.\n"); @@ -597,7 +627,8 @@ void ReportRace(ThreadState *thr) { } #endif - if (!OutputReport(ctx, rep, rep.GetReport()->mops[0]->stack)) + if (!OutputReport(ctx, rep, rep.GetReport()->mops[0]->stack, + rep.GetReport()->mops[1]->stack)) return; AddRacyStacks(thr, traces, addr_min, addr_max); @@ -609,4 +640,16 @@ void PrintCurrentStack(ThreadState *thr, uptr pc) { PrintStack(SymbolizeStack(trace)); } +void PrintCurrentStackSlow() { +#ifndef TSAN_GO + __sanitizer::StackTrace *ptrace = new(internal_alloc(MBlockStackTrace, + sizeof(__sanitizer::StackTrace))) __sanitizer::StackTrace; + ptrace->SlowUnwindStack(__sanitizer::StackTrace::GetCurrentPc(), + kStackTraceMax); + StackTrace trace; + trace.Init(ptrace->trace, ptrace->size); + PrintStack(SymbolizeStack(trace)); +#endif +} + } // namespace __tsan |