xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/fuzzer/scripts/unbalanced_allocs.py (revision a7c257b03e4462df2b1020128fb82716512d7856)
1#!/usr/bin/env python
2#===- lib/fuzzer/scripts/unbalanced_allocs.py ------------------------------===#
3#
4#                     The LLVM Compiler Infrastructure
5#
6# This file is distributed under the University of Illinois Open Source
7# License. See LICENSE.TXT for details.
8#
9#===------------------------------------------------------------------------===#
10#
11# Post-process -trace_malloc=2 output and printout only allocations and frees
12# unbalanced inside of fuzzer runs.
13# Usage:
14#   my_fuzzer -trace_malloc=2 -runs=10 2>&1 | unbalanced_allocs.py -skip=5
15#
16#===------------------------------------------------------------------------===#
17
18import argparse
19import sys
20
21_skip = 0
22
23def PrintStack(line, stack):
24  global _skip
25  if _skip > 0:
26    return
27  print('Unbalanced ' + line.rstrip());
28  for l in stack:
29    print(l.rstrip())
30
31def ProcessStack(line, f):
32  stack = []
33  while line and line.startswith('    #'):
34    stack += [line]
35    line = f.readline()
36  return line, stack
37
38def ProcessFree(line, f, allocs):
39  if not line.startswith('FREE['):
40    return f.readline()
41
42  addr = int(line.split()[1], 16)
43  next_line, stack = ProcessStack(f.readline(), f)
44  if addr in allocs:
45    del allocs[addr]
46  else:
47    PrintStack(line, stack)
48  return next_line
49
50def ProcessMalloc(line, f, allocs):
51  if not line.startswith('MALLOC['):
52    return ProcessFree(line, f, allocs)
53
54  addr = int(line.split()[1], 16)
55  assert not addr in allocs
56
57  next_line, stack = ProcessStack(f.readline(), f)
58  allocs[addr] = (line, stack)
59  return next_line
60
61def ProcessRun(line, f):
62  if not line.startswith('MallocFreeTracer: START'):
63    return ProcessMalloc(line, f, {})
64
65  allocs = {}
66  print(line.rstrip())
67  line = f.readline()
68  while line:
69    if line.startswith('MallocFreeTracer: STOP'):
70      global _skip
71      _skip = _skip - 1
72      for _, (l, s) in allocs.items():
73        PrintStack(l, s)
74      print(line.rstrip())
75      return f.readline()
76    line = ProcessMalloc(line, f, allocs)
77  return line
78
79def ProcessFile(f):
80  line = f.readline()
81  while line:
82    line = ProcessRun(line, f);
83
84def main(argv):
85  parser = argparse.ArgumentParser()
86  parser.add_argument('--skip', default=0, help='number of runs to ignore')
87  args = parser.parse_args()
88  global _skip
89  _skip = int(args.skip) + 1
90  ProcessFile(sys.stdin)
91
92if __name__ == '__main__':
93  main(sys.argv)
94