diff options
-rw-r--r-- | compiler-rt/lib/lsan/lsan_common.cc | 25 | ||||
-rw-r--r-- | compiler-rt/lib/lsan/lsan_common.h | 1 |
2 files changed, 22 insertions, 4 deletions
diff --git a/compiler-rt/lib/lsan/lsan_common.cc b/compiler-rt/lib/lsan/lsan_common.cc index e8b6d088886..63ba4dbfda5 100644 --- a/compiler-rt/lib/lsan/lsan_common.cc +++ b/compiler-rt/lib/lsan/lsan_common.cc @@ -267,8 +267,10 @@ void PrintLeakedCb::operator()(void *p) const { } static void PrintLeaked() { - Printf("\nReporting individual blocks:\n"); + Printf("Reporting individual blocks:\n"); + Printf("============================\n"); ForEachChunk(PrintLeakedCb()); + Printf("\n"); } enum LeakCheckResult { @@ -290,9 +292,14 @@ static void DoLeakCheckCallback(const SuspendedThreadsList &suspended_threads, *result = kNoLeaks; return; } + Printf("\n"); + Printf("=================================================================\n"); + Report("ERROR: LeakSanitizer: detected leaks.\n"); leak_report.PrintLargest(flags()->max_leaks); if (flags()->report_blocks) PrintLeaked(); + leak_report.PrintSummary(); + Printf("\n"); ForEachChunk(ClearTagCb()); *result = kLeaksFound; } @@ -387,17 +394,27 @@ void LeakReport::PrintLargest(uptr max_leaks) { InternalSort(&leaks_, leaks_.size(), IsLarger); max_leaks = max_leaks > 0 ? Min(max_leaks, leaks_.size()) : leaks_.size(); for (uptr i = 0; i < max_leaks; i++) { - Printf("\n%s leak of %llu bytes in %llu objects allocated from:\n", + Printf("%s leak of %llu bytes in %llu object%s allocated from:\n", leaks_[i].is_directly_leaked ? "Direct" : "Indirect", - leaks_[i].total_size, leaks_[i].hit_count); + leaks_[i].total_size, leaks_[i].hit_count, + leaks_[i].hit_count == 1 ? "" : "s"); PrintStackTraceById(leaks_[i].stack_trace_id); + Printf("\n"); } if (max_leaks < leaks_.size()) { uptr remaining = leaks_.size() - max_leaks; - Printf("\nOmitting %llu more leak%s.\n", remaining, + Printf("Omitting %llu more leak%s.\n", remaining, remaining > 1 ? "s" : ""); } } +void LeakReport::PrintSummary() { + CHECK(leaks_.size() <= kMaxLeaksConsidered); + uptr bytes_leaked = 0; + for (uptr i = 0; i < leaks_.size(); i++) { + bytes_leaked += leaks_[i].total_size; + } + Printf("SUMMARY: LeakSanitizer: %llu bytes leaked.\n", bytes_leaked); +} } // namespace __lsan #endif // CAN_SANITIZE_LEAKS diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h index be52732bb4e..c02680cc0ea 100644 --- a/compiler-rt/lib/lsan/lsan_common.h +++ b/compiler-rt/lib/lsan/lsan_common.h @@ -98,6 +98,7 @@ class LeakReport { LeakReport() : leaks_(1) {} void Add(u32 stack_trace_id, uptr leaked_size, ChunkTag tag); void PrintLargest(uptr max_leaks); + void PrintSummary(); bool IsEmpty() { return leaks_.size() == 0; } private: InternalVector<Leak> leaks_; |