[compiler-rt] r232573 - [sanitizer] add run-time a flag coverage_order_pcs. When true, the PCs are dumped in the order of their appearance

Kostya Serebryany kcc at google.com
Tue Mar 17 17:23:45 PDT 2015


Author: kcc
Date: Tue Mar 17 19:23:44 2015
New Revision: 232573

URL: http://llvm.org/viewvc/llvm-project?rev=232573&view=rev
Log:
[sanitizer] add run-time a flag coverage_order_pcs. When true, the PCs are dumped in the order of their appearance

Added:
    compiler-rt/trunk/test/asan/TestCases/Linux/coverage-order-pcs.cc
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_flags.inc
    compiler-rt/trunk/lib/sanitizer_common/scripts/sancov.py

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=232573&r1=232572&r2=232573&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common.h Tue Mar 17 19:23:44 2015
@@ -445,6 +445,9 @@ class InternalMmapVectorNoCtor {
   const T *data() const {
     return data_;
   }
+  T *data() {
+    return data_;
+  }
   uptr capacity() const {
     return 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=232573&r1=232572&r2=232573&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc Tue Mar 17 19:23:44 2015
@@ -352,6 +352,32 @@ void CoverageData::InitializeGuards(s32
   UpdateModuleNameVec(caller_pc, range_beg, range_end);
 }
 
+static const uptr kBundleCounterBits = 16;
+
+// When coverage_order_pcs==true and SANITIZER_WORDSIZE==64
+// we insert the global counter into the first 16 bits of the PC.
+uptr BundlePcAndCounter(uptr pc, uptr counter) {
+  if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs)
+    return pc;
+  static const uptr kMaxCounter = (1 << kBundleCounterBits) - 1;
+  if (counter > kMaxCounter)
+    counter = kMaxCounter;
+  CHECK_EQ(0, pc >> (SANITIZER_WORDSIZE - kBundleCounterBits));
+  return pc | (counter << (SANITIZER_WORDSIZE - kBundleCounterBits));
+}
+
+uptr UnbundlePc(uptr bundle) {
+  if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs)
+    return bundle;
+  return (bundle << kBundleCounterBits) >> kBundleCounterBits;
+}
+
+uptr UnbundleCounter(uptr bundle) {
+  if (SANITIZER_WORDSIZE != 64 || !common_flags()->coverage_order_pcs)
+    return 0;
+  return bundle >> (SANITIZER_WORDSIZE - kBundleCounterBits);
+}
+
 // If guard is negative, atomically set it to -guard and store the PC in
 // pc_array.
 void CoverageData::Add(uptr pc, u32 *guard) {
@@ -367,8 +393,8 @@ void CoverageData::Add(uptr pc, u32 *gua
     return;  // May happen after fork when pc_array_index becomes 0.
   CHECK_LT(idx * sizeof(uptr),
            atomic_load(&pc_array_size, memory_order_acquire));
-  pc_array[idx] = pc;
-  atomic_fetch_add(&coverage_counter, 1, memory_order_relaxed);
+  uptr counter = atomic_fetch_add(&coverage_counter, 1, memory_order_relaxed);
+  pc_array[idx] = BundlePcAndCounter(pc, counter);
 }
 
 // Registers a pair caller=>callee.
@@ -555,7 +581,7 @@ void CoverageData::DumpTrace() {
   for (uptr i = 0, n = size(); i < n; i++) {
     const char *module_name = "<unknown>";
     uptr module_address = 0;
-    sym->GetModuleNameAndOffsetForPC(pc_array[i], &module_name,
+    sym->GetModuleNameAndOffsetForPC(UnbundlePc(pc_array[i]), &module_name,
                                      &module_address);
     out.append("%s 0x%zx\n", module_name, module_address);
   }
@@ -681,7 +707,7 @@ void CoverageData::DumpAsBitSet() {
     CHECK_LE(r.beg, r.end);
     CHECK_LE(r.end, size());
     for (uptr i = r.beg; i < r.end; i++) {
-      uptr pc = data()[i];
+      uptr pc = UnbundlePc(pc_array[i]);
       out[i] = pc ? '1' : '0';
       if (pc)
         n_set_bits++;
@@ -711,12 +737,18 @@ void CoverageData::DumpOffsets() {
     CHECK_LE(r.end, size());
     const char *module_name = "<unknown>";
     for (uptr i = r.beg; i < r.end; i++) {
-      uptr pc = data()[i];
+      uptr pc = UnbundlePc(pc_array[i]);
+      uptr counter = UnbundleCounter(pc_array[i]);
       if (!pc) continue; // Not visited.
       uptr offset = 0;
       sym->GetModuleNameAndOffsetForPC(pc, &module_name, &offset);
-      offsets.push_back(offset);
+      offsets.push_back(BundlePcAndCounter(offset, counter));
     }
+
+    SortArray(offsets.data(), offsets.size());
+    for (uptr i = 0; i < offsets.size(); i++)
+      offsets[i] = UnbundlePc(offsets[i]);
+
     module_name = StripModuleName(r.name);
     if (cov_sandboxed) {
       if (cov_fd >= 0) {

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc?rev=232573&r1=232572&r2=232573&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc Tue Mar 17 19:23:44 2015
@@ -111,10 +111,12 @@ COMMON_FLAG(
     bool, coverage, false,
     "If set, coverage information will be dumped at program shutdown (if the "
     "coverage instrumentation was enabled at compile time).")
-// On by default, but works only if coverage == true.
 COMMON_FLAG(bool, coverage_pcs, true,
             "If set (and if 'coverage' is set too), the coverage information "
             "will be dumped as a set of PC offsets for every module.")
+COMMON_FLAG(bool, coverage_order_pcs, false,
+             "If true, the PCs will be dumped in the order they've"
+             " appeared during the execution.")
 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.")

Modified: compiler-rt/trunk/lib/sanitizer_common/scripts/sancov.py
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/scripts/sancov.py?rev=232573&r1=232572&r2=232573&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/scripts/sancov.py (original)
+++ compiler-rt/trunk/lib/sanitizer_common/scripts/sancov.py Tue Mar 17 19:23:44 2015
@@ -30,20 +30,23 @@ def ReadOneFile(path, bits):
     f.seek(0, 2)
     size = f.tell()
     f.seek(0, 0)
-    s = set(array.array(TypeCodeForBits(bits), f.read(size)))
+    s = array.array(TypeCodeForBits(bits), f.read(size))
   print >>sys.stderr, "%s: read %d PCs from %s" % (prog_name, size * 8 / bits, path)
   return s
 
 def Merge(files, bits):
   s = set()
   for f in files:
-    s = s.union(ReadOneFile(f, bits))
+    s = s.union(set(ReadOneFile(f, bits)))
   print >> sys.stderr, "%s: %d files merged; %d PCs total" % \
     (prog_name, len(files), len(s))
   return sorted(s)
 
 def PrintFiles(files, bits):
-  s = Merge(files, bits)
+  if len(files) > 1:
+    s = Merge(files, bits)
+  else:  # If there is just on file, print the PCs in order.
+    s = ReadOneFile(files[0], bits)
   for i in s:
     print "0x%x" % i
 

Added: compiler-rt/trunk/test/asan/TestCases/Linux/coverage-order-pcs.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/coverage-order-pcs.cc?rev=232573&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/coverage-order-pcs.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/coverage-order-pcs.cc Tue Mar 17 19:23:44 2015
@@ -0,0 +1,56 @@
+// Test coverage_order_pcs=1 flag which orders the PCs by their appearance.
+// RUN: DIR=%T/coverage-order-pcs
+// RUN: rm -rf $DIR
+// RUN: mkdir $DIR
+// RUN: %clangxx_asan -fsanitize-coverage=1 %s -o %t
+// RUN: ASAN_OPTIONS=coverage_dir=$DIR:coverage=1:coverage_order_pcs=0 %t
+// RUN: mv $DIR/*sancov $DIR/A
+
+// RUN: ASAN_OPTIONS=coverage_dir=$DIR:coverage=1:coverage_order_pcs=0 %t 1
+// RUN: mv $DIR/*sancov $DIR/B
+
+// RUN: ASAN_OPTIONS=coverage_dir=$DIR:coverage=1:coverage_order_pcs=1 %t
+// RUN: mv $DIR/*sancov $DIR/C
+
+// RUN: ASAN_OPTIONS=coverage_dir=$DIR:coverage=1:coverage_order_pcs=1 %t 1
+// RUN: mv $DIR/*sancov $DIR/D
+//
+// RUN: (%sancov print $DIR/A; %sancov print $DIR/B; %sancov print $DIR/C; %sancov print $DIR/D) | FileCheck %s
+//
+// RUN: rm -rf $DIR
+// Ordering works only in 64-bit mode for now.
+// REQUIRES: asan-64-bits
+#include <stdio.h>
+
+void foo() { fprintf(stderr, "FOO\n"); }
+void bar() { fprintf(stderr, "BAR\n"); }
+
+int main(int argc, char **argv) {
+  if (argc == 2) {
+    foo();
+    bar();
+  } else {
+    bar();
+    foo();
+  }
+}
+
+// Run A: no ordering
+// CHECK: [[FOO:0x[0-9a-f]*]]
+// CHECK-NEXT: [[BAR:0x[0-9a-f]*]]
+// CHECK-NEXT: [[MAIN:0x[0-9a-f]*]]
+//
+// Run B: still no ordering
+// CHECK-NEXT: [[FOO]]
+// CHECK-NEXT: [[BAR]]
+// CHECK-NEXT: [[MAIN]]
+//
+// Run C: MAIN, BAR, FOO
+// CHECK-NEXT: [[MAIN]]
+// CHECK-NEXT: [[BAR]]
+// CHECK-NEXT: [[FOO]]
+//
+// Run D: MAIN, FOO, BAR
+// CHECK-NEXT: [[MAIN]]
+// CHECK-NEXT: [[FOO]]
+// CHECK-NEXT: [[BAR]]





More information about the llvm-commits mailing list