summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSergey Matveev <earthdok@google.com>2013-06-26 15:37:14 +0000
committerSergey Matveev <earthdok@google.com>2013-06-26 15:37:14 +0000
commita52e5c6f371bcc66e89792db1219a557664aab8d (patch)
treeef740503c2d0b73765b1104f11e86a8c29a1cdd9 /lib
parentb5cf98f76fd62236f2945bff17b3cdb4e8a5c2f4 (diff)
downloadcompiler-rt-a52e5c6f371bcc66e89792db1219a557664aab8d.tar.gz
[tsan] Move some suppressions-related code to common.
Factor out code to be reused in LSan. Also switch from linked list to vector. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@184957 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/sanitizer_common/CMakeLists.txt1
-rw-r--r--lib/sanitizer_common/sanitizer_suppressions.cc131
-rw-r--r--lib/sanitizer_common/sanitizer_suppressions.h58
-rw-r--r--lib/sanitizer_common/tests/CMakeLists.txt1
-rw-r--r--lib/sanitizer_common/tests/sanitizer_suppressions_test.cc130
-rw-r--r--lib/tsan/rtl/tsan_defs.h1
-rw-r--r--lib/tsan/rtl/tsan_rtl.h1
-rw-r--r--lib/tsan/rtl/tsan_suppressions.cc161
-rw-r--r--lib/tsan/rtl/tsan_suppressions.h20
-rw-r--r--lib/tsan/tests/unit/CMakeLists.txt1
-rw-r--r--lib/tsan/tests/unit/tsan_suppressions_test.cc128
11 files changed, 362 insertions, 271 deletions
diff --git a/lib/sanitizer_common/CMakeLists.txt b/lib/sanitizer_common/CMakeLists.txt
index 55c3ad145..8141ae684 100644
--- a/lib/sanitizer_common/CMakeLists.txt
+++ b/lib/sanitizer_common/CMakeLists.txt
@@ -13,6 +13,7 @@ set(SANITIZER_SOURCES
sanitizer_printf.cc
sanitizer_stackdepot.cc
sanitizer_stacktrace.cc
+ sanitizer_suppressions.cc
sanitizer_symbolizer_itanium.cc
sanitizer_symbolizer_linux.cc
sanitizer_symbolizer_mac.cc
diff --git a/lib/sanitizer_common/sanitizer_suppressions.cc b/lib/sanitizer_common/sanitizer_suppressions.cc
new file mode 100644
index 000000000..24713528b
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_suppressions.cc
@@ -0,0 +1,131 @@
+//===-- sanitizer_suppressions.cc -----------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Suppression parsing/matching code shared between TSan and LSan.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_suppressions.h"
+
+#include "sanitizer_allocator_internal.h"
+#include "sanitizer_common.h"
+#include "sanitizer_libc.h"
+
+namespace __sanitizer {
+
+static const char *const kTypeStrings[SuppressionTypeCount] = {
+ "none", "race", "mutex", "thread", "signal"
+};
+
+bool TemplateMatch(char *templ, const char *str) {
+ if (str == 0 || str[0] == 0)
+ return false;
+ char *tpos;
+ const char *spos;
+ while (templ && templ[0]) {
+ if (templ[0] == '*') {
+ templ++;
+ continue;
+ }
+ if (str[0] == 0)
+ return false;
+ tpos = (char*)internal_strchr(templ, '*');
+ if (tpos != 0)
+ tpos[0] = 0;
+ spos = internal_strstr(str, templ);
+ str = spos + internal_strlen(templ);
+ templ = tpos;
+ if (tpos)
+ tpos[0] = '*';
+ if (spos == 0)
+ return false;
+ }
+ return true;
+}
+
+bool SuppressionContext::Match(const char *str, SuppressionType type,
+ Suppression **s) {
+ can_parse_ = false;
+ uptr i;
+ for (i = 0; i < suppressions_.size(); i++)
+ if (type == suppressions_[i].type &&
+ TemplateMatch(suppressions_[i].templ, str))
+ break;
+ if (i == suppressions_.size()) return false;
+ *s = &suppressions_[i];
+ return true;
+}
+
+static const char *StripPrefix(const char *str, const char *prefix) {
+ while (str && *str == *prefix) {
+ str++;
+ prefix++;
+ }
+ if (!*prefix)
+ return str;
+ return 0;
+}
+
+void SuppressionContext::Parse(const char *str) {
+ // Context must not mutate once Match has been called.
+ CHECK(can_parse_);
+ const char *line = str;
+ while (line) {
+ while (line[0] == ' ' || line[0] == '\t')
+ line++;
+ const char *end = internal_strchr(line, '\n');
+ if (end == 0)
+ end = line + internal_strlen(line);
+ if (line != end && line[0] != '#') {
+ const char *end2 = end;
+ while (line != end2 && (end2[-1] == ' ' || end2[-1] == '\t'))
+ end2--;
+ int type;
+ for (type = 0; type < SuppressionTypeCount; type++) {
+ const char *next_char = StripPrefix(line, kTypeStrings[type]);
+ if (next_char && *next_char == ':') {
+ line = ++next_char;
+ break;
+ }
+ }
+ if (type == SuppressionTypeCount) {
+ Printf("%s: failed to parse suppressions file\n", SanitizerToolName);
+ Die();
+ }
+ Suppression s;
+ s.type = static_cast<SuppressionType>(type);
+ s.templ = (char*)InternalAlloc(end2 - line + 1);
+ internal_memcpy(s.templ, line, end2 - line);
+ s.templ[end2 - line] = 0;
+ s.hit_count = 0;
+ suppressions_.push_back(s);
+ }
+ if (end[0] == 0)
+ break;
+ line = end + 1;
+ }
+}
+
+uptr SuppressionContext::SuppressionCount() {
+ return suppressions_.size();
+}
+
+void SuppressionContext::GetMatched(
+ InternalMmapVector<Suppression *> *matched) {
+ for (uptr i = 0; i < suppressions_.size(); i++)
+ if (suppressions_[i].hit_count)
+ matched->push_back(&suppressions_[i]);
+}
+
+const char *SuppressionTypeString(SuppressionType t) {
+ CHECK(t < SuppressionTypeCount);
+ return kTypeStrings[t];
+}
+
+} // namespace __sanitizer
diff --git a/lib/sanitizer_common/sanitizer_suppressions.h b/lib/sanitizer_common/sanitizer_suppressions.h
new file mode 100644
index 000000000..d78da0c49
--- /dev/null
+++ b/lib/sanitizer_common/sanitizer_suppressions.h
@@ -0,0 +1,58 @@
+//===-- sanitizer_suppressions.h --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Suppression parsing/matching code shared between TSan and LSan.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_SUPPRESSIONS_H
+#define SANITIZER_SUPPRESSIONS_H
+
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+
+namespace __sanitizer {
+
+enum SuppressionType {
+ SuppressionNone,
+ SuppressionRace,
+ SuppressionMutex,
+ SuppressionThread,
+ SuppressionSignal,
+ SuppressionTypeCount
+};
+
+struct Suppression {
+ SuppressionType type;
+ char *templ;
+ unsigned hit_count;
+};
+
+class SuppressionContext {
+ public:
+ SuppressionContext() : suppressions_(1), can_parse_(true) {}
+ void Parse(const char *str);
+ bool Match(const char* str, SuppressionType type, Suppression **s);
+ uptr SuppressionCount();
+ void GetMatched(InternalMmapVector<Suppression *> *matched);
+
+ private:
+ InternalMmapVector<Suppression> suppressions_;
+ bool can_parse_;
+
+ friend class SuppressionContextTest;
+};
+
+const char *SuppressionTypeString(SuppressionType t);
+
+// Exposed for testing.
+bool TemplateMatch(char *templ, const char *str);
+
+} // namespace __sanitizer
+
+#endif // SANITIZER_SUPPRESSIONS_H
diff --git a/lib/sanitizer_common/tests/CMakeLists.txt b/lib/sanitizer_common/tests/CMakeLists.txt
index 5f51544f1..d7ccc788d 100644
--- a/lib/sanitizer_common/tests/CMakeLists.txt
+++ b/lib/sanitizer_common/tests/CMakeLists.txt
@@ -16,6 +16,7 @@ set(SANITIZER_UNITTESTS
sanitizer_stackdepot_test.cc
sanitizer_stacktrace_test.cc
sanitizer_stoptheworld_test.cc
+ sanitizer_suppressions_test.cc
sanitizer_test_main.cc
sanitizer_thread_registry_test.cc
)
diff --git a/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc b/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
new file mode 100644
index 000000000..f6ee5ce83
--- /dev/null
+++ b/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
@@ -0,0 +1,130 @@
+//===-- sanitizer_suppressions_test.cc ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
+//
+//===----------------------------------------------------------------------===//
+#include "sanitizer_common/sanitizer_suppressions.h"
+#include "gtest/gtest.h"
+
+#include <string.h>
+
+namespace __sanitizer {
+
+static bool MyMatch(const char *templ, const char *func) {
+ char tmp[1024];
+ strcpy(tmp, templ); // NOLINT
+ return TemplateMatch(tmp, func);
+}
+
+TEST(Suppressions, Match) {
+ EXPECT_TRUE(MyMatch("foobar", "foobar"));
+ EXPECT_TRUE(MyMatch("foobar", "prefix_foobar_postfix"));
+ EXPECT_TRUE(MyMatch("*foobar*", "prefix_foobar_postfix"));
+ EXPECT_TRUE(MyMatch("foo*bar", "foo_middle_bar"));
+ EXPECT_TRUE(MyMatch("foo*bar", "foobar"));
+ EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_bar_another_baz"));
+ EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_barbaz"));
+
+ EXPECT_FALSE(MyMatch("foo", "baz"));
+ EXPECT_FALSE(MyMatch("foobarbaz", "foobar"));
+ EXPECT_FALSE(MyMatch("foobarbaz", "barbaz"));
+ EXPECT_FALSE(MyMatch("foo*bar", "foobaz"));
+ EXPECT_FALSE(MyMatch("foo*bar", "foo_baz"));
+}
+
+TEST(Suppressions, TypeStrings) {
+ CHECK(!internal_strcmp(SuppressionTypeString(SuppressionNone), "none"));
+ CHECK(!internal_strcmp(SuppressionTypeString(SuppressionRace), "race"));
+ CHECK(!internal_strcmp(SuppressionTypeString(SuppressionMutex), "mutex"));
+ CHECK(!internal_strcmp(SuppressionTypeString(SuppressionThread), "thread"));
+ CHECK(!internal_strcmp(SuppressionTypeString(SuppressionSignal), "signal"));
+ // Ensure this test is up-to-date when suppression types are added.
+ CHECK_EQ(SuppressionTypeCount, 5);
+}
+
+class SuppressionContextTest : public ::testing::Test {
+ public:
+ virtual void SetUp() { ctx_ = new(placeholder_) SuppressionContext; }
+ virtual void TearDown() { ctx_->~SuppressionContext(); }
+
+ protected:
+ InternalMmapVector<Suppression> *Suppressions() {
+ return &ctx_->suppressions_;
+ }
+ SuppressionContext *ctx_;
+ ALIGNED(64) char placeholder_[sizeof(SuppressionContext)];
+};
+
+TEST_F(SuppressionContextTest, Parse) {
+ ctx_->Parse(
+ "race:foo\n"
+ " race:bar\n" // NOLINT
+ "race:baz \n" // NOLINT
+ "# a comment\n"
+ "race:quz\n"
+ ); // NOLINT
+ EXPECT_EQ((unsigned)4, ctx_->SuppressionCount());
+ EXPECT_EQ((*Suppressions())[3].type, SuppressionRace);
+ EXPECT_EQ(0, strcmp((*Suppressions())[3].templ, "quz"));
+ EXPECT_EQ((*Suppressions())[2].type, SuppressionRace);
+ EXPECT_EQ(0, strcmp((*Suppressions())[2].templ, "baz"));
+ EXPECT_EQ((*Suppressions())[1].type, SuppressionRace);
+ EXPECT_EQ(0, strcmp((*Suppressions())[1].templ, "bar"));
+ EXPECT_EQ((*Suppressions())[0].type, SuppressionRace);
+ EXPECT_EQ(0, strcmp((*Suppressions())[0].templ, "foo"));
+}
+
+TEST_F(SuppressionContextTest, Parse2) {
+ ctx_->Parse(
+ " # first line comment\n" // NOLINT
+ " race:bar \n" // NOLINT
+ "race:baz* *baz\n"
+ "# a comment\n"
+ "# last line comment\n"
+ ); // NOLINT
+ EXPECT_EQ((unsigned)2, ctx_->SuppressionCount());
+ EXPECT_EQ((*Suppressions())[1].type, SuppressionRace);
+ EXPECT_EQ(0, strcmp((*Suppressions())[1].templ, "baz* *baz"));
+ EXPECT_EQ((*Suppressions())[0].type, SuppressionRace);
+ EXPECT_EQ(0, strcmp((*Suppressions())[0].templ, "bar"));
+}
+
+TEST_F(SuppressionContextTest, Parse3) {
+ ctx_->Parse(
+ "# last suppression w/o line-feed\n"
+ "race:foo\n"
+ "race:bar"
+ ); // NOLINT
+ EXPECT_EQ((unsigned)2, ctx_->SuppressionCount());
+ EXPECT_EQ((*Suppressions())[1].type, SuppressionRace);
+ EXPECT_EQ(0, strcmp((*Suppressions())[1].templ, "bar"));
+ EXPECT_EQ((*Suppressions())[0].type, SuppressionRace);
+ EXPECT_EQ(0, strcmp((*Suppressions())[0].templ, "foo"));
+}
+
+TEST_F(SuppressionContextTest, ParseType) {
+ ctx_->Parse(
+ "race:foo\n"
+ "thread:bar\n"
+ "mutex:baz\n"
+ "signal:quz\n"
+ ); // NOLINT
+ EXPECT_EQ((unsigned)4, ctx_->SuppressionCount());
+ EXPECT_EQ((*Suppressions())[3].type, SuppressionSignal);
+ EXPECT_EQ(0, strcmp((*Suppressions())[3].templ, "quz"));
+ EXPECT_EQ((*Suppressions())[2].type, SuppressionMutex);
+ EXPECT_EQ(0, strcmp((*Suppressions())[2].templ, "baz"));
+ EXPECT_EQ((*Suppressions())[1].type, SuppressionThread);
+ EXPECT_EQ(0, strcmp((*Suppressions())[1].templ, "bar"));
+ EXPECT_EQ((*Suppressions())[0].type, SuppressionRace);
+ EXPECT_EQ(0, strcmp((*Suppressions())[0].templ, "foo"));
+}
+
+} // namespace __sanitizer
diff --git a/lib/tsan/rtl/tsan_defs.h b/lib/tsan/rtl/tsan_defs.h
index 7150e2e25..27f1db38f 100644
--- a/lib/tsan/rtl/tsan_defs.h
+++ b/lib/tsan/rtl/tsan_defs.h
@@ -162,7 +162,6 @@ class ReportDesc;
class RegionAlloc;
class StackTrace;
struct MBlock;
-struct Suppression;
} // namespace __tsan
diff --git a/lib/tsan/rtl/tsan_rtl.h b/lib/tsan/rtl/tsan_rtl.h
index 849389b72..5445f575a 100644
--- a/lib/tsan/rtl/tsan_rtl.h
+++ b/lib/tsan/rtl/tsan_rtl.h
@@ -29,6 +29,7 @@
#include "sanitizer_common/sanitizer_allocator.h"
#include "sanitizer_common/sanitizer_allocator_internal.h"
#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
#include "sanitizer_common/sanitizer_thread_registry.h"
#include "tsan_clock.h"
#include "tsan_defs.h"
diff --git a/lib/tsan/rtl/tsan_suppressions.cc b/lib/tsan/rtl/tsan_suppressions.cc
index 8d5debc08..11047d4f6 100644
--- a/lib/tsan/rtl/tsan_suppressions.cc
+++ b/lib/tsan/rtl/tsan_suppressions.cc
@@ -13,6 +13,8 @@
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
#include "tsan_suppressions.h"
#include "tsan_rtl.h"
#include "tsan_flags.h"
@@ -28,7 +30,7 @@ extern "C" const char *WEAK __tsan_default_suppressions() {
namespace __tsan {
-static Suppression *g_suppressions;
+static SuppressionContext* g_ctx;
static char *ReadFile(const char *filename) {
if (filename == 0 || filename[0] == 0)
@@ -62,87 +64,14 @@ static char *ReadFile(const char *filename) {
return buf;
}
-bool SuppressionMatch(char *templ, const char *str) {
- if (str == 0 || str[0] == 0)
- return false;
- char *tpos;
- const char *spos;
- while (templ && templ[0]) {
- if (templ[0] == '*') {
- templ++;
- continue;
- }
- if (str[0] == 0)
- return false;
- tpos = (char*)internal_strchr(templ, '*');
- if (tpos != 0)
- tpos[0] = 0;
- spos = internal_strstr(str, templ);
- str = spos + internal_strlen(templ);
- templ = tpos;
- if (tpos)
- tpos[0] = '*';
- if (spos == 0)
- return false;
- }
- return true;
-}
-
-Suppression *SuppressionParse(Suppression *head, const char* supp) {
- const char *line = supp;
- while (line) {
- while (line[0] == ' ' || line[0] == '\t')
- line++;
- const char *end = internal_strchr(line, '\n');
- if (end == 0)
- end = line + internal_strlen(line);
- if (line != end && line[0] != '#') {
- const char *end2 = end;
- while (line != end2 && (end2[-1] == ' ' || end2[-1] == '\t'))
- end2--;
- SuppressionType stype;
- if (0 == internal_strncmp(line, "race:", sizeof("race:") - 1)) {
- stype = SuppressionRace;
- line += sizeof("race:") - 1;
- } else if (0 == internal_strncmp(line, "thread:",
- sizeof("thread:") - 1)) {
- stype = SuppressionThread;
- line += sizeof("thread:") - 1;
- } else if (0 == internal_strncmp(line, "mutex:",
- sizeof("mutex:") - 1)) {
- stype = SuppressionMutex;
- line += sizeof("mutex:") - 1;
- } else if (0 == internal_strncmp(line, "signal:",
- sizeof("signal:") - 1)) {
- stype = SuppressionSignal;
- line += sizeof("signal:") - 1;
- } else {
- Printf("ThreadSanitizer: failed to parse suppressions file\n");
- Die();
- }
- Suppression *s = (Suppression*)internal_alloc(MBlockSuppression,
- sizeof(Suppression));
- s->next = head;
- head = s;
- s->type = stype;
- 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;
- line = end + 1;
- }
- return head;
-}
-
void InitializeSuppressions() {
+ ALIGNED(64) static char placeholder_[sizeof(SuppressionContext)];
+ g_ctx = new(placeholder_) SuppressionContext;
const char *supp = ReadFile(flags()->suppressions);
- g_suppressions = SuppressionParse(0, supp);
+ g_ctx->Parse(supp);
#ifndef TSAN_GO
supp = __tsan_default_suppressions();
- g_suppressions = SuppressionParse(g_suppressions, supp);
+ g_ctx->Parse(supp);
#endif
}
@@ -166,71 +95,59 @@ SuppressionType conv(ReportType typ) {
}
uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
- if (g_suppressions == 0 || stack == 0)
- return 0;
+ CHECK(g_ctx);
+ if (!g_ctx->SuppressionCount() || stack == 0) return 0;
SuppressionType stype = conv(typ);
if (stype == SuppressionNone)
return 0;
+ Suppression *s;
for (const ReportStack *frame = stack; frame; frame = frame->next) {
- for (Suppression *supp = g_suppressions; supp; supp = supp->next) {
- if (stype == supp->type &&
- (SuppressionMatch(supp->templ, frame->func) ||
- 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;
- }
+ if (g_ctx->Match(frame->func, stype, &s) ||
+ g_ctx->Match(frame->file, stype, &s) ||
+ g_ctx->Match(frame->module, stype, &s)) {
+ DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
+ s->hit_count++;
+ *sp = s;
+ return frame->pc;
}
}
return 0;
}
uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
- if (g_suppressions == 0 || loc == 0 || loc->type != ReportLocationGlobal)
+ CHECK(g_ctx);
+ if (!g_ctx->SuppressionCount() || 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;
+ Suppression *s;
+ if (g_ctx->Match(loc->name, stype, &s) ||
+ g_ctx->Match(loc->file, stype, &s) ||
+ g_ctx->Match(loc->module, stype, &s)) {
+ DPrintf("ThreadSanitizer: matched suppression '%s'\n", templ);
+ s->hit_count++;
+ *sp = s;
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";
- 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)
+ CHECK(g_ctx);
+ InternalMmapVector<Suppression *> matched(1);
+ g_ctx->GetMatched(&matched);
+ if (!matched.size())
return;
- Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n",
- hit_count, (int)internal_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);
+ int hit_count = 0;
+ for (uptr i = 0; i < matched.size(); i++)
+ hit_count += matched[i]->hit_count;
+ Printf("ThreadSanitizer: Matched %d suppressions (pid=%d):\n", hit_count,
+ (int)internal_getpid());
+ for (uptr i = 0; i < matched.size(); i++) {
+ Printf("%d %s:%s\n", matched[i]->hit_count,
+ SuppressionTypeString(matched[i]->type), matched[i]->templ);
}
}
} // namespace __tsan
diff --git a/lib/tsan/rtl/tsan_suppressions.h b/lib/tsan/rtl/tsan_suppressions.h
index edcaa1e5e..c618b3db4 100644
--- a/lib/tsan/rtl/tsan_suppressions.h
+++ b/lib/tsan/rtl/tsan_suppressions.h
@@ -13,33 +13,15 @@
#ifndef TSAN_SUPPRESSIONS_H
#define TSAN_SUPPRESSIONS_H
+#include "sanitizer_common/sanitizer_suppressions.h"
#include "tsan_report.h"
namespace __tsan {
-// Exposed for testing.
-enum SuppressionType {
- SuppressionNone,
- SuppressionRace,
- SuppressionMutex,
- SuppressionThread,
- SuppressionSignal
-};
-
-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);
uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp);
-Suppression *SuppressionParse(Suppression *head, const char* supp);
-bool SuppressionMatch(char *templ, const char *str);
} // namespace __tsan
diff --git a/lib/tsan/tests/unit/CMakeLists.txt b/lib/tsan/tests/unit/CMakeLists.txt
index b25a56d8d..1cd2abe4d 100644
--- a/lib/tsan/tests/unit/CMakeLists.txt
+++ b/lib/tsan/tests/unit/CMakeLists.txt
@@ -5,7 +5,6 @@ set(TSAN_UNIT_TESTS
tsan_mutex_test.cc
tsan_shadow_test.cc
tsan_stack_test.cc
- tsan_suppressions_test.cc
tsan_sync_test.cc
tsan_vector_test.cc
)
diff --git a/lib/tsan/tests/unit/tsan_suppressions_test.cc b/lib/tsan/tests/unit/tsan_suppressions_test.cc
deleted file mode 100644
index decfa3214..000000000
--- a/lib/tsan/tests/unit/tsan_suppressions_test.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-//===-- tsan_suppressions_test.cc -----------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of ThreadSanitizer (TSan), a race detector.
-//
-//===----------------------------------------------------------------------===//
-#include "tsan_suppressions.h"
-#include "tsan_rtl.h"
-#include "gtest/gtest.h"
-
-#include <string.h>
-
-namespace __tsan {
-
-TEST(Suppressions, Parse) {
- ScopedInRtl in_rtl;
- Suppression *supp0 = SuppressionParse(0,
- "race:foo\n"
- " race:bar\n" // NOLINT
- "race:baz \n" // NOLINT
- "# a comment\n"
- "race:quz\n"
- ); // NOLINT
- Suppression *supp = supp0;
- EXPECT_EQ(supp->type, SuppressionRace);
- EXPECT_EQ(0, strcmp(supp->templ, "quz"));
- supp = supp->next;
- EXPECT_EQ(supp->type, SuppressionRace);
- EXPECT_EQ(0, strcmp(supp->templ, "baz"));
- supp = supp->next;
- EXPECT_EQ(supp->type, SuppressionRace);
- EXPECT_EQ(0, strcmp(supp->templ, "bar"));
- supp = supp->next;
- EXPECT_EQ(supp->type, SuppressionRace);
- EXPECT_EQ(0, strcmp(supp->templ, "foo"));
- supp = supp->next;
- EXPECT_EQ((Suppression*)0, supp);
-}
-
-TEST(Suppressions, Parse2) {
- ScopedInRtl in_rtl;
- Suppression *supp0 = SuppressionParse(0,
- " # first line comment\n" // NOLINT
- " race:bar \n" // NOLINT
- "race:baz* *baz\n"
- "# a comment\n"
- "# last line comment\n"
- ); // NOLINT
- Suppression *supp = supp0;
- EXPECT_EQ(supp->type, SuppressionRace);
- EXPECT_EQ(0, strcmp(supp->templ, "baz* *baz"));
- supp = supp->next;
- EXPECT_EQ(supp->type, SuppressionRace);
- EXPECT_EQ(0, strcmp(supp->templ, "bar"));
- supp = supp->next;
- EXPECT_EQ((Suppression*)0, supp);
-}
-
-TEST(Suppressions, Parse3) {
- ScopedInRtl in_rtl;
- Suppression *supp0 = SuppressionParse(0,
- "# last suppression w/o line-feed\n"
- "race:foo\n"
- "race:bar"
- ); // NOLINT
- Suppression *supp = supp0;
- EXPECT_EQ(supp->type, SuppressionRace);
- EXPECT_EQ(0, strcmp(supp->templ, "bar"));
- supp = supp->next;
- EXPECT_EQ(supp->type, SuppressionRace);
- EXPECT_EQ(0, strcmp(supp->templ, "foo"));
- supp = supp->next;
- EXPECT_EQ((Suppression*)0, supp);
-}
-
-TEST(Suppressions, ParseType) {
- ScopedInRtl in_rtl;
- Suppression *supp0 = SuppressionParse(0,
- "race:foo\n"
- "thread:bar\n"
- "mutex:baz\n"
- "signal:quz\n"
- ); // NOLINT
- Suppression *supp = supp0;
- EXPECT_EQ(supp->type, SuppressionSignal);
- EXPECT_EQ(0, strcmp(supp->templ, "quz"));
- supp = supp->next;
- EXPECT_EQ(supp->type, SuppressionMutex);
- EXPECT_EQ(0, strcmp(supp->templ, "baz"));
- supp = supp->next;
- EXPECT_EQ(supp->type, SuppressionThread);
- EXPECT_EQ(0, strcmp(supp->templ, "bar"));
- supp = supp->next;
- EXPECT_EQ(supp->type, SuppressionRace);
- EXPECT_EQ(0, strcmp(supp->templ, "foo"));
- supp = supp->next;
- EXPECT_EQ((Suppression*)0, supp);
-}
-
-static bool MyMatch(const char *templ, const char *func) {
- char tmp[1024];
- strcpy(tmp, templ); // NOLINT
- return SuppressionMatch(tmp, func);
-}
-
-TEST(Suppressions, Match) {
- EXPECT_TRUE(MyMatch("foobar", "foobar"));
- EXPECT_TRUE(MyMatch("foobar", "prefix_foobar_postfix"));
- EXPECT_TRUE(MyMatch("*foobar*", "prefix_foobar_postfix"));
- EXPECT_TRUE(MyMatch("foo*bar", "foo_middle_bar"));
- EXPECT_TRUE(MyMatch("foo*bar", "foobar"));
- EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_bar_another_baz"));
- EXPECT_TRUE(MyMatch("foo*bar*baz", "foo_middle_barbaz"));
-
- EXPECT_FALSE(MyMatch("foo", "baz"));
- EXPECT_FALSE(MyMatch("foobarbaz", "foobar"));
- EXPECT_FALSE(MyMatch("foobarbaz", "barbaz"));
- EXPECT_FALSE(MyMatch("foo*bar", "foobaz"));
- EXPECT_FALSE(MyMatch("foo*bar", "foo_baz"));
-}
-
-} // namespace __tsan