1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
#!/usr/bin/env python
# Merge or print the coverage data collected by asan's coverage.
# Input files are sequences of 4-byte integers.
# We need to merge these integers into a set and then
# either print them (as hex) or dump them into another file.
import array
import struct
import sys
import bisect
import os.path
prog_name = "";
def Usage():
print >> sys.stderr, "Usage: \n" + \
" " + prog_name + " merge file1 [file2 ...] > output\n" \
" " + prog_name + " print file1 [file2 ...]\n" \
" " + prog_name + " unpack file1 [file2 ...]\n" \
" " + prog_name + " rawunpack file1 [file2 ...]\n"
exit(1)
def ReadOneFile(path):
with open(path, mode="rb") as f:
f.seek(0, 2)
size = f.tell()
f.seek(0, 0)
s = set(array.array('I', f.read(size)))
print >>sys.stderr, "%s: read %d PCs from %s" % (prog_name, size / 4, path)
return s
def Merge(files):
s = set()
for f in files:
s = s.union(ReadOneFile(f))
print >> sys.stderr, "%s: %d files merged; %d PCs total" % \
(prog_name, len(files), len(s))
return sorted(s)
def PrintFiles(files):
s = Merge(files)
for i in s:
print "0x%x" % i
def MergeAndPrint(files):
if sys.stdout.isatty():
Usage()
s = Merge(files)
a = array.array('I', s)
a.tofile(sys.stdout)
def UnpackOneFile(path):
with open(path, mode="rb") as f:
print >> sys.stderr, "%s: unpacking %s" % (prog_name, path)
while True:
header = f.read(12)
if not header: return
if len(header) < 12:
break
pid, module_length, blob_size = struct.unpack('iII', header)
module = f.read(module_length)
blob = f.read(blob_size)
assert(len(module) == module_length)
assert(len(blob) == blob_size)
extracted_file = "%s.%d.sancov" % (module, pid)
print >> sys.stderr, "%s: extracting %s" % \
(prog_name, extracted_file)
# The packed file may contain multiple blobs for the same pid/module
# pair. Append to the end of the file instead of overwriting.
with open(extracted_file, 'ab') as f2:
f2.write(blob)
# fail
raise Exception('Error reading file %s' % path)
def Unpack(files):
for f in files:
UnpackOneFile(f)
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)
bits = int(f_map.readline())
for line in f_map:
parts = line.rstrip().split()
mem_map.append((int(parts[0], 16),
int(parts[1], 16),
int(parts[2], 16),
' '.join(parts[3:])))
mem_map.sort(key=lambda m : m[0])
mem_map_keys = [m[0] for m in mem_map]
with open(path, mode="rb") as f:
print >> sys.stderr, "%s: unpacking %s" % (prog_name, path)
f.seek(0, 2)
size = f.tell()
f.seek(0, 0)
if bits == 64:
typecode = 'L'
else:
typecode = 'I'
pcs = array.array(typecode, f.read(size))
mem_map_pcs = [[] for i in range(0, len(mem_map))]
for pc in pcs:
if pc == 0: continue
map_idx = bisect.bisect(mem_map_keys, pc) - 1
(start, end, base, module_path) = mem_map[map_idx]
assert pc >= start
if pc >= end:
print >> sys.stderr, "warning: %s: pc %x outside of any known mapping" % (prog_name, pc)
continue
mem_map_pcs[map_idx].append(pc - base)
for ((start, end, base, module_path), pc_list) in zip(mem_map, mem_map_pcs):
if len(pc_list) == 0: continue
assert path.endswith('.sancov.raw')
dst_path = module_path + '.' + os.path.basename(path)[:-4]
print >> sys.stderr, "%s: writing %d PCs to %s" % (prog_name, len(pc_list), dst_path)
arr = array.array('I')
arr.fromlist(sorted(pc_list))
with open(dst_path, 'ab') as f2:
arr.tofile(f2)
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)
if __name__ == '__main__':
prog_name = sys.argv[0]
if len(sys.argv) <= 2:
Usage();
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()
|