summaryrefslogtreecommitdiffstats
path: root/compiler-rt
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2013-03-27 17:59:57 +0000
committerDmitry Vyukov <dvyukov@google.com>2013-03-27 17:59:57 +0000
commitb365d40415639411515302f4efb02f836e6ca5d2 (patch)
tree8415e17027df1175064334041e35a7f55c82b479 /compiler-rt
parentfd3f5ec0cba347eadf9aca6aab5954a018c2eadc (diff)
downloadbcm5719-llvm-b365d40415639411515302f4efb02f836e6ca5d2.tar.gz
bcm5719-llvm-b365d40415639411515302f4efb02f836e6ca5d2.zip
tsan: print matched suppressions if print_suppressions=1 flag is provided
llvm-svn: 178159
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_defs.h1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_flags.cc2
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_flags.h2
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl.cc3
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl.h1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc17
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_suppressions.cc31
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_suppressions.h9
8 files changed, 55 insertions, 11 deletions
diff --git a/compiler-rt/lib/tsan/rtl/tsan_defs.h b/compiler-rt/lib/tsan/rtl/tsan_defs.h
index 27f1db38f3a..7150e2e255d 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_defs.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_defs.h
@@ -162,6 +162,7 @@ class ReportDesc;
class RegionAlloc;
class StackTrace;
struct MBlock;
+struct Suppression;
} // namespace __tsan
diff --git a/compiler-rt/lib/tsan/rtl/tsan_flags.cc b/compiler-rt/lib/tsan/rtl/tsan_flags.cc
index 722ffdfee0f..c2ae9d35dee 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_flags.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_flags.cc
@@ -49,6 +49,7 @@ void InitializeFlags(Flags *f, const char *env) {
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 @@ void InitializeFlags(Flags *f, const char *env) {
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/compiler-rt/lib/tsan/rtl/tsan_flags.h b/compiler-rt/lib/tsan/rtl/tsan_flags.h
index edeac04d5ac..572d96c3356 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_flags.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_flags.h
@@ -52,6 +52,8 @@ struct Flags {
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/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc
index d67c9125f7b..28113c6cebd 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc
@@ -277,6 +277,9 @@ int Finalize(ThreadState *thr) {
ctx->nmissed_expected);
}
+ if (flags()->print_suppressions)
+ PrintMatchedSuppressions();
+
failed = OnFinalize(failed);
StatAggregate(ctx->stat, thr->stat);
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
index 80ec3024f3d..99dceb46038 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
@@ -512,6 +512,7 @@ struct RacyAddress {
struct FiredSuppression {
ReportType type;
uptr pc;
+ Suppression *supp;
};
struct Context {
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc
index fd61f4a43e4..e7109f6e70a 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc
@@ -501,12 +501,13 @@ bool OutputReport(Context *ctx,
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 @@ bool IsFiredSuppression(Context *ctx,
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 @@ static bool IsJavaNonsense(const ReportDesc *rep) {
|| (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/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc
index 941c208aa3e..47fe7b2d4f3 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc
@@ -127,6 +127,7 @@ Suppression *SuppressionParse(Suppression *head, const char* supp) {
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 @@ void InitializeSuppressions() {
#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 @@ uptr IsSuppressed(ReportType typ, const ReportStack *stack) {
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/compiler-rt/lib/tsan/rtl/tsan_suppressions.h b/compiler-rt/lib/tsan/rtl/tsan_suppressions.h
index c5883167058..1c98363383d 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_suppressions.h
+++ b/compiler-rt/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 @@ struct Suppression {
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);
OpenPOWER on IntegriCloud