[compiler-rt] r231413 - [sanitizer] Reconstruct the function that dumps block/edge coverage, hopefully making it more robust. Also increase the allowed coverage size on 32-bit.

Kostya Serebryany kcc at google.com
Thu Mar 5 14:19:25 PST 2015


Author: kcc
Date: Thu Mar  5 16:19:25 2015
New Revision: 231413

URL: http://llvm.org/viewvc/llvm-project?rev=231413&view=rev
Log:
[sanitizer] Reconstruct the function that dumps block/edge coverage, hopefully making it more robust. Also increase the allowed coverage size on 32-bit.

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
    compiler-rt/trunk/test/asan/TestCases/Linux/coverage-module-unloaded.cc
    compiler-rt/trunk/test/asan/TestCases/Linux/coverage-sandboxing.cc
    compiler-rt/trunk/test/asan/TestCases/Linux/coverage.cc

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=231413&r1=231412&r2=231413&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc Thu Mar  5 16:19:25 2015
@@ -79,6 +79,8 @@ class CoverageData {
   void DumpTrace();
   void DumpAsBitSet();
   void DumpCounters();
+  void DumpOffsets();
+  void DumpAll();
 
   ALWAYS_INLINE
   void TraceBasicBlock(s32 *id);
@@ -98,7 +100,7 @@ class CoverageData {
  private:
   // Maximal size pc array may ever grow.
   // We MmapNoReserve this space to ensure that the array is contiguous.
-  static const uptr kPcArrayMaxSize = FIRST_32_SECOND_64(1 << 24, 1 << 27);
+  static const uptr kPcArrayMaxSize = FIRST_32_SECOND_64(1 << 26, 1 << 27);
   // The amount file mapping for the pc array is grown by.
   static const uptr kPcArrayMmapSize = 64 * 1024;
 
@@ -520,23 +522,23 @@ static void CovWritePacked(int pid, cons
 // If packed = true and name == 0: <pid>.<sancov>.<packed>.
 // If packed = true and name != 0: <name>.<sancov>.<packed> (name is
 // user-supplied).
-static int CovOpenFile(bool packed, const char *name,
-                       const char *extension = "sancov") {
-  InternalScopedString path(kMaxPathLength);
+static int CovOpenFile(InternalScopedString *path, bool packed,
+                       const char *name, const char *extension = "sancov") {
+  path->clear();
   if (!packed) {
     CHECK(name);
-    path.append("%s/%s.%zd.%s", coverage_dir, name, internal_getpid(),
+    path->append("%s/%s.%zd.%s", coverage_dir, name, internal_getpid(),
                 extension);
   } else {
     if (!name)
-      path.append("%s/%zd.%s.packed", coverage_dir, internal_getpid(),
+      path->append("%s/%zd.%s.packed", coverage_dir, internal_getpid(),
                   extension);
     else
-      path.append("%s/%s.%s.packed", coverage_dir, name, extension);
+      path->append("%s/%s.%s.packed", coverage_dir, name, extension);
   }
-  uptr fd = OpenFile(path.data(), true);
+  uptr fd = OpenFile(path->data(), true);
   if (internal_iserror(fd)) {
-    Report(" SanitizerCoverage: failed to open %s for writing\n", path.data());
+    Report(" SanitizerCoverage: failed to open %s for writing\n", path->data());
     return -1;
   }
   return fd;
@@ -557,12 +559,13 @@ void CoverageData::DumpTrace() {
                                      &module_address);
     out.append("%s 0x%zx\n", module_name, module_address);
   }
-  int fd = CovOpenFile(false, "trace-points");
+  InternalScopedString path(kMaxPathLength);
+  int fd = CovOpenFile(&path, false, "trace-points");
   if (fd < 0) return;
   internal_write(fd, out.data(), out.length());
   internal_close(fd);
 
-  fd = CovOpenFile(false, "trace-compunits");
+  fd = CovOpenFile(&path, false, "trace-compunits");
   if (fd < 0) return;
   out.clear();
   for (uptr i = 0; i < comp_unit_name_vec.size(); i++)
@@ -570,7 +573,7 @@ void CoverageData::DumpTrace() {
   internal_write(fd, out.data(), out.length());
   internal_close(fd);
 
-  fd = CovOpenFile(false, "trace-events");
+  fd = CovOpenFile(&path, false, "trace-events");
   if (fd < 0) return;
   uptr bytes_to_write = max_idx * sizeof(tr_event_array[0]);
   u8 *event_bytes = reinterpret_cast<u8*>(tr_event_array);
@@ -621,7 +624,8 @@ void CoverageData::DumpCallerCalleePairs
                  callee_module_address);
     }
   }
-  int fd = CovOpenFile(false, "caller-callee");
+  InternalScopedString path(kMaxPathLength);
+  int fd = CovOpenFile(&path, false, "caller-callee");
   if (fd < 0) return;
   internal_write(fd, out.data(), out.length());
   internal_close(fd);
@@ -647,6 +651,7 @@ void CoverageData::DumpCounters() {
   if (!n) return;
   InternalScopedBuffer<u8> bitset(n);
   coverage_data.Update8bitCounterBitsetAndClearCounters(bitset.data());
+  InternalScopedString path(kMaxPathLength);
 
   for (uptr m = 0; m < module_name_vec.size(); m++) {
     auto r = module_name_vec[m];
@@ -654,7 +659,8 @@ void CoverageData::DumpCounters() {
     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");
+    int fd =
+        CovOpenFile(&path, /* packed */ false, base_name, "counters-sancov");
     if (fd < 0) return;
     internal_write(fd, bitset.data() + r.beg, r.end - r.beg);
     internal_close(fd);
@@ -667,6 +673,7 @@ void CoverageData::DumpAsBitSet() {
   if (!common_flags()->coverage_bitset) return;
   if (!size()) return;
   InternalScopedBuffer<char> out(size());
+  InternalScopedString path(kMaxPathLength);
   for (uptr m = 0; m < module_name_vec.size(); m++) {
     uptr n_set_bits = 0;
     auto r = module_name_vec[m];
@@ -680,7 +687,7 @@ void CoverageData::DumpAsBitSet() {
         n_set_bits++;
     }
     const char *base_name = StripModuleName(r.name);
-    int fd = CovOpenFile(/* packed */ false, base_name, "bitset-sancov");
+    int fd = CovOpenFile(&path, /* packed */ false, base_name, "bitset-sancov");
     if (fd < 0) return;
     internal_write(fd, out.data() + r.beg, r.end - r.beg);
     internal_close(fd);
@@ -690,67 +697,58 @@ void CoverageData::DumpAsBitSet() {
   }
 }
 
-// Dump the coverage on disk.
-static void CovDump() {
-  if (!coverage_enabled || common_flags()->coverage_direct) return;
-#if !SANITIZER_WINDOWS
-  if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed))
-    return;
-  coverage_data.DumpAsBitSet();
-  coverage_data.DumpCounters();
-  coverage_data.DumpTrace();
+void CoverageData::DumpOffsets() {
+  auto sym = Symbolizer::GetOrInit();
   if (!common_flags()->coverage_pcs) return;
-  uptr size = coverage_data.size();
-  InternalMmapVector<u32> offsets(size);
-  uptr *vb = coverage_data.data();
-  uptr *ve = vb + size;
-  SortArray(vb, size);
-  MemoryMappingLayout proc_maps(/*cache_enabled*/true);
-  uptr mb, me, off, prot;
-  InternalScopedString module(kMaxPathLength);
+  CHECK_NE(sym, nullptr);
+  InternalMmapVector<u32> offsets(0);
   InternalScopedString path(kMaxPathLength);
-  for (int i = 0;
-       proc_maps.Next(&mb, &me, &off, module.data(), module.size(), &prot);
-       i++) {
-    if ((prot & MemoryMappingLayout::kProtectionExecute) == 0)
-      continue;
-    while (vb < ve && *vb < mb) vb++;
-    if (vb >= ve) break;
-    if (*vb < me) {
-      offsets.clear();
-      const uptr *old_vb = vb;
-      CHECK_LE(off, *vb);
-      for (; vb < ve && *vb < me; vb++) {
-        uptr diff = *vb - (i ? mb : 0) + off;
-        CHECK_LE(diff, 0xffffffffU);
-        offsets.push_back(static_cast<u32>(diff));
-      }
-      const char *module_name = StripModuleName(module.data());
-      if (cov_sandboxed) {
-        if (cov_fd >= 0) {
-          CovWritePacked(internal_getpid(), module_name, offsets.data(),
-                         offsets.size() * sizeof(u32));
-          VReport(1, " CovDump: %zd PCs written to packed file\n", vb - old_vb);
-        }
-      } else {
-        // One file per module per process.
-        path.clear();
-        path.append("%s/%s.%zd.sancov", coverage_dir, module_name,
-                    internal_getpid());
-        int fd = CovOpenFile(false /* packed */, module_name);
-        if (fd > 0) {
-          internal_write(fd, offsets.data(), offsets.size() * sizeof(u32));
-          internal_close(fd);
-          VReport(1, " CovDump: %s: %zd PCs written\n", path.data(),
-                  vb - old_vb);
-        }
+  for (uptr m = 0; m < module_name_vec.size(); m++) {
+    offsets.clear();
+    auto r = module_name_vec[m];
+    CHECK(r.name);
+    CHECK_LE(r.beg, r.end);
+    CHECK_LE(r.end, size());
+    const char *module_name = "<unknown>";
+    for (uptr i = r.beg; i < r.end; i++) {
+      uptr pc = data()[i];
+      if (!pc) continue; // Not visited.
+      uptr offset = 0;
+      sym->GetModuleNameAndOffsetForPC(pc, &module_name, &offset);
+      if (!offset || offset > 0xffffffffU) continue;
+      offsets.push_back(static_cast<u32>(offset));
+    }
+    module_name = StripModuleName(r.name);
+    if (cov_sandboxed) {
+      if (cov_fd >= 0) {
+        CovWritePacked(internal_getpid(), module_name, offsets.data(),
+                       offsets.size() * sizeof(u32));
+        VReport(1, " CovDump: %zd PCs written to packed file\n",
+                offsets.size());
       }
+    } else {
+      // One file per module per process.
+      int fd = CovOpenFile(&path, false /* packed */, module_name);
+      if (fd < 0) continue;
+      internal_write(fd, offsets.data(), offsets.size() * sizeof(u32));
+      internal_close(fd);
+      VReport(1, " CovDump: %s: %zd PCs written\n", path.data(),
+              offsets.size());
     }
   }
   if (cov_fd >= 0)
     internal_close(cov_fd);
-  coverage_data.DumpCallerCalleePairs();
-#endif  // !SANITIZER_WINDOWS
+}
+
+void CoverageData::DumpAll() {
+  if (!coverage_enabled || common_flags()->coverage_direct) return;
+  if (atomic_fetch_add(&dump_once_guard, 1, memory_order_relaxed))
+    return;
+  DumpAsBitSet();
+  DumpCounters();
+  DumpTrace();
+  DumpOffsets();
+  DumpCallerCalleePairs();
 }
 
 void CovPrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
@@ -760,15 +758,18 @@ void CovPrepareForSandboxing(__sanitizer
   if (!cov_sandboxed) return;
   cov_fd = args->coverage_fd;
   cov_max_block_size = args->coverage_max_block_size;
-  if (cov_fd < 0)
+  if (cov_fd < 0) {
+    InternalScopedString path(kMaxPathLength);
     // Pre-open the file now. The sandbox won't allow us to do it later.
-    cov_fd = CovOpenFile(true /* packed */, 0);
+    cov_fd = CovOpenFile(&path, true /* packed */, 0);
+  }
 }
 
 int MaybeOpenCovFile(const char *name) {
   CHECK(name);
   if (!coverage_enabled) return -1;
-  return CovOpenFile(true /* packed */, name);
+  InternalScopedString path(kMaxPathLength);
+  return CovOpenFile(&path, true /* packed */, name);
 }
 
 void CovBeforeFork() {
@@ -824,7 +825,9 @@ SANITIZER_INTERFACE_ATTRIBUTE void __san
   coverage_dir = common_flags()->coverage_dir;
   coverage_data.Init();
 }
-SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() { CovDump(); }
+SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_cov_dump() {
+  coverage_data.DumpAll();
+}
 SANITIZER_INTERFACE_ATTRIBUTE void
 __sanitizer_cov_module_init(s32 *guards, uptr npcs, u8 *counters,
                             const char *comp_unit_name) {

Modified: compiler-rt/trunk/test/asan/TestCases/Linux/coverage-module-unloaded.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/coverage-module-unloaded.cc?rev=231413&r1=231412&r2=231413&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/coverage-module-unloaded.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/coverage-module-unloaded.cc Thu Mar  5 16:19:25 2015
@@ -50,7 +50,7 @@ int main(int argc, char **argv) {
 
 // CHECK: PID: [[PID:[0-9]+]]
 // CHECK: [[PID]].sancov: 1 PCs written
-// CHECK: .so.[[PID]]
-// If we get coverage for both DSOs, it means the module wasn't unloaded and
-// this test is useless.
-// CHECK-NOT: .so.[[PID]]
+// CHECK: test_1.so.[[PID]]
+// CHECK: test_2.so.[[PID]]
+// Even though we've unloaded one of the libs we still dump the coverage file
+// for that lib (although the data will be inaccurate, it at all useful)

Modified: compiler-rt/trunk/test/asan/TestCases/Linux/coverage-sandboxing.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/coverage-sandboxing.cc?rev=231413&r1=231412&r2=231413&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/coverage-sandboxing.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/coverage-sandboxing.cc Thu Mar  5 16:19:25 2015
@@ -78,8 +78,8 @@ int main(int argc, char **argv) {
 #endif
 
 // CHECK-vanilla: PID: [[PID:[0-9]+]]
-// CHECK-vanilla: [[PID]].sancov: 1 PCs written
 // CHECK-vanilla: .so.[[PID]].sancov: 258 PCs written
+// CHECK-vanilla: [[PID]].sancov: 1 PCs written
 
 // CHECK-sandbox: PID: [[PID:[0-9]+]]
 // CHECK-sandbox: 258 PCs written to packed file

Modified: compiler-rt/trunk/test/asan/TestCases/Linux/coverage.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/coverage.cc?rev=231413&r1=231412&r2=231413&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/coverage.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/coverage.cc Thu Mar  5 16:19:25 2015
@@ -57,12 +57,12 @@ int main(int argc, char **argv) {
 // CHECK-foo-NOT: .so.[[PID]]
 //
 // CHECK-bar: PID: [[PID:[0-9]+]]
-// CHECK-bar: [[PID]].sancov: 1 PCs written
 // CHECK-bar: .so.[[PID]].sancov: 1 PCs written
+// CHECK-bar: [[PID]].sancov: 1 PCs written
 //
 // CHECK-foo-bar: PID: [[PID:[0-9]+]]
-// CHECK-foo-bar: [[PID]].sancov: 2 PCs written
 // CHECK-foo-bar: so.[[PID]].sancov: 1 PCs written
+// CHECK-foo-bar: [[PID]].sancov: 2 PCs written
 //
 // CHECK-report: AddressSanitizer: global-buffer-overflow
 // CHECK-report: PCs written





More information about the llvm-commits mailing list