Home | History | Annotate | Line # | Download | only in scripts
      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 
     18 import argparse
     19 import sys
     20 
     21 _skip = 0
     22 
     23 def 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 
     31 def ProcessStack(line, f):
     32   stack = []
     33   while line and line.startswith('    #'):
     34     stack += [line]
     35     line = f.readline()
     36   return line, stack
     37 
     38 def 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 
     50 def 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 
     61 def 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 
     79 def ProcessFile(f):
     80   line = f.readline()
     81   while line:
     82     line = ProcessRun(line, f);
     83 
     84 def 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 
     92 if __name__ == '__main__':
     93   main(sys.argv)
     94