diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h index 5fb506fe584b..8e2b8b6651de 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -602,7 +602,8 @@ void ReportRace(ThreadState *thr); bool OutputReport(Context *ctx, const ScopedReport &srep, const ReportStack *suppress_stack1 = 0, - const ReportStack *suppress_stack2 = 0); + const ReportStack *suppress_stack2 = 0, + const ReportLocation *suppress_loc = 0); bool IsFiredSuppression(Context *ctx, const ScopedReport &srep, const StackTrace &trace); diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc index 35394a1e42a9..d594a5bd94ce 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc @@ -502,13 +502,16 @@ static void AddRacyStacks(ThreadState *thr, const StackTrace (&traces)[2], bool OutputReport(Context *ctx, const ScopedReport &srep, const ReportStack *suppress_stack1, - const ReportStack *suppress_stack2) { + const ReportStack *suppress_stack2, + const ReportLocation *suppress_loc) { atomic_store(&ctx->last_symbolize_time_ns, NanoTime(), memory_order_relaxed); const ReportDesc *rep = srep.GetReport(); Suppression *supp = 0; uptr suppress_pc = IsSuppressed(rep->typ, suppress_stack1, &supp); if (suppress_pc == 0) suppress_pc = IsSuppressed(rep->typ, suppress_stack2, &supp); + if (suppress_pc == 0) + suppress_pc = IsSuppressed(rep->typ, suppress_loc, &supp); if (suppress_pc != 0) { FiredSuppression s = {srep.GetReport()->typ, suppress_pc, supp}; ctx->fired_suppressions.PushBack(s); @@ -538,6 +541,22 @@ bool IsFiredSuppression(Context *ctx, return false; } +static bool IsFiredSuppression(Context *ctx, + const ScopedReport &srep, + uptr addr) { + for (uptr k = 0; k < ctx->fired_suppressions.Size(); k++) { + if (ctx->fired_suppressions[k].type != srep.GetReport()->typ) + continue; + FiredSuppression *s = &ctx->fired_suppressions[k]; + if (addr == s->pc) { + if (s->supp) + s->supp->hit_count++; + return true; + } + } + return false; +} + bool FrameIsInternal(const ReportStack *frame) { return frame != 0 && frame->file != 0 && (internal_strstr(frame->file, "tsan_interceptors.cc") || @@ -631,6 +650,8 @@ void ReportRace(ThreadState *thr) { else if (freed) typ = ReportTypeUseAfterFree; ScopedReport rep(typ); + if (IsFiredSuppression(ctx, rep, addr)) + return; const uptr kMop = 2; StackTrace traces[kMop]; const uptr toppc = TraceTopPC(thr); @@ -641,6 +662,8 @@ void ReportRace(ThreadState *thr) { new(mset2.data()) MutexSet(); Shadow s2(thr->racy_state[1]); RestoreStack(s2.tid(), s2.epoch(), &traces[1], mset2.data()); + if (IsFiredSuppression(ctx, rep, traces[1])) + return; if (HandleRacyStacks(thr, traces, addr_min, addr_max)) return; @@ -673,8 +696,11 @@ void ReportRace(ThreadState *thr) { } #endif + ReportLocation *suppress_loc = rep.GetReport()->locs.Size() ? + rep.GetReport()->locs[0] : 0; if (!OutputReport(ctx, rep, rep.GetReport()->mops[0]->stack, - rep.GetReport()->mops[1]->stack)) + rep.GetReport()->mops[1]->stack, + suppress_loc)) return; AddRacyStacks(thr, traces, addr_min, addr_max); diff --git a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc index 977c008b88ba..8d5debc08447 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc @@ -146,26 +146,31 @@ void InitializeSuppressions() { #endif } +SuppressionType conv(ReportType typ) { + if (typ == ReportTypeRace) + return SuppressionRace; + else if (typ == ReportTypeVptrRace) + return SuppressionRace; + else if (typ == ReportTypeUseAfterFree) + return SuppressionNone; + else if (typ == ReportTypeThreadLeak) + return SuppressionThread; + else if (typ == ReportTypeMutexDestroyLocked) + return SuppressionMutex; + else if (typ == ReportTypeSignalUnsafe) + return SuppressionSignal; + else if (typ == ReportTypeErrnoInSignal) + return SuppressionNone; + Printf("ThreadSanitizer: unknown report type %d\n", typ), + Die(); +} + uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) { if (g_suppressions == 0 || stack == 0) return 0; - SuppressionType stype; - if (typ == ReportTypeRace) - stype = SuppressionRace; - else if (typ == ReportTypeVptrRace) - stype = SuppressionRace; - else if (typ == ReportTypeUseAfterFree) + SuppressionType stype = conv(typ); + if (stype == SuppressionNone) return 0; - else if (typ == ReportTypeThreadLeak) - stype = SuppressionThread; - else if (typ == ReportTypeMutexDestroyLocked) - stype = SuppressionMutex; - else if (typ == ReportTypeSignalUnsafe) - stype = SuppressionSignal; - else if (typ == ReportTypeErrnoInSignal) - return 0; - else - Printf("ThreadSanitizer: unknown report type %d\n", typ), Die(); for (const ReportStack *frame = stack; frame; frame = frame->next) { for (Suppression *supp = g_suppressions; supp; supp = supp->next) { if (stype == supp->type && @@ -182,8 +187,29 @@ uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) { return 0; } +uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) { + if (g_suppressions == 0 || loc == 0 || loc->type != ReportLocationGlobal) + return 0; + SuppressionType stype = conv(typ); + if (stype == SuppressionNone) + return 0; + for (Suppression *supp = g_suppressions; supp; supp = supp->next) { + if (stype == supp->type && + (SuppressionMatch(supp->templ, loc->name) || + SuppressionMatch(supp->templ, loc->file) || + SuppressionMatch(supp->templ, loc->module))) { + DPrintf("ThreadSanitizer: matched suppression '%s'\n", supp->templ); + supp->hit_count++; + *sp = supp; + return loc->addr; + } + } + return 0; +} + static const char *SuppTypeStr(SuppressionType t) { switch (t) { + case SuppressionNone: return "none"; case SuppressionRace: return "race"; case SuppressionMutex: return "mutex"; case SuppressionThread: return "thread"; diff --git a/compiler-rt/lib/tsan/rtl/tsan_suppressions.h b/compiler-rt/lib/tsan/rtl/tsan_suppressions.h index 1c98363383dc..edcaa1e5ec5d 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_suppressions.h +++ b/compiler-rt/lib/tsan/rtl/tsan_suppressions.h @@ -19,6 +19,7 @@ namespace __tsan { // Exposed for testing. enum SuppressionType { + SuppressionNone, SuppressionRace, SuppressionMutex, SuppressionThread, @@ -36,6 +37,7 @@ void InitializeSuppressions(); void FinalizeSuppressions(); void PrintMatchedSuppressions(); uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp); +uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp); Suppression *SuppressionParse(Suppression *head, const char* supp); bool SuppressionMatch(char *templ, const char *str);