diff options
3 files changed, 30 insertions, 0 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc index 136a567db6c..39c3df4d50b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc @@ -78,6 +78,7 @@ class CoverageData { void DumpCallerCalleePairs(); void DumpTrace(); void DumpAsBitSet(); + void DumpCounters(); ALWAYS_INLINE void TraceBasicBlock(s32 *id); @@ -640,6 +641,28 @@ void CoverageData::TraceBasicBlock(s32 *id) { tr_event_pointer++; } +void CoverageData::DumpCounters() { + if (!common_flags()->coverage_counters) return; + uptr n = coverage_data.GetNumberOf8bitCounters(); + if (!n) return; + InternalScopedBuffer<u8> bitset(n); + coverage_data.Update8bitCounterBitsetAndClearCounters(bitset.data()); + + for (uptr m = 0; m < module_name_vec.size(); m++) { + auto r = module_name_vec[m]; + CHECK(r.name); + CHECK_LE(r.beg, r.end); + CHECK_LE(r.end, size()); + const char *base_name = StripModuleName(r.name); + int fd = CovOpenFile(/* packed */ false, base_name, "counters-sancov"); + if (fd < 0) return; + internal_write(fd, bitset.data() + r.beg, r.end - r.beg); + internal_close(fd); + VReport(1, " CovDump: %zd counters written for '%s'\n", r.end - r.beg, + base_name); + } +} + void CoverageData::DumpAsBitSet() { if (!common_flags()->coverage_bitset) return; if (!size()) return; @@ -674,6 +697,7 @@ static void CovDump() { if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed)) return; coverage_data.DumpAsBitSet(); + coverage_data.DumpCounters(); coverage_data.DumpTrace(); if (!common_flags()->coverage_pcs) return; uptr size = coverage_data.size(); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc index 58f7f372228..983af072fb8 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc @@ -118,6 +118,9 @@ COMMON_FLAG(bool, coverage_pcs, true, COMMON_FLAG(bool, coverage_bitset, false, "If set (and if 'coverage' is set too), the coverage information " "will also be dumped as a bitset to a separate file.") +COMMON_FLAG(bool, coverage_counters, false, + "If set (and if 'coverage' is set too), the bitmap that corresponds" + " to coverage counters will be dumped.") COMMON_FLAG(bool, coverage_direct, SANITIZER_ANDROID, "If set, coverage information will be dumped directly to a memory " "mapped file. This way data is not lost even if the process is " diff --git a/compiler-rt/test/asan/TestCases/Linux/coverage-levels.cc b/compiler-rt/test/asan/TestCases/Linux/coverage-levels.cc index 6d528e72d59..f84fd0bf6a9 100644 --- a/compiler-rt/test/asan/TestCases/Linux/coverage-levels.cc +++ b/compiler-rt/test/asan/TestCases/Linux/coverage-levels.cc @@ -6,6 +6,8 @@ // RUN: ASAN_OPTIONS=coverage=1:coverage_bitset=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2 // RUN: %clangxx_asan -O1 -fsanitize-coverage=3 %s -o %t // RUN: ASAN_OPTIONS=coverage=1:coverage_bitset=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 +// RUN: %clangxx_asan -O1 -fsanitize-coverage=3 -mllvm -sanitizer-coverage-8bit-counters=1 %s -o %t +// RUN: ASAN_OPTIONS=coverage=1:coverage_counters=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK_COUNTERS // RUN: ASAN_OPTIONS=coverage=1:coverage_bitset=0:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3_NOBITSET // RUN: ASAN_OPTIONS=coverage=1:verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3_NOBITSET @@ -27,3 +29,4 @@ int main(int argc, char **argv) { // CHECK3: 3 PCs written // CHECK3_NOBITSET-NOT: bitset of // CHECK3_NOPCS-NOT: PCs written +// CHECK_COUNTERS: CovDump: 4 counters written for |

