summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Samsonov <vonosmas@gmail.com>2015-02-20 17:41:59 +0000
committerAlexey Samsonov <vonosmas@gmail.com>2015-02-20 17:41:59 +0000
commitd1c318657b1c3b3ee54f4b30a6c6a52a6c4c3b93 (patch)
treeb4cfbb968f87c098bdeb11bab0fe7eedf550db74
parent57d71ac7b387b443ad9a0643fa2565ba0926c78e (diff)
downloadbcm5719-llvm-d1c318657b1c3b3ee54f4b30a6c6a52a6c4c3b93.tar.gz
bcm5719-llvm-d1c318657b1c3b3ee54f4b30a6c6a52a6c4c3b93.zip
[Sanitizer] Refactor SuppressionContext class.
SuppressionContext is no longer a singleton, shared by all sanitizers, but a regular class. Each of ASan, LSan, UBSan and TSan now have their own SuppressionContext, which only parses suppressions specific to that sanitizer. "suppressions" flag is moved away from common flags into tool-specific flags, so the user now may pass ASAN_OPTIONS=suppressions=asan_supp.txt LSAN_OPIONS=suppressions=lsan_supp.txt in a single invocation. llvm-svn: 230026
-rw-r--r--compiler-rt/lib/asan/asan_flags.inc1
-rw-r--r--compiler-rt/lib/asan/asan_suppressions.cc40
-rw-r--r--compiler-rt/lib/lsan/lsan_common.cc29
-rw-r--r--compiler-rt/lib/lsan/lsan_flags.inc1
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_flags.inc1
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc87
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h48
-rw-r--r--compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc106
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_flags.inc1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_interceptors.cc4
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_suppressions.cc81
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_suppressions.h9
-rw-r--r--compiler-rt/lib/ubsan/ubsan_diag.cc21
-rw-r--r--compiler-rt/lib/ubsan/ubsan_diag.h4
-rw-r--r--compiler-rt/lib/ubsan/ubsan_flags.inc1
-rw-r--r--compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc3
-rw-r--r--compiler-rt/lib/ubsan/ubsan_init.cc4
-rw-r--r--compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp16
18 files changed, 220 insertions, 237 deletions
diff --git a/compiler-rt/lib/asan/asan_flags.inc b/compiler-rt/lib/asan/asan_flags.inc
index ec9d41980d9..53a8a4039e7 100644
--- a/compiler-rt/lib/asan/asan_flags.inc
+++ b/compiler-rt/lib/asan/asan_flags.inc
@@ -142,3 +142,4 @@ ASAN_FLAG(int, detect_odr_violation, 2,
"have different sizes")
ASAN_FLAG(bool, dump_instruction_bytes, false,
"If true, dump 16 bytes starting at the instruction that caused SEGV")
+ASAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
diff --git a/compiler-rt/lib/asan/asan_suppressions.cc b/compiler-rt/lib/asan/asan_suppressions.cc
index ef554716faa..62198aec64e 100644
--- a/compiler-rt/lib/asan/asan_suppressions.cc
+++ b/compiler-rt/lib/asan/asan_suppressions.cc
@@ -15,57 +15,62 @@
#include "asan_suppressions.h"
#include "asan_stack.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_suppressions.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
namespace __asan {
-static bool suppressions_inited = false;
+ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
+static SuppressionContext *suppression_ctx = nullptr;
+static const char kInterceptorName[] = "interceptor_name";
+static const char kInterceptorViaFunction[] = "interceptor_via_fun";
+static const char kInterceptorViaLibrary[] = "interceptor_via_lib";
+static const char *kSuppressionTypes[] = {
+ kInterceptorName, kInterceptorViaFunction, kInterceptorViaLibrary};
void InitializeSuppressions() {
- CHECK(!suppressions_inited);
- SuppressionContext::InitIfNecessary();
- suppressions_inited = true;
+ CHECK_EQ(nullptr, suppression_ctx);
+ suppression_ctx = new (suppression_placeholder) // NOLINT
+ SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
+ suppression_ctx->ParseFromFile(flags()->suppressions);
}
bool IsInterceptorSuppressed(const char *interceptor_name) {
- CHECK(suppressions_inited);
- SuppressionContext *ctx = SuppressionContext::Get();
+ CHECK(suppression_ctx);
Suppression *s;
// Match "interceptor_name" suppressions.
- return ctx->Match(interceptor_name, SuppressionInterceptorName, &s);
+ return suppression_ctx->Match(interceptor_name, kInterceptorName, &s);
}
bool HaveStackTraceBasedSuppressions() {
- CHECK(suppressions_inited);
- SuppressionContext *ctx = SuppressionContext::Get();
- return ctx->HasSuppressionType(SuppressionInterceptorViaFunction) ||
- ctx->HasSuppressionType(SuppressionInterceptorViaLibrary);
+ CHECK(suppression_ctx);
+ return suppression_ctx->HasSuppressionType(kInterceptorViaFunction) ||
+ suppression_ctx->HasSuppressionType(kInterceptorViaLibrary);
}
bool IsStackTraceSuppressed(const StackTrace *stack) {
- CHECK(suppressions_inited);
if (!HaveStackTraceBasedSuppressions())
return false;
- SuppressionContext *ctx = SuppressionContext::Get();
+ CHECK(suppression_ctx);
Symbolizer *symbolizer = Symbolizer::GetOrInit();
Suppression *s;
for (uptr i = 0; i < stack->size && stack->trace[i]; i++) {
uptr addr = stack->trace[i];
- if (ctx->HasSuppressionType(SuppressionInterceptorViaLibrary)) {
+ if (suppression_ctx->HasSuppressionType(kInterceptorViaLibrary)) {
const char *module_name;
uptr module_offset;
// Match "interceptor_via_lib" suppressions.
if (symbolizer->GetModuleNameAndOffsetForPC(addr, &module_name,
&module_offset) &&
- ctx->Match(module_name, SuppressionInterceptorViaLibrary, &s)) {
+ suppression_ctx->Match(module_name, kInterceptorViaLibrary, &s)) {
return true;
}
}
- if (ctx->HasSuppressionType(SuppressionInterceptorViaFunction)) {
+ if (suppression_ctx->HasSuppressionType(kInterceptorViaFunction)) {
SymbolizedStack *frames = symbolizer->SymbolizePC(addr);
for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
const char *function_name = cur->info.function;
@@ -73,7 +78,8 @@ bool IsStackTraceSuppressed(const StackTrace *stack) {
continue;
}
// Match "interceptor_via_fun" suppressions.
- if (ctx->Match(function_name, SuppressionInterceptorViaFunction, &s)) {
+ if (suppression_ctx->Match(function_name, kInterceptorViaFunction,
+ &s)) {
frames->ClearAll();
return true;
}
diff --git a/compiler-rt/lib/lsan/lsan_common.cc b/compiler-rt/lib/lsan/lsan_common.cc
index 6dafb8484fc..b9e2a110432 100644
--- a/compiler-rt/lib/lsan/lsan_common.cc
+++ b/compiler-rt/lib/lsan/lsan_common.cc
@@ -60,14 +60,23 @@ void RegisterLsanFlags(FlagParser *parser, Flags *f) {
if (flags()->log_threads) Report(__VA_ARGS__); \
} while (0);
-static bool suppressions_inited = false;
+ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
+static SuppressionContext *suppression_ctx = nullptr;
+static const char kSuppressionLeak[] = "leak";
+static const char *kSuppressionTypes[] = { kSuppressionLeak };
void InitializeSuppressions() {
- CHECK(!suppressions_inited);
- SuppressionContext::InitIfNecessary();
+ CHECK_EQ(nullptr, suppression_ctx);
+ suppression_ctx = new (suppression_placeholder) // NOLINT
+ SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
+ suppression_ctx->ParseFromFile(flags()->suppressions);
if (&__lsan_default_suppressions)
- SuppressionContext::Get()->Parse(__lsan_default_suppressions());
- suppressions_inited = true;
+ suppression_ctx->Parse(__lsan_default_suppressions());
+}
+
+static SuppressionContext *GetSuppressionContext() {
+ CHECK(suppression_ctx);
+ return suppression_ctx;
}
struct RootRegion {
@@ -350,7 +359,7 @@ static void CollectLeaksCb(uptr chunk, void *arg) {
static void PrintMatchedSuppressions() {
InternalMmapVector<Suppression *> matched(1);
- SuppressionContext::Get()->GetMatched(&matched);
+ GetSuppressionContext()->GetMatched(&matched);
if (!matched.size())
return;
const char *line = "-----------------------------------------------------";
@@ -429,17 +438,17 @@ static Suppression *GetSuppressionForAddr(uptr addr) {
// Suppress by module name.
const char *module_name;
uptr module_offset;
+ SuppressionContext *suppressions = GetSuppressionContext();
if (Symbolizer::GetOrInit()->GetModuleNameAndOffsetForPC(addr, &module_name,
&module_offset) &&
- SuppressionContext::Get()->Match(module_name, SuppressionLeak, &s))
+ suppressions->Match(module_name, kSuppressionLeak, &s))
return s;
// Suppress by file or function name.
SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(addr);
for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
- if (SuppressionContext::Get()->Match(cur->info.function, SuppressionLeak,
- &s) ||
- SuppressionContext::Get()->Match(cur->info.file, SuppressionLeak, &s)) {
+ if (suppressions->Match(cur->info.function, kSuppressionLeak, &s) ||
+ suppressions->Match(cur->info.file, kSuppressionLeak, &s)) {
break;
}
}
diff --git a/compiler-rt/lib/lsan/lsan_flags.inc b/compiler-rt/lib/lsan/lsan_flags.inc
index 7f00acbf911..b19b3452b2f 100644
--- a/compiler-rt/lib/lsan/lsan_flags.inc
+++ b/compiler-rt/lib/lsan/lsan_flags.inc
@@ -42,3 +42,4 @@ LSAN_FLAG(bool, use_poisoned, false,
"Consider pointers found in poisoned memory to be valid.")
LSAN_FLAG(bool, log_pointers, false, "Debug logging")
LSAN_FLAG(bool, log_threads, false, "Debug logging")
+LSAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc
index e8c8a87537d..58f7f372228 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc
@@ -128,7 +128,6 @@ COMMON_FLAG(const char *, coverage_dir, ".",
COMMON_FLAG(bool, full_address_space, false,
"Sanitize complete address space; "
"by default kernel area on 32-bit platforms will not be sanitized")
-COMMON_FLAG(const char *, suppressions, "", "Suppressions file name.")
COMMON_FLAG(bool, print_suppressions, true,
"Print matched suppressions at exit.")
COMMON_FLAG(
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
index ec4789c90f2..2b697e95570 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.cc
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// Suppression parsing/matching code shared between TSan and LSan.
+// Suppression parsing/matching code.
//
//===----------------------------------------------------------------------===//
@@ -21,55 +21,43 @@
namespace __sanitizer {
-static const char *const kTypeStrings[SuppressionTypeCount] = {
- "none", "race", "mutex", "thread", "signal", "leak", "called_from_lib",
- "deadlock", "vptr_check", "interceptor_name", "interceptor_via_fun",
- "interceptor_via_lib"};
-
-ALIGNED(64) static char placeholder[sizeof(SuppressionContext)];
-static SuppressionContext *suppression_ctx = 0;
-
-SuppressionContext::SuppressionContext() : suppressions_(1), can_parse_(true) {
- internal_memset(has_suppresson_type_, 0, sizeof(has_suppresson_type_));
-}
-
-SuppressionContext *SuppressionContext::Get() {
- CHECK(suppression_ctx);
- return suppression_ctx;
+SuppressionContext::SuppressionContext(const char *suppression_types[],
+ int suppression_types_num)
+ : suppression_types_(suppression_types),
+ suppression_types_num_(suppression_types_num), suppressions_(1),
+ can_parse_(true) {
+ CHECK_LE(suppression_types_num_, kMaxSuppressionTypes);
+ internal_memset(has_suppression_type_, 0, suppression_types_num_);
}
-void SuppressionContext::InitIfNecessary() {
- if (suppression_ctx)
+void SuppressionContext::ParseFromFile(const char *filename) {
+ if (filename[0] == '\0')
return;
- suppression_ctx = new(placeholder) SuppressionContext;
- if (common_flags()->suppressions[0] == '\0')
- return;
- char *suppressions_from_file;
+ char *file_contents;
uptr buffer_size;
- uptr contents_size =
- ReadFileToBuffer(common_flags()->suppressions, &suppressions_from_file,
- &buffer_size, 1 << 26 /* max_len */);
+ uptr contents_size = ReadFileToBuffer(filename, &file_contents, &buffer_size,
+ 1 << 26 /* max_len */);
if (contents_size == 0) {
Printf("%s: failed to read suppressions file '%s'\n", SanitizerToolName,
- common_flags()->suppressions);
+ filename);
Die();
}
- suppression_ctx->Parse(suppressions_from_file);
+ Parse(file_contents);
}
-bool SuppressionContext::Match(const char *str, SuppressionType type,
+bool SuppressionContext::Match(const char *str, const char *type,
Suppression **s) {
- if (!has_suppresson_type_[type])
- return false;
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;
+ if (!HasSuppressionType(type))
+ return false;
+ for (uptr i = 0; i < suppressions_.size(); i++) {
+ Suppression &cur = suppressions_[i];
+ if (0 == internal_strcmp(cur.type, type) && TemplateMatch(cur.templ, str)) {
+ *s = &cur;
+ return true;
+ }
+ }
+ return false;
}
static const char *StripPrefix(const char *str, const char *prefix) {
@@ -97,26 +85,26 @@ void SuppressionContext::Parse(const char *str) {
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]);
+ for (type = 0; type < suppression_types_num_; type++) {
+ const char *next_char = StripPrefix(line, suppression_types_[type]);
if (next_char && *next_char == ':') {
line = ++next_char;
break;
}
}
- if (type == SuppressionTypeCount) {
+ if (type == suppression_types_num_) {
Printf("%s: failed to parse suppressions\n", SanitizerToolName);
Die();
}
Suppression s;
- s.type = static_cast<SuppressionType>(type);
+ s.type = suppression_types_[type];
s.templ = (char*)InternalAlloc(end2 - line + 1);
internal_memcpy(s.templ, line, end2 - line);
s.templ[end2 - line] = 0;
s.hit_count = 0;
s.weight = 0;
suppressions_.push_back(s);
- has_suppresson_type_[s.type] = true;
+ has_suppression_type_[type] = true;
}
if (end[0] == 0)
break;
@@ -128,8 +116,12 @@ uptr SuppressionContext::SuppressionCount() const {
return suppressions_.size();
}
-bool SuppressionContext::HasSuppressionType(SuppressionType type) const {
- return has_suppresson_type_[type];
+bool SuppressionContext::HasSuppressionType(const char *type) const {
+ for (int i = 0; i < suppression_types_num_; i++) {
+ if (0 == internal_strcmp(type, suppression_types_[i]))
+ return has_suppression_type_[i];
+ }
+ return false;
}
const Suppression *SuppressionContext::SuppressionAt(uptr i) const {
@@ -144,9 +136,4 @@ void SuppressionContext::GetMatched(
matched->push_back(&suppressions_[i]);
}
-const char *SuppressionTypeString(SuppressionType t) {
- CHECK(t < SuppressionTypeCount);
- return kTypeStrings[t];
-}
-
} // namespace __sanitizer
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h
index afb3150fea6..02dbf6f9690 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_suppressions.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// Suppression parsing/matching code shared between TSan and LSan.
+// Suppression parsing/matching code.
//
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_SUPPRESSIONS_H
@@ -18,24 +18,8 @@
namespace __sanitizer {
-enum SuppressionType {
- SuppressionNone,
- SuppressionRace,
- SuppressionMutex,
- SuppressionThread,
- SuppressionSignal,
- SuppressionLeak,
- SuppressionLib,
- SuppressionDeadlock,
- SuppressionVptrCheck,
- SuppressionInterceptorName,
- SuppressionInterceptorViaFunction,
- SuppressionInterceptorViaLibrary,
- SuppressionTypeCount
-};
-
struct Suppression {
- SuppressionType type;
+ const char *type;
char *templ;
unsigned hit_count;
uptr weight;
@@ -43,31 +27,29 @@ struct Suppression {
class SuppressionContext {
public:
+ // Create new SuppressionContext capable of parsing given suppression types.
+ SuppressionContext(const char *supprression_types[],
+ int suppression_types_num);
+
+ void ParseFromFile(const char *filename);
void Parse(const char *str);
- bool Match(const char* str, SuppressionType type, Suppression **s);
+
+ bool Match(const char *str, const char *type, Suppression **s);
uptr SuppressionCount() const;
- bool HasSuppressionType(SuppressionType type) const;
+ bool HasSuppressionType(const char *type) const;
const Suppression *SuppressionAt(uptr i) const;
void GetMatched(InternalMmapVector<Suppression *> *matched);
- // Create a SuppressionContext singleton if it hasn't been created earlier.
- // Not thread safe. Must be called early during initialization (but after
- // runtime flags are parsed).
- static void InitIfNecessary();
- // Returns a SuppressionContext singleton.
- static SuppressionContext *Get();
-
private:
- SuppressionContext();
+ static const int kMaxSuppressionTypes = 16;
+ const char **const suppression_types_;
+ const int suppression_types_num_;
+
InternalMmapVector<Suppression> suppressions_;
- bool has_suppresson_type_[SuppressionTypeCount];
+ bool has_suppression_type_[kMaxSuppressionTypes];
bool can_parse_;
-
- friend class SuppressionContextTest;
};
-const char *SuppressionTypeString(SuppressionType t);
-
} // namespace __sanitizer
#endif // SANITIZER_SUPPRESSIONS_H
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc b/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
index 0699243283d..e8c30d07e78 100644
--- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_suppressions_test.cc
@@ -58,117 +58,77 @@ TEST(Suppressions, Match) {
EXPECT_FALSE(MyMatch("foo$^bar", "foobar"));
}
-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"));
- CHECK(!internal_strcmp(SuppressionTypeString(SuppressionLeak), "leak"));
- CHECK(!internal_strcmp(SuppressionTypeString(SuppressionLib),
- "called_from_lib"));
- CHECK(
- !internal_strcmp(SuppressionTypeString(SuppressionDeadlock), "deadlock"));
- CHECK(!internal_strcmp(SuppressionTypeString(SuppressionVptrCheck),
- "vptr_check"));
- CHECK(!internal_strcmp(SuppressionTypeString(SuppressionInterceptorName),
- "interceptor_name"));
- CHECK(
- !internal_strcmp(SuppressionTypeString(SuppressionInterceptorViaFunction),
- "interceptor_via_fun"));
- CHECK(
- !internal_strcmp(SuppressionTypeString(SuppressionInterceptorViaLibrary),
- "interceptor_via_lib"));
- // Ensure this test is up-to-date when suppression types are added.
- CHECK_EQ(12, SuppressionTypeCount);
-}
+static const char *kTestSuppressionTypes[] = {"race", "thread", "mutex",
+ "signal"};
class SuppressionContextTest : public ::testing::Test {
public:
- virtual void SetUp() { ctx_ = new(placeholder_) SuppressionContext; }
- virtual void TearDown() { ctx_->~SuppressionContext(); }
+ SuppressionContextTest()
+ : ctx_(kTestSuppressionTypes, ARRAY_SIZE(kTestSuppressionTypes)) {}
protected:
- InternalMmapVector<Suppression> *Suppressions() {
- return &ctx_->suppressions_;
+ SuppressionContext ctx_;
+
+ void CheckSuppressions(unsigned count, std::vector<const char *> types,
+ std::vector<const char *> templs) const {
+ EXPECT_EQ(count, ctx_.SuppressionCount());
+ for (unsigned i = 0; i < count; i++) {
+ const Suppression *s = ctx_.SuppressionAt(i);
+ EXPECT_STREQ(types[i], s->type);
+ EXPECT_STREQ(templs[i], s->templ);
+ }
}
- 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"));
+ ctx_.Parse("race:foo\n"
+ " race:bar\n" // NOLINT
+ "race:baz \n" // NOLINT
+ "# a comment\n"
+ "race:quz\n"); // NOLINT
+ CheckSuppressions(4, {"race", "race", "race", "race"},
+ {"foo", "bar", "baz", "quz"});
}
TEST_F(SuppressionContextTest, Parse2) {
- ctx_->Parse(
+ 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"));
+ CheckSuppressions(2, {"race", "race"}, {"bar", "baz* *baz"});
}
TEST_F(SuppressionContextTest, Parse3) {
- ctx_->Parse(
+ 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"));
+ CheckSuppressions(2, {"race", "race"}, {"foo", "bar"});
}
TEST_F(SuppressionContextTest, ParseType) {
- ctx_->Parse(
+ 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"));
+ CheckSuppressions(4, {"race", "thread", "mutex", "signal"},
+ {"foo", "bar", "baz", "quz"});
}
TEST_F(SuppressionContextTest, HasSuppressionType) {
- ctx_->Parse(
+ ctx_.Parse(
"race:foo\n"
"thread:bar\n");
- EXPECT_TRUE(ctx_->HasSuppressionType(SuppressionRace));
- EXPECT_TRUE(ctx_->HasSuppressionType(SuppressionThread));
- EXPECT_FALSE(ctx_->HasSuppressionType(SuppressionMutex));
- EXPECT_FALSE(ctx_->HasSuppressionType(SuppressionSignal));
+ EXPECT_TRUE(ctx_.HasSuppressionType("race"));
+ EXPECT_TRUE(ctx_.HasSuppressionType("thread"));
+ EXPECT_FALSE(ctx_.HasSuppressionType("mutex"));
+ EXPECT_FALSE(ctx_.HasSuppressionType("signal"));
}
} // namespace __sanitizer
diff --git a/compiler-rt/lib/tsan/rtl/tsan_flags.inc b/compiler-rt/lib/tsan/rtl/tsan_flags.inc
index d15b722ee5e..e4994685fa0 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_flags.inc
+++ b/compiler-rt/lib/tsan/rtl/tsan_flags.inc
@@ -76,3 +76,4 @@ TSAN_FLAG(int, io_sync, 1,
"2 - global synchronization of all IO operations.")
TSAN_FLAG(bool, die_after_fork, true,
"Die after multi-threaded fork if the child creates new threads.")
+TSAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
index de469ce645b..31ff7d56aac 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc
@@ -182,11 +182,11 @@ static LibIgnore *libignore() {
}
void InitializeLibIgnore() {
- const SuppressionContext &supp = *SuppressionContext::Get();
+ const SuppressionContext &supp = *Suppressions();
const uptr n = supp.SuppressionCount();
for (uptr i = 0; i < n; i++) {
const Suppression *s = supp.SuppressionAt(i);
- if (s->type == SuppressionLib)
+ if (0 == internal_strcmp(s->type, kSuppressionLib))
libignore()->AddIgnoredLibrary(s->templ);
}
libignore()->OnLibraryLoaded(0);
diff --git a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc
index 299fc80fd26..5413f04af1d 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc
@@ -41,63 +41,74 @@ extern "C" const char *WEAK __tsan_default_suppressions() {
namespace __tsan {
-static bool suppressions_inited = false;
+ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
+static SuppressionContext *suppression_ctx = nullptr;
+static const char *kSuppressionTypes[] = {
+ kSuppressionRace, kSuppressionMutex, kSuppressionThread,
+ kSuppressionSignal, kSuppressionLib, kSuppressionDeadlock};
void InitializeSuppressions() {
- CHECK(!suppressions_inited);
- SuppressionContext::InitIfNecessary();
+ CHECK_EQ(nullptr, suppression_ctx);
+ suppression_ctx = new (suppression_placeholder) // NOLINT
+ SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
+ suppression_ctx->ParseFromFile(flags()->suppressions);
#ifndef SANITIZER_GO
- SuppressionContext::Get()->Parse(__tsan_default_suppressions());
- SuppressionContext::Get()->Parse(std_suppressions);
+ suppression_ctx->Parse(__tsan_default_suppressions());
+ suppression_ctx->Parse(std_suppressions);
#endif
- suppressions_inited = true;
}
-SuppressionType conv(ReportType typ) {
+SuppressionContext *Suppressions() {
+ CHECK(suppression_ctx);
+ return suppression_ctx;
+}
+
+static const char *conv(ReportType typ) {
if (typ == ReportTypeRace)
- return SuppressionRace;
+ return kSuppressionRace;
else if (typ == ReportTypeVptrRace)
- return SuppressionRace;
+ return kSuppressionRace;
else if (typ == ReportTypeUseAfterFree)
- return SuppressionRace;
+ return kSuppressionRace;
else if (typ == ReportTypeVptrUseAfterFree)
- return SuppressionRace;
+ return kSuppressionRace;
else if (typ == ReportTypeThreadLeak)
- return SuppressionThread;
+ return kSuppressionThread;
else if (typ == ReportTypeMutexDestroyLocked)
- return SuppressionMutex;
+ return kSuppressionMutex;
else if (typ == ReportTypeMutexDoubleLock)
- return SuppressionMutex;
+ return kSuppressionMutex;
else if (typ == ReportTypeMutexBadUnlock)
- return SuppressionMutex;
+ return kSuppressionMutex;
else if (typ == ReportTypeMutexBadReadLock)
- return SuppressionMutex;
+ return kSuppressionMutex;
else if (typ == ReportTypeMutexBadReadUnlock)
- return SuppressionMutex;
+ return kSuppressionMutex;
else if (typ == ReportTypeSignalUnsafe)
- return SuppressionSignal;
+ return kSuppressionSignal;
else if (typ == ReportTypeErrnoInSignal)
- return SuppressionNone;
+ return kSuppressionNone;
else if (typ == ReportTypeDeadlock)
- return SuppressionDeadlock;
+ return kSuppressionDeadlock;
Printf("ThreadSanitizer: unknown report type %d\n", typ),
Die();
}
uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
- if (!SuppressionContext::Get()->SuppressionCount() || stack == 0 ||
+ CHECK(suppression_ctx);
+ if (!suppression_ctx->SuppressionCount() || stack == 0 ||
!stack->suppressable)
return 0;
- SuppressionType stype = conv(typ);
- if (stype == SuppressionNone)
+ const char *stype = conv(typ);
+ if (0 == internal_strcmp(stype, kSuppressionNone))
return 0;
Suppression *s;
for (const SymbolizedStack *frame = stack->frames; frame;
frame = frame->next) {
const AddressInfo &info = frame->info;
- if (SuppressionContext::Get()->Match(info.function, stype, &s) ||
- SuppressionContext::Get()->Match(info.file, stype, &s) ||
- SuppressionContext::Get()->Match(info.module, stype, &s)) {
+ if (suppression_ctx->Match(info.function, stype, &s) ||
+ suppression_ctx->Match(info.file, stype, &s) ||
+ suppression_ctx->Match(info.module, stype, &s)) {
DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
s->hit_count++;
*sp = s;
@@ -108,16 +119,17 @@ uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
}
uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
- if (!SuppressionContext::Get()->SuppressionCount() || loc == 0 ||
+ CHECK(suppression_ctx);
+ if (!suppression_ctx->SuppressionCount() || loc == 0 ||
loc->type != ReportLocationGlobal || !loc->suppressable)
return 0;
- SuppressionType stype = conv(typ);
- if (stype == SuppressionNone)
+ const char *stype = conv(typ);
+ if (0 == internal_strcmp(stype, kSuppressionNone))
return 0;
Suppression *s;
const DataInfo &global = loc->global;
- if (SuppressionContext::Get()->Match(global.name, stype, &s) ||
- SuppressionContext::Get()->Match(global.module, stype, &s)) {
+ if (suppression_ctx->Match(global.name, stype, &s) ||
+ suppression_ctx->Match(global.module, stype, &s)) {
DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
s->hit_count++;
*sp = s;
@@ -128,7 +140,8 @@ uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
void PrintMatchedSuppressions() {
InternalMmapVector<Suppression *> matched(1);
- SuppressionContext::Get()->GetMatched(&matched);
+ CHECK(suppression_ctx);
+ suppression_ctx->GetMatched(&matched);
if (!matched.size())
return;
int hit_count = 0;
@@ -137,8 +150,8 @@ void PrintMatchedSuppressions() {
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);
+ Printf("%d %s:%s\n", matched[i]->hit_count, matched[i]->type,
+ matched[i]->templ);
}
}
} // namespace __tsan
diff --git a/compiler-rt/lib/tsan/rtl/tsan_suppressions.h b/compiler-rt/lib/tsan/rtl/tsan_suppressions.h
index c618b3db4c2..e6d279c33a4 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_suppressions.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_suppressions.h
@@ -18,7 +18,16 @@
namespace __tsan {
+const char kSuppressionNone[] = "none";
+const char kSuppressionRace[] = "race";
+const char kSuppressionMutex[] = "mutex";
+const char kSuppressionThread[] = "thread";
+const char kSuppressionSignal[] = "signal";
+const char kSuppressionLib[] = "called_from_lib";
+const char kSuppressionDeadlock[] = "deadlock";
+
void InitializeSuppressions();
+SuppressionContext *Suppressions();
void PrintMatchedSuppressions();
uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp);
uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp);
diff --git a/compiler-rt/lib/ubsan/ubsan_diag.cc b/compiler-rt/lib/ubsan/ubsan_diag.cc
index 57890f71137..4f2a2a9f356 100644
--- a/compiler-rt/lib/ubsan/ubsan_diag.cc
+++ b/compiler-rt/lib/ubsan/ubsan_diag.cc
@@ -14,9 +14,11 @@
#include "ubsan_diag.h"
#include "ubsan_init.h"
#include "ubsan_flags.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_report_decorator.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "sanitizer_common/sanitizer_stacktrace_printer.h"
+#include "sanitizer_common/sanitizer_suppressions.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
#include <stdio.h>
@@ -333,11 +335,24 @@ ScopedReport::~ScopedReport() {
Die();
}
-bool __ubsan::MatchSuppression(const char *Str, SuppressionType Type) {
- Suppression *s;
+ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
+static SuppressionContext *suppression_ctx = nullptr;
+static const char kVptrCheck[] = "vptr_check";
+static const char *kSuppressionTypes[] = { kVptrCheck };
+
+void __ubsan::InitializeSuppressions() {
+ CHECK_EQ(nullptr, suppression_ctx);
+ suppression_ctx = new (suppression_placeholder) // NOLINT
+ SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
+ suppression_ctx->ParseFromFile(flags()->suppressions);
+}
+
+bool __ubsan::IsVptrCheckSuppressed(const char *TypeName) {
// If .preinit_array is not used, it is possible that the UBSan runtime is not
// initialized.
if (!SANITIZER_CAN_USE_PREINIT_ARRAY)
InitIfNecessary();
- return SuppressionContext::Get()->Match(Str, Type, &s);
+ CHECK(suppression_ctx);
+ Suppression *s;
+ return suppression_ctx->Match(TypeName, kVptrCheck, &s);
}
diff --git a/compiler-rt/lib/ubsan/ubsan_diag.h b/compiler-rt/lib/ubsan/ubsan_diag.h
index e1c6571f542..44dca90b7a5 100644
--- a/compiler-rt/lib/ubsan/ubsan_diag.h
+++ b/compiler-rt/lib/ubsan/ubsan_diag.h
@@ -15,7 +15,6 @@
#include "ubsan_value.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
-#include "sanitizer_common/sanitizer_suppressions.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
namespace __ubsan {
@@ -236,7 +235,8 @@ public:
~ScopedReport();
};
-bool MatchSuppression(const char *Str, SuppressionType Type);
+void InitializeSuppressions();
+bool IsVptrCheckSuppressed(const char *TypeName);
} // namespace __ubsan
diff --git a/compiler-rt/lib/ubsan/ubsan_flags.inc b/compiler-rt/lib/ubsan/ubsan_flags.inc
index 3260e8e13df..9ca31d13a9b 100644
--- a/compiler-rt/lib/ubsan/ubsan_flags.inc
+++ b/compiler-rt/lib/ubsan/ubsan_flags.inc
@@ -21,4 +21,5 @@ UBSAN_FLAG(bool, halt_on_error, false,
"Crash the program after printing the first error report")
UBSAN_FLAG(bool, print_stacktrace, false,
"Include full stacktrace into an error report")
+UBSAN_FLAG(const char *, suppressions, "", "Suppressions file name.")
diff --git a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc
index 5704c1e6342..4718e6eacee 100644
--- a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc
+++ b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc
@@ -36,8 +36,7 @@ static void HandleDynamicTypeCacheMiss(
// Check if error report should be suppressed.
DynamicTypeInfo DTI = getDynamicTypeInfo((void*)Pointer);
- if (DTI.isValid() &&
- MatchSuppression(DTI.getMostDerivedTypeName(), SuppressionVptrCheck))
+ if (DTI.isValid() && IsVptrCheckSuppressed(DTI.getMostDerivedTypeName()))
return;
SourceLocation Loc = Data->Loc.acquire();
diff --git a/compiler-rt/lib/ubsan/ubsan_init.cc b/compiler-rt/lib/ubsan/ubsan_init.cc
index 48fa492486d..219273d5192 100644
--- a/compiler-rt/lib/ubsan/ubsan_init.cc
+++ b/compiler-rt/lib/ubsan/ubsan_init.cc
@@ -11,12 +11,12 @@
//
//===----------------------------------------------------------------------===//
+#include "ubsan_diag.h"
#include "ubsan_init.h"
#include "ubsan_flags.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_mutex.h"
-#include "sanitizer_common/sanitizer_suppressions.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
using namespace __ubsan;
@@ -43,7 +43,7 @@ void __ubsan::InitIfNecessary() {
}
// Initialize UBSan-specific flags.
InitializeFlags(standalone);
- SuppressionContext::InitIfNecessary();
+ InitializeSuppressions();
InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
ubsan_inited = true;
}
diff --git a/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp b/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp
index dc408d39ad3..1f8ee02641a 100644
--- a/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp
+++ b/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr.cpp
@@ -12,16 +12,16 @@
// RUN: %run %t m0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL-MEMBER --strict-whitespace
// RUN: (echo "vptr_check:S"; echo "vptr_check:T"; echo "vptr_check:U") > %t.supp
-// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mS 2>&1
-// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fS 2>&1
-// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cS 2>&1
-// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mV 2>&1
-// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fV 2>&1
-// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cV 2>&1
-// RUN: ASAN_OPTIONS="suppressions='%t.supp'" UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t oU 2>&1
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mS 2>&1
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fS 2>&1
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cS 2>&1
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t mV 2>&1
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t fV 2>&1
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t cV 2>&1
+// RUN: UBSAN_OPTIONS="suppressions='%t.supp':halt_on_error=1" %run %t oU 2>&1
// RUN: echo "vptr_check:S" > %t.loc-supp
-// RUN: ASAN_OPTIONS="suppressions='%t.loc-supp'" UBSAN_OPTIONS="suppressions='%t.loc-supp':halt_on_error=1" not %run %t x- 2>&1 | FileCheck %s --check-prefix=CHECK-LOC-SUPPRESS
+// RUN: UBSAN_OPTIONS="suppressions='%t.loc-supp':halt_on_error=1" not %run %t x- 2>&1 | FileCheck %s --check-prefix=CHECK-LOC-SUPPRESS
// FIXME: This test produces linker errors on Darwin.
// XFAIL: darwin
OpenPOWER on IntegriCloud