diff options
author | Kostya Serebryany <kcc@google.com> | 2015-03-04 23:41:55 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2015-03-04 23:41:55 +0000 |
commit | 07aee9c2c6261829ff10fb87e5d14711a110bd67 (patch) | |
tree | e29fbaabe801378c899251e5fba342e9f74bebf2 | |
parent | e9c019a7a611cfe2f2b5de8885c9a3f996153604 (diff) | |
download | bcm5719-llvm-07aee9c2c6261829ff10fb87e5d14711a110bd67.tar.gz bcm5719-llvm-07aee9c2c6261829ff10fb87e5d14711a110bd67.zip |
[sanitizer] when dumping coverage bitset, dump seperate file for every module, instead of dumping a single combined bitset
llvm-svn: 231319
4 files changed, 69 insertions, 28 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 0f6f43cab80..1b720aa9cc9 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -450,6 +450,7 @@ class InternalMmapVectorNoCtor { } void clear() { size_ = 0; } + bool empty() const { return size() == 0; } private: void Resize(uptr new_capacity) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc index 7197b4c6ab0..136a567db6c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_libcdep.cc @@ -77,12 +77,15 @@ class CoverageData { uptr cache_size); void DumpCallerCalleePairs(); void DumpTrace(); + void DumpAsBitSet(); ALWAYS_INLINE void TraceBasicBlock(s32 *id); void InitializeGuardArray(s32 *guards); - void InitializeGuards(s32 *guards, uptr n, const char *module_name); + void InitializeGuards(s32 *guards, uptr n, const char *module_name, + uptr caller_pc); + void UpdateModuleNameVec(uptr caller_pc, uptr range_beg, uptr range_end); void InitializeCounters(u8 *counters, uptr n); void ReinitializeGuards(); uptr GetNumberOf8bitCounters(); @@ -113,8 +116,14 @@ class CoverageData { // Vector of coverage guard arrays, protected by mu. InternalMmapVectorNoCtor<s32*> guard_array_vec; - // Vector of module (compilation unit) names. - InternalMmapVectorNoCtor<const char*> comp_unit_name_vec; + struct NamedPcRange { + const char *name; + uptr beg, end; // elements [beg,end) in pc_array. + }; + + // Vector of module and compilation unit pc ranges. + InternalMmapVectorNoCtor<NamedPcRange> comp_unit_name_vec; + InternalMmapVectorNoCtor<NamedPcRange> module_name_vec; struct CounterAndSize { u8 *counters; @@ -311,16 +320,33 @@ void CoverageData::InitializeCounters(u8 *counters, uptr n) { num_8bit_counters += n; } +void CoverageData::UpdateModuleNameVec(uptr caller_pc, uptr range_beg, + uptr range_end) { + auto sym = Symbolizer::GetOrInit(); + if (!sym) + return; + const char *module_name = sym->GetModuleNameForPc(caller_pc); + if (!module_name) return; + if (module_name_vec.empty() || module_name_vec.back().name != module_name) + module_name_vec.push_back({module_name, range_beg, range_end}); + else + module_name_vec.back().end = range_end; +} + void CoverageData::InitializeGuards(s32 *guards, uptr n, - const char *module_name) { + const char *comp_unit_name, + uptr caller_pc) { // The array 'guards' has n+1 elements, we use the element zero // to store 'n'. CHECK_LT(n, 1 << 30); guards[0] = static_cast<s32>(n); InitializeGuardArray(guards); SpinMutexLock l(&mu); - comp_unit_name_vec.push_back(module_name); + uptr range_end = atomic_load(&pc_array_index, memory_order_relaxed); + uptr range_beg = range_end - n; + comp_unit_name_vec.push_back({comp_unit_name, range_beg, range_end}); guard_array_vec.push_back(guards); + UpdateModuleNameVec(caller_pc, range_beg, range_end); } // If guard is negative, atomically set it to -guard and store the PC in @@ -539,7 +565,7 @@ void CoverageData::DumpTrace() { if (fd < 0) return; out.clear(); for (uptr i = 0; i < comp_unit_name_vec.size(); i++) - out.append("%s\n", comp_unit_name_vec[i]); + out.append("%s\n", comp_unit_name_vec[i].name); internal_write(fd, out.data(), out.length()); internal_close(fd); @@ -614,24 +640,31 @@ void CoverageData::TraceBasicBlock(s32 *id) { tr_event_pointer++; } -static void CovDumpAsBitSet() { +void CoverageData::DumpAsBitSet() { if (!common_flags()->coverage_bitset) return; - if (!coverage_data.size()) return; - int fd = CovOpenFile(/* packed */false, "combined", "bitset-sancov"); - if (fd < 0) return; - uptr n = coverage_data.size(); - uptr n_set_bits = 0; - InternalScopedBuffer<char> out(n); - for (uptr i = 0; i < n; i++) { - uptr pc = coverage_data.data()[i]; - out[i] = pc ? '1' : '0'; - if (pc) - n_set_bits++; + if (!size()) return; + InternalScopedBuffer<char> out(size()); + for (uptr m = 0; m < module_name_vec.size(); m++) { + uptr n_set_bits = 0; + auto r = module_name_vec[m]; + CHECK(r.name); + CHECK_LE(r.beg, r.end); + CHECK_LE(r.end, size()); + for (uptr i = r.beg; i < r.end; i++) { + uptr pc = data()[i]; + out[i] = pc ? '1' : '0'; + if (pc) + n_set_bits++; + } + const char *base_name = StripModuleName(r.name); + int fd = CovOpenFile(/* packed */ false, base_name, "bitset-sancov"); + if (fd < 0) return; + internal_write(fd, out.data() + r.beg, r.end - r.beg); + internal_close(fd); + VReport(1, + " CovDump: bitset of %zd bits written for '%s', %zd bits are set\n", + r.end - r.beg, base_name, n_set_bits); } - internal_write(fd, out.data(), n); - internal_close(fd); - VReport(1, " CovDump: bitset of %zd bits written, %zd bits are set\n", n, - n_set_bits); } // Dump the coverage on disk. @@ -640,7 +673,7 @@ static void CovDump() { #if !SANITIZER_WINDOWS if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed)) return; - CovDumpAsBitSet(); + coverage_data.DumpAsBitSet(); coverage_data.DumpTrace(); if (!common_flags()->coverage_pcs) return; uptr size = coverage_data.size(); @@ -770,8 +803,8 @@ SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_init() { SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { CovDump(); } SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_module_init(s32 *guards, uptr npcs, u8 *counters, - const char *module_name) { - coverage_data.InitializeGuards(guards, npcs, module_name); + const char *comp_unit_name) { + coverage_data.InitializeGuards(guards, npcs, comp_unit_name, GET_CALLER_PC()); coverage_data.InitializeCounters(counters, npcs); if (!common_flags()->coverage_direct) return; if (SANITIZER_ANDROID && coverage_enabled) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h index a9942f12573..619c9978b14 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h @@ -90,6 +90,13 @@ class Symbolizer { uptr *module_address) { return false; } + const char *GetModuleNameForPc(uptr pc) { + const char *module_name = 0; + uptr unused; + if (GetModuleNameAndOffsetForPC(pc, &module_name, &unused)) + return module_name; + return nullptr; + } virtual bool CanReturnFileLineInfo() { return false; } diff --git a/compiler-rt/test/asan/TestCases/Linux/coverage-levels.cc b/compiler-rt/test/asan/TestCases/Linux/coverage-levels.cc index cc196c5a9e1..6d528e72d59 100644 --- a/compiler-rt/test/asan/TestCases/Linux/coverage-levels.cc +++ b/compiler-rt/test/asan/TestCases/Linux/coverage-levels.cc @@ -19,11 +19,11 @@ int main(int argc, char **argv) { sink = 0; } -// CHECK1: CovDump: bitset of 1 bits written, 1 bits are set +// CHECK1: CovDump: bitset of 1 bits written for '{{.*}}', 1 bits are set // CHECK1: 1 PCs written -// CHECK2: CovDump: bitset of 3 bits written, 2 bits are set +// CHECK2: CovDump: bitset of 3 bits written for '{{.*}}', 2 bits are set // CHECK2: 2 PCs written -// CHECK3: CovDump: bitset of 4 bits written, 3 bits are set +// CHECK3: CovDump: bitset of 4 bits written for '{{.*}}', 3 bits are set // CHECK3: 3 PCs written // CHECK3_NOBITSET-NOT: bitset of // CHECK3_NOPCS-NOT: PCs written |