[compiler-rt] r231319 - [sanitizer] when dumping coverage bitset, dump seperate file for every module, instead of dumping a single combined bitset

Kostya Serebryany kcc at google.com
Wed Mar 4 15:41:55 PST 2015


Author: kcc
Date: Wed Mar  4 17:41:55 2015
New Revision: 231319

URL: http://llvm.org/viewvc/llvm-project?rev=231319&view=rev
Log:
[sanitizer] when dumping coverage bitset, dump seperate file for every module, instead of dumping a single combined bitset

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h
    compiler-rt/trunk/test/asan/TestCases/Linux/coverage-levels.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h?rev=231319&r1=231318&r2=231319&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Wed Mar  4 17:41:55 2015
@@ -450,6 +450,7 @@ class InternalMmapVectorNoCtor {
   }
 
   void clear() { size_ = 0; }
+  bool empty() const { return size() == 0; }
 
  private:
   void Resize(uptr new_capacity) {

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc?rev=231319&r1=231318&r2=231319&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc Wed Mar  4 17:41:55 2015
@@ -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
   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 *
   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 __san
 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) {

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h?rev=231319&r1=231318&r2=231319&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h Wed Mar  4 17:41:55 2015
@@ -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;
   }

Modified: compiler-rt/trunk/test/asan/TestCases/Linux/coverage-levels.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/coverage-levels.cc?rev=231319&r1=231318&r2=231319&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/coverage-levels.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/coverage-levels.cc Wed Mar  4 17:41:55 2015
@@ -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





More information about the llvm-commits mailing list