[Sanitizer] Make SuppressionContext a singleton class, residing in sanitizer_common.

Convert TSan and LSan to the new interface. More changes will follow:
1) "suppressions" should become a common runtime flag.
2) Code for parsing suppressions file should be moved to SuppressionContext::Init().

llvm-svn: 214334
This commit is contained in:
Alexey Samsonov 2014-07-30 20:54:37 +00:00
parent cab7ca3e2a
commit 34a4c6e12f
6 changed files with 45 additions and 38 deletions

View File

@ -87,24 +87,20 @@ static void InitializeFlags() {
if (flags()->log_threads) Report(__VA_ARGS__); \
} while (0);
SuppressionContext *suppression_ctx;
void InitializeSuppressions() {
CHECK(!suppression_ctx);
ALIGNED(64) static char placeholder[sizeof(SuppressionContext)];
suppression_ctx = new(placeholder) SuppressionContext;
SuppressionContext::Init();
char *suppressions_from_file;
uptr buffer_size;
if (ReadFileToBuffer(flags()->suppressions, &suppressions_from_file,
&buffer_size, 1 << 26 /* max_len */))
suppression_ctx->Parse(suppressions_from_file);
SuppressionContext::Get()->Parse(suppressions_from_file);
if (flags()->suppressions[0] && !buffer_size) {
Printf("LeakSanitizer: failed to read suppressions file '%s'\n",
flags()->suppressions);
Die();
}
if (&__lsan_default_suppressions)
suppression_ctx->Parse(__lsan_default_suppressions());
SuppressionContext::Get()->Parse(__lsan_default_suppressions());
}
struct RootRegion {
@ -389,7 +385,7 @@ static void CollectLeaksCb(uptr chunk, void *arg) {
static void PrintMatchedSuppressions() {
InternalMmapVector<Suppression *> matched(1);
suppression_ctx->GetMatched(&matched);
SuppressionContext::Get()->GetMatched(&matched);
if (!matched.size())
return;
const char *line = "-----------------------------------------------------";
@ -467,7 +463,7 @@ static Suppression *GetSuppressionForAddr(uptr addr) {
uptr module_offset;
if (Symbolizer::Get()->GetModuleNameAndOffsetForPC(addr, &module_name,
&module_offset) &&
suppression_ctx->Match(module_name, SuppressionLeak, &s))
SuppressionContext::Get()->Match(module_name, SuppressionLeak, &s))
return s;
// Suppress by file or function name.
@ -477,8 +473,10 @@ static Suppression *GetSuppressionForAddr(uptr addr) {
uptr addr_frames_num = Symbolizer::Get()->SymbolizePC(
addr, addr_frames.data(), kMaxAddrFrames);
for (uptr i = 0; i < addr_frames_num; i++) {
if (suppression_ctx->Match(addr_frames[i].function, SuppressionLeak, &s) ||
suppression_ctx->Match(addr_frames[i].file, SuppressionLeak, &s))
if (SuppressionContext::Get()->Match(addr_frames[i].function,
SuppressionLeak, &s) ||
SuppressionContext::Get()->Match(addr_frames[i].file, SuppressionLeak,
&s))
return s;
}
return 0;

View File

@ -16,6 +16,7 @@
#include "sanitizer_allocator_internal.h"
#include "sanitizer_common.h"
#include "sanitizer_libc.h"
#include "sanitizer_placement_new.h"
namespace __sanitizer {
@ -65,6 +66,19 @@ bool TemplateMatch(char *templ, const char *str) {
return true;
}
ALIGNED(64) static char placeholder[sizeof(SuppressionContext)];
static SuppressionContext *suppression_ctx = 0;
SuppressionContext *SuppressionContext::Get() {
CHECK(suppression_ctx);
return suppression_ctx;
}
void SuppressionContext::Init() {
CHECK(!suppression_ctx);
suppression_ctx = new(placeholder) SuppressionContext;
}
bool SuppressionContext::Match(const char *str, SuppressionType type,
Suppression **s) {
can_parse_ = false;

View File

@ -39,14 +39,20 @@ struct Suppression {
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() const;
const Suppression *SuppressionAt(uptr i) const;
void GetMatched(InternalMmapVector<Suppression *> *matched);
// Create a SuppressionContext singleton. Not thread safe. Must be called
// early during initialization.
static void Init();
// Returns a SuppressionContext singleton.
static SuppressionContext *Get();
private:
SuppressionContext() : suppressions_(1), can_parse_(true) {}
InternalMmapVector<Suppression> suppressions_;
bool can_parse_;

View File

@ -138,7 +138,7 @@ static LibIgnore *libignore() {
}
void InitializeLibIgnore() {
libignore()->Init(*GetSuppressionContext());
libignore()->Init(*SuppressionContext::Get());
libignore()->OnLibraryLoaded(0);
}

View File

@ -41,8 +41,6 @@ extern "C" const char *WEAK __tsan_default_suppressions() {
namespace __tsan {
static SuppressionContext* g_ctx;
static char *ReadFile(const char *filename) {
if (filename == 0 || filename[0] == 0)
return 0;
@ -76,22 +74,16 @@ static char *ReadFile(const char *filename) {
}
void InitializeSuppressions() {
ALIGNED(64) static char placeholder_[sizeof(SuppressionContext)];
g_ctx = new(placeholder_) SuppressionContext;
SuppressionContext::Init();
const char *supp = ReadFile(flags()->suppressions);
g_ctx->Parse(supp);
SuppressionContext::Get()->Parse(supp);
#ifndef TSAN_GO
supp = __tsan_default_suppressions();
g_ctx->Parse(supp);
g_ctx->Parse(std_suppressions);
SuppressionContext::Get()->Parse(supp);
SuppressionContext::Get()->Parse(std_suppressions);
#endif
}
SuppressionContext *GetSuppressionContext() {
CHECK_NE(g_ctx, 0);
return g_ctx;
}
SuppressionType conv(ReportType typ) {
if (typ == ReportTypeRace)
return SuppressionRace;
@ -122,17 +114,17 @@ SuppressionType conv(ReportType typ) {
}
uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
CHECK(g_ctx);
if (!g_ctx->SuppressionCount() || stack == 0 || !stack->suppressable)
if (!SuppressionContext::Get()->SuppressionCount() || stack == 0 ||
!stack->suppressable)
return 0;
SuppressionType stype = conv(typ);
if (stype == SuppressionNone)
return 0;
Suppression *s;
for (const ReportStack *frame = stack; frame; frame = frame->next) {
if (g_ctx->Match(frame->func, stype, &s) ||
g_ctx->Match(frame->file, stype, &s) ||
g_ctx->Match(frame->module, stype, &s)) {
if (SuppressionContext::Get()->Match(frame->func, stype, &s) ||
SuppressionContext::Get()->Match(frame->file, stype, &s) ||
SuppressionContext::Get()->Match(frame->module, stype, &s)) {
DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
s->hit_count++;
*sp = s;
@ -143,17 +135,16 @@ uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp) {
}
uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
CHECK(g_ctx);
if (!g_ctx->SuppressionCount() || loc == 0 ||
if (!SuppressionContext::Get()->SuppressionCount() || loc == 0 ||
loc->type != ReportLocationGlobal || !loc->suppressable)
return 0;
SuppressionType stype = conv(typ);
if (stype == SuppressionNone)
return 0;
Suppression *s;
if (g_ctx->Match(loc->name, stype, &s) ||
g_ctx->Match(loc->file, stype, &s) ||
g_ctx->Match(loc->module, stype, &s)) {
if (SuppressionContext::Get()->Match(loc->name, stype, &s) ||
SuppressionContext::Get()->Match(loc->file, stype, &s) ||
SuppressionContext::Get()->Match(loc->module, stype, &s)) {
DPrintf("ThreadSanitizer: matched suppression '%s'\n", s->templ);
s->hit_count++;
*sp = s;
@ -163,9 +154,8 @@ uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp) {
}
void PrintMatchedSuppressions() {
CHECK(g_ctx);
InternalMmapVector<Suppression *> matched(1);
g_ctx->GetMatched(&matched);
SuppressionContext::Get()->GetMatched(&matched);
if (!matched.size())
return;
int hit_count = 0;

View File

@ -22,7 +22,6 @@ void InitializeSuppressions();
void PrintMatchedSuppressions();
uptr IsSuppressed(ReportType typ, const ReportStack *stack, Suppression **sp);
uptr IsSuppressed(ReportType typ, const ReportLocation *loc, Suppression **sp);
SuppressionContext *GetSuppressionContext();
} // namespace __tsan