tsan: print matched suppressions if print_suppressions=1 flag is provided
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@178159 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/tsan/rtl/tsan_defs.h b/lib/tsan/rtl/tsan_defs.h
index 27f1db3..7150e2e 100644
--- a/lib/tsan/rtl/tsan_defs.h
+++ b/lib/tsan/rtl/tsan_defs.h
@@ -162,6 +162,7 @@
class RegionAlloc;
class StackTrace;
struct MBlock;
+struct Suppression;
} // namespace __tsan
diff --git a/lib/tsan/rtl/tsan_flags.cc b/lib/tsan/rtl/tsan_flags.cc
index 722ffdf..c2ae9d3 100644
--- a/lib/tsan/rtl/tsan_flags.cc
+++ b/lib/tsan/rtl/tsan_flags.cc
@@ -49,6 +49,7 @@
f->force_seq_cst_atomics = false;
f->strip_path_prefix = "";
f->suppressions = "";
+ f->print_suppressions = false;
f->exitcode = 66;
f->log_path = "stderr";
f->atexit_sleep_ms = 1000;
@@ -78,6 +79,7 @@
ParseFlag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics");
ParseFlag(env, &f->strip_path_prefix, "strip_path_prefix");
ParseFlag(env, &f->suppressions, "suppressions");
+ ParseFlag(env, &f->print_suppressions, "print_suppressions");
ParseFlag(env, &f->exitcode, "exitcode");
ParseFlag(env, &f->log_path, "log_path");
ParseFlag(env, &f->atexit_sleep_ms, "atexit_sleep_ms");
diff --git a/lib/tsan/rtl/tsan_flags.h b/lib/tsan/rtl/tsan_flags.h
index edeac04..572d96c 100644
--- a/lib/tsan/rtl/tsan_flags.h
+++ b/lib/tsan/rtl/tsan_flags.h
@@ -52,6 +52,8 @@
const char *strip_path_prefix;
// Suppressions filename.
const char *suppressions;
+ // Print matched suppressions at exit.
+ bool print_suppressions;
// Override exit status if something was reported.
int exitcode;
// Write logs to "log_path.pid".
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index d67c912..28113c6 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/lib/tsan/rtl/tsan_rtl.cc
@@ -277,6 +277,9 @@
ctx->nmissed_expected);
}
+ if (flags()->print_suppressions)
+ PrintMatchedSuppressions();
+
failed = OnFinalize(failed);
StatAggregate(ctx->stat, thr->stat);
diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h
index 80ec302..99dceb4 100644
--- a/lib/tsan/rtl/tsan_rtl.h
+++ b/lib/tsan/rtl/tsan_rtl.h
@@ -512,6 +512,7 @@
struct FiredSuppression {
ReportType type;
uptr pc;
+ Suppression *supp;
};
struct Context {
diff --git a/lib/tsan/rtl/tsan_rtl_report.cc b/lib/tsan/rtl/tsan_rtl_report.cc
index fd61f4a..e7109f6 100644
--- a/lib/tsan/rtl/tsan_rtl_report.cc
+++ b/lib/tsan/rtl/tsan_rtl_report.cc
@@ -501,12 +501,13 @@
const ReportStack *suppress_stack2) {
atomic_store(&ctx->last_symbolize_time_ns, NanoTime(), memory_order_relaxed);
const ReportDesc *rep = srep.GetReport();
- uptr suppress_pc = IsSuppressed(rep->typ, suppress_stack1);
+ Suppression *supp = 0;
+ uptr suppress_pc = IsSuppressed(rep->typ, suppress_stack1, &supp);
if (suppress_pc == 0)
- suppress_pc = IsSuppressed(rep->typ, suppress_stack2);
+ suppress_pc = IsSuppressed(rep->typ, suppress_stack2, &supp);
if (suppress_pc != 0) {
- FiredSuppression supp = {srep.GetReport()->typ, suppress_pc};
- ctx->fired_suppressions.PushBack(supp);
+ FiredSuppression s = {srep.GetReport()->typ, suppress_pc, supp};
+ ctx->fired_suppressions.PushBack(s);
}
if (OnReport(rep, suppress_pc != 0))
return false;
@@ -522,8 +523,12 @@
if (ctx->fired_suppressions[k].type != srep.GetReport()->typ)
continue;
for (uptr j = 0; j < trace.Size(); j++) {
- if (trace.Get(j) == ctx->fired_suppressions[k].pc)
+ FiredSuppression *s = &ctx->fired_suppressions[k];
+ if (trace.Get(j) == s->pc) {
+ if (s->supp)
+ s->supp->hit_count++;
return true;
+ }
}
}
return false;
@@ -560,7 +565,7 @@
|| (frame->func == 0 && frame->file == 0 && frame->line == 0
&& frame->module == 0)) {
if (frame) {
- FiredSuppression supp = {rep->typ, frame->pc};
+ FiredSuppression supp = {rep->typ, frame->pc, 0};
CTX()->fired_suppressions.PushBack(supp);
}
return true;
diff --git a/lib/tsan/rtl/tsan_suppressions.cc b/lib/tsan/rtl/tsan_suppressions.cc
index 941c208..47fe7b2 100644
--- a/lib/tsan/rtl/tsan_suppressions.cc
+++ b/lib/tsan/rtl/tsan_suppressions.cc
@@ -127,6 +127,7 @@
s->templ = (char*)internal_alloc(MBlockSuppression, end2 - line + 1);
internal_memcpy(s->templ, line, end2 - line);
s->templ[end2 - line] = 0;
+ s->hit_count = 0;
}
if (end[0] == 0)
break;
@@ -144,7 +145,7 @@
#endif
}
-uptr IsSuppressed(ReportType typ, const ReportStack *stack) {
+uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
if (g_suppressions == 0 || stack == 0)
return 0;
SuppressionType stype;
@@ -165,10 +166,38 @@
SuppressionMatch(supp->templ, frame->file) ||
SuppressionMatch(supp->templ, frame->module))) {
DPrintf("ThreadSanitizer: matched suppression '%s'\n", supp->templ);
+ supp->hit_count++;
+ *sp = supp;
return frame->pc;
}
}
}
return 0;
}
+
+static const char *SuppTypeStr(SuppressionType t) {
+ switch (t) {
+ case SuppressionRace: return "race";
+ case SuppressionMutex: return "mutex";
+ case SuppressionThread: return "thread";
+ case SuppressionSignal: return "signal";
+ }
+ CHECK(0);
+ return "unknown";
+}
+
+void PrintMatchedSuppressions() {
+ int hit_count = 0;
+ for (Suppression *supp = g_suppressions; supp; supp = supp->next)
+ hit_count += supp->hit_count;
+ if (hit_count == 0)
+ return;
+ Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n",
+ hit_count, GetPid());
+ for (Suppression *supp = g_suppressions; supp; supp = supp->next) {
+ if (supp->hit_count == 0)
+ continue;
+ Printf("%d %s:%s\n", supp->hit_count, SuppTypeStr(supp->type), supp->templ);
+ }
+}
} // namespace __tsan
diff --git a/lib/tsan/rtl/tsan_suppressions.h b/lib/tsan/rtl/tsan_suppressions.h
index c588316..1c98363 100644
--- a/lib/tsan/rtl/tsan_suppressions.h
+++ b/lib/tsan/rtl/tsan_suppressions.h
@@ -17,10 +17,6 @@
namespace __tsan {
-void InitializeSuppressions();
-void FinalizeSuppressions();
-uptr IsSuppressed(ReportType typ, const ReportStack *stack);
-
// Exposed for testing.
enum SuppressionType {
SuppressionRace,
@@ -33,8 +29,13 @@
Suppression *next;
SuppressionType type;
char *templ;
+ int hit_count;
};
+void InitializeSuppressions();
+void FinalizeSuppressions();
+void PrintMatchedSuppressions();
+uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp);
Suppression *SuppressionParse(Suppression *head, const char* supp);
bool SuppressionMatch(char *templ, const char *str);