forked from OSchip/llvm-project
[sanitizer] change the sanitizer coverage format once again, this time adding a magic to the beginning of the file
llvm-svn: 232679
This commit is contained in:
parent
05fd66d2f8
commit
2d56abacd1
|
@ -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)
|
||||
|
|
|
@ -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 TypeCodeForBits(bits):
|
||||
if bits == 64:
|
||||
return 'L'
|
||||
else:
|
||||
return 'I'
|
||||
def CheckBits(bits):
|
||||
if bits != 32 and bits != 64:
|
||||
raise Exception("Wrond bitness: %d" % bits)
|
||||
|
||||
def ReadOneFile(path, bits):
|
||||
def TypeCodeForBits(bits):
|
||||
CheckBits(bits)
|
||||
return 'L' if bits == 64 else 'I'
|
||||
|
||||
kMagic64 = 0xC0BFFFFFFFFFFF64
|
||||
kMagic32 = 0xC0BFFFFFFFFFFF32
|
||||
|
||||
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, bits):
|
|||
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:
|
||||
if len(sys.argv) <= 2:
|
||||
Usage();
|
||||
|
||||
if sys.argv[1] == "32":
|
||||
bits = 32
|
||||
elif sys.argv[1] == "64":
|
||||
bits = 64
|
||||
else:
|
||||
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()
|
||||
|
|
|
@ -121,7 +121,7 @@ sancov = os.path.join(sanitizer_common_source_dir, "scripts", "sancov.py")
|
|||
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":
|
||||
|
|
Loading…
Reference in New Issue