[lsan] Parse suppressions just before leak reporting

Without leaks suppressions are not needed.
This commit is contained in:
Vitaly Buka 2020-12-29 17:18:39 -08:00
parent d034a94e7b
commit 9a5261efd7
1 changed files with 50 additions and 22 deletions

View File

@ -65,8 +65,24 @@ void RegisterLsanFlags(FlagParser *parser, Flags *f) {
if (flags()->log_threads) Report(__VA_ARGS__); \
} while (0)
ALIGNED(64) static char suppression_placeholder[sizeof(SuppressionContext)];
static SuppressionContext *suppression_ctx = nullptr;
class LeakSuppressionContext {
bool parsed = false;
SuppressionContext context;
Suppression *GetSuppressionForAddr(uptr addr);
void LazyParse();
public:
LeakSuppressionContext(const char *supprression_types[],
int suppression_types_num)
: context(supprression_types, suppression_types_num) {}
Suppression *GetSuppressionForStack(u32 stack_trace_id);
void PrintMatchedSuppressions();
};
ALIGNED(64) static char suppression_placeholder[sizeof(LeakSuppressionContext)];
static LeakSuppressionContext *suppression_ctx = nullptr;
static const char kSuppressionLeak[] = "leak";
static const char *kSuppressionTypes[] = { kSuppressionLeak };
static const char kStdSuppressions[] =
@ -86,14 +102,20 @@ static const char kStdSuppressions[] =
void InitializeSuppressions() {
CHECK_EQ(nullptr, suppression_ctx);
suppression_ctx = new (suppression_placeholder)
SuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
suppression_ctx->ParseFromFile(flags()->suppressions);
if (&__lsan_default_suppressions)
suppression_ctx->Parse(__lsan_default_suppressions());
suppression_ctx->Parse(kStdSuppressions);
LeakSuppressionContext(kSuppressionTypes, ARRAY_SIZE(kSuppressionTypes));
}
static SuppressionContext *GetSuppressionContext() {
void LeakSuppressionContext::LazyParse() {
if (!parsed) {
parsed = true;
context.ParseFromFile(flags()->suppressions);
if (&__lsan_default_suppressions)
context.Parse(__lsan_default_suppressions());
context.Parse(kStdSuppressions);
}
}
static LeakSuppressionContext *GetSuppressionContext() {
CHECK(suppression_ctx);
return suppression_ctx;
}
@ -532,18 +554,20 @@ static void CollectLeaksCb(uptr chunk, void *arg) {
}
}
static void PrintMatchedSuppressions() {
void LeakSuppressionContext::PrintMatchedSuppressions() {
InternalMmapVector<Suppression *> matched;
GetSuppressionContext()->GetMatched(&matched);
context.GetMatched(&matched);
if (!matched.size())
return;
const char *line = "-----------------------------------------------------";
Printf("%s\n", line);
Printf("Suppressions used:\n");
Printf(" count bytes template\n");
for (uptr i = 0; i < matched.size(); i++)
Printf("%7zu %10zu %s\n", static_cast<uptr>(atomic_load_relaxed(
&matched[i]->hit_count)), matched[i]->weight, matched[i]->templ);
for (uptr i = 0; i < matched.size(); i++) {
Printf("%7zu %10zu %s\n",
static_cast<uptr>(atomic_load_relaxed(&matched[i]->hit_count)),
matched[i]->weight, matched[i]->templ);
}
Printf("%s\n\n", line);
}
@ -623,7 +647,7 @@ static bool CheckForLeaks() {
param.leak_report.ReportTopLeaks(flags()->max_leaks);
}
if (common_flags()->print_suppressions)
PrintMatchedSuppressions();
GetSuppressionContext()->PrintMatchedSuppressions();
if (unsuppressed_count > 0) {
param.leak_report.PrintSummary();
return true;
@ -651,21 +675,20 @@ static int DoRecoverableLeakCheck() {
void DoRecoverableLeakCheckVoid() { DoRecoverableLeakCheck(); }
static Suppression *GetSuppressionForAddr(uptr addr) {
Suppression *LeakSuppressionContext::GetSuppressionForAddr(uptr addr) {
Suppression *s = nullptr;
// Suppress by module name.
SuppressionContext *suppressions = GetSuppressionContext();
if (const char *module_name =
Symbolizer::GetOrInit()->GetModuleNameForPc(addr))
if (suppressions->Match(module_name, kSuppressionLeak, &s))
if (context.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 (suppressions->Match(cur->info.function, kSuppressionLeak, &s) ||
suppressions->Match(cur->info.file, kSuppressionLeak, &s)) {
if (context.Match(cur->info.function, kSuppressionLeak, &s) ||
context.Match(cur->info.file, kSuppressionLeak, &s)) {
break;
}
}
@ -673,12 +696,15 @@ static Suppression *GetSuppressionForAddr(uptr addr) {
return s;
}
static Suppression *GetSuppressionForStack(u32 stack_trace_id) {
Suppression *LeakSuppressionContext::GetSuppressionForStack(
u32 stack_trace_id) {
LazyParse();
StackTrace stack = StackDepotGet(stack_trace_id);
for (uptr i = 0; i < stack.size; i++) {
Suppression *s = GetSuppressionForAddr(
StackTrace::GetPreviousInstructionPc(stack.trace[i]));
if (s) return s;
if (s)
return s;
}
return nullptr;
}
@ -790,8 +816,10 @@ void LeakReport::PrintSummary() {
}
void LeakReport::ApplySuppressions() {
LeakSuppressionContext *suppressions = GetSuppressionContext();
for (uptr i = 0; i < leaks_.size(); i++) {
Suppression *s = GetSuppressionForStack(leaks_[i].stack_trace_id);
Suppression *s =
suppressions->GetSuppressionForStack(leaks_[i].stack_trace_id);
if (s) {
s->weight += leaks_[i].total_size;
atomic_store_relaxed(&s->hit_count, atomic_load_relaxed(&s->hit_count) +