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