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