[compiler-rt] r232679 - [sanitizer] change the sanitizer coverage format once again, this time adding a magic to the beginning of the file

Kostya Serebryany kcc at google.com
Wed Mar 18 15:03:39 PDT 2015


Author: kcc
Date: Wed Mar 18 17:03:39 2015
New Revision: 232679

URL: http://llvm.org/viewvc/llvm-project?rev=232679&view=rev
Log:
[sanitizer] change the sanitizer coverage format once again, this time adding a magic to the beginning of the file

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_libcdep.cc
    compiler-rt/trunk/lib/sanitizer_common/scripts/sancov.py
    compiler-rt/trunk/test/asan/lit.cfg

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=232679&r1=232678&r2=232679&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 18 17:03:39 2015
@@ -24,8 +24,12 @@
 //    and atomically set Guard to -Guard.
 //  - __sanitizer_cov_dump: dump the coverage data to disk.
 //  For every module of the current process that has coverage data
-//  this will create a file module_name.PID.sancov. The file format is simple:
-//  it's just a sorted sequence of 4-byte offsets in the module.
+//  this will create a file module_name.PID.sancov.
+//
+// The file format is simple: the first 8 bytes is the magic,
+// one of 0xC0BFFFFFFFFFFF64 and 0xC0BFFFFFFFFFFF32. The last byte of the
+// magic defines the size of the following offsets.
+// The rest of the data is the offsets in the module.
 //
 // Eventually, this coverage implementation should be obsoleted by a more
 // powerful general purpose Clang/LLVM coverage instrumentation.
@@ -43,6 +47,9 @@
 #include "sanitizer_symbolizer.h"
 #include "sanitizer_flags.h"
 
+static const u64 kMagic64 = 0xC0BFFFFFFFFFFF64ULL;
+static const u64 kMagic32 = 0xC0BFFFFFFFFFFF32ULL;
+
 static atomic_uint32_t dump_once_guard;  // Ensure that CovDump runs only once.
 
 static atomic_uintptr_t coverage_counter;
@@ -731,6 +738,9 @@ void CoverageData::DumpOffsets() {
   InternalScopedString path(kMaxPathLength);
   for (uptr m = 0; m < module_name_vec.size(); m++) {
     offsets.clear();
+    uptr num_words_for_magic = SANITIZER_WORDSIZE == 64 ? 1 : 2;
+    for (uptr i = 0; i < num_words_for_magic; i++)
+      offsets.push_back(0);
     auto r = module_name_vec[m];
     CHECK(r.name);
     CHECK_LE(r.beg, r.end);
@@ -745,17 +755,24 @@ void CoverageData::DumpOffsets() {
       offsets.push_back(BundlePcAndCounter(offset, counter));
     }
 
+    CHECK_GE(offsets.size(), num_words_for_magic);
     SortArray(offsets.data(), offsets.size());
     for (uptr i = 0; i < offsets.size(); i++)
       offsets[i] = UnbundlePc(offsets[i]);
 
+    uptr num_offsets = offsets.size() - num_words_for_magic;
+    u64 *magic_p = reinterpret_cast<u64*>(offsets.data());
+    CHECK_EQ(*magic_p, 0ULL);
+    // FIXME: we may want to write 32-bit offsets even in 64-mode
+    // if all the offsets are small enough.
+    *magic_p = SANITIZER_WORDSIZE == 64 ? kMagic64 : kMagic32;
+
     module_name = StripModuleName(r.name);
     if (cov_sandboxed) {
       if (cov_fd >= 0) {
         CovWritePacked(internal_getpid(), module_name, offsets.data(),
                        offsets.size() * sizeof(offsets[0]));
-        VReport(1, " CovDump: %zd PCs written to packed file\n",
-                offsets.size());
+        VReport(1, " CovDump: %zd PCs written to packed file\n", num_offsets);
       }
     } else {
       // One file per module per process.
@@ -763,8 +780,7 @@ void CoverageData::DumpOffsets() {
       if (fd < 0) continue;
       internal_write(fd, offsets.data(), offsets.size() * sizeof(offsets[0]));
       internal_close(fd);
-      VReport(1, " CovDump: %s: %zd PCs written\n", path.data(),
-              offsets.size());
+      VReport(1, " CovDump: %s: %zd PCs written\n", path.data(), num_offsets);
     }
   }
   if (cov_fd >= 0)

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=232679&r1=232678&r2=232679&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/scripts/sancov.py (original)
+++ compiler-rt/trunk/lib/sanitizer_common/scripts/sancov.py Wed Mar 18 17:03:39 2015
@@ -9,7 +9,7 @@ import sys
 import bisect
 import os.path
 
-prog_name = "";
+prog_name = ""
 
 def Usage():
   print >> sys.stderr, "Usage: \n" + \
@@ -19,41 +19,65 @@ def Usage():
       " " + prog_name + " [32|64] rawunpack file1 [file2 ...]\n"
   exit(1)
 
+def CheckBits(bits):
+  if bits != 32 and bits != 64:
+    raise Exception("Wrond bitness: %d" % bits)
+
 def TypeCodeForBits(bits):
-  if bits == 64:
-    return 'L'
-  else:
-    return 'I'
+  CheckBits(bits)
+  return 'L' if bits == 64 else 'I'
+
+kMagic64 = 0xC0BFFFFFFFFFFF64
+kMagic32 = 0xC0BFFFFFFFFFFF32
 
-def ReadOneFile(path, bits):
+def MagicForBits(bits):
+  CheckBits(bits)
+  return kMagic64 if bits == 64 else kMagic32
+
+def ReadOneFile(path):
   with open(path, mode="rb") as f:
     f.seek(0, 2)
     size = f.tell()
     f.seek(0, 0)
+    if size <= 8:
+      raise Exception('File %s is short (> 8 bytes)' % path)
+    magic_word = struct.unpack('L', f.read(8))[0];
+    if magic_word == kMagic64:
+      bits = 64
+    elif magic_word == kMagic32:
+      bits = 32
+    else:
+      raise Exception('Bad magic word in %s' % path)
+    size -= 8
     s = array.array(TypeCodeForBits(bits), f.read(size))
-  print >>sys.stderr, "%s: read %d PCs from %s" % (prog_name, size * 8 / bits, path)
+  print >>sys.stderr, "%s: read %d %d-bit PCs from %s" % (prog_name, size * 8 / bits, bits, path)
   return s
 
-def Merge(files, bits):
+def Merge(files):
   s = set()
   for f in files:
-    s = s.union(set(ReadOneFile(f, bits)))
+    s = s.union(set(ReadOneFile(f)))
   print >> sys.stderr, "%s: %d files merged; %d PCs total" % \
     (prog_name, len(files), len(s))
   return sorted(s)
 
-def PrintFiles(files, bits):
+def PrintFiles(files):
   if len(files) > 1:
-    s = Merge(files, bits)
+    s = Merge(files)
   else:  # If there is just on file, print the PCs in order.
-    s = ReadOneFile(files[0], bits)
+    s = ReadOneFile(files[0])
   for i in s:
     print "0x%x" % i
 
-def MergeAndPrint(files, bits):
+def MergeAndPrint(files):
   if sys.stdout.isatty():
     Usage()
-  s = Merge(files, bits)
+  s = Merge(files)
+  bits = 32
+  magic = kMagic32
+  if max(s) > 0xFFFFFFFF:
+    bits = 64
+    magic = kMagic64
   a = array.array(TypeCodeForBits(bits), s)
   a.tofile(sys.stdout)
 
@@ -86,11 +110,12 @@ def Unpack(files):
   for f in files:
     UnpackOneFile(f)
 
-def UnpackOneRawFile(path, map_path, bits):
+def UnpackOneRawFile(path, map_path):
   mem_map = []
   with open(map_path, mode="rt") as f_map:
     print >> sys.stderr, "%s: reading map %s" % (prog_name, map_path)
-    if bits != int(f_map.readline()):
+    bits = int(f_map.readline())
+    if bits != 32 and bits != 64:
       raise Exception('Wrong bits size in the map')
     for line in f_map:
       parts = line.rstrip().split()
@@ -128,34 +153,28 @@ def UnpackOneRawFile(path, map_path, bit
       arr = array.array(TypeCodeForBits(bits))
       arr.fromlist(sorted(pc_list))
       with open(dst_path, 'ab') as f2:
+        array.array('L', [MagicForBits(bits)]).tofile(f2)
         arr.tofile(f2)
 
-def RawUnpack(files, bits):
+def RawUnpack(files):
   for f in files:
     if not f.endswith('.sancov.raw'):
       raise Exception('Unexpected raw file name %s' % f)
     f_map = f[:-3] + 'map'
-    UnpackOneRawFile(f, f_map, bits)
+    UnpackOneRawFile(f, f_map)
 
 if __name__ == '__main__':
   prog_name = sys.argv[0]
-  if len(sys.argv) <= 3:
-    Usage();
-
-  if sys.argv[1] == "32":
-    bits = 32
-  elif sys.argv[1] == "64":
-    bits = 64
-  else:
+  if len(sys.argv) <= 2:
     Usage();
 
-  if sys.argv[2] == "print":
-    PrintFiles(sys.argv[3:], bits)
-  elif sys.argv[2] == "merge":
-    MergeAndPrint(sys.argv[3:], bits)
-  elif sys.argv[2] == "unpack":
-    Unpack(sys.argv[3:])
-  elif sys.argv[2] == "rawunpack":
-    RawUnpack(sys.argv[3:], bits)
+  if sys.argv[1] == "print":
+    PrintFiles(sys.argv[2:])
+  elif sys.argv[1] == "merge":
+    MergeAndPrint(sys.argv[2:])
+  elif sys.argv[1] == "unpack":
+    Unpack(sys.argv[2:])
+  elif sys.argv[1] == "rawunpack":
+    RawUnpack(sys.argv[2:])
   else:
     Usage()

Modified: compiler-rt/trunk/test/asan/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/lit.cfg?rev=232679&r1=232678&r2=232679&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/lit.cfg (original)
+++ compiler-rt/trunk/test/asan/lit.cfg Wed Mar 18 17:03:39 2015
@@ -121,7 +121,7 @@ sancov = os.path.join(sanitizer_common_s
 if not os.path.exists(sancov):
   lit_config.fatal("Can't find script on path %r" % sancov)
 python_exec = get_required_attr(config, "python_executable")
-config.substitutions.append( ("%sancov", python_exec + " " + sancov + " " + config.bits + " ") )
+config.substitutions.append( ("%sancov", python_exec + " " + sancov + " ") )
 
 # Determine kernel bitness
 if config.host_arch.find('64') != -1 and config.android != "1":





More information about the llvm-commits mailing list