vitalybuka | 0239a5b | 2017-11-01 20:27:06 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | #===- lib/fuzzer/scripts/unbalanced_allocs.py ------------------------------===# |
| 3 | # |
chandlerc | 4028449 | 2019-01-19 08:50:56 +0000 | [diff] [blame^] | 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 |
vitalybuka | 0239a5b | 2017-11-01 20:27:06 +0000 | [diff] [blame] | 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 | |
| 17 | import argparse |
| 18 | import sys |
| 19 | |
| 20 | _skip = 0 |
| 21 | |
| 22 | def PrintStack(line, stack): |
| 23 | global _skip |
| 24 | if _skip > 0: |
| 25 | return |
delcypher | 66c64f6 | 2018-04-20 06:46:09 +0000 | [diff] [blame] | 26 | print('Unbalanced ' + line.rstrip()); |
vitalybuka | 0239a5b | 2017-11-01 20:27:06 +0000 | [diff] [blame] | 27 | for l in stack: |
delcypher | 66c64f6 | 2018-04-20 06:46:09 +0000 | [diff] [blame] | 28 | print(l.rstrip()) |
vitalybuka | 0239a5b | 2017-11-01 20:27:06 +0000 | [diff] [blame] | 29 | |
| 30 | def ProcessStack(line, f): |
| 31 | stack = [] |
| 32 | while line and line.startswith(' #'): |
| 33 | stack += [line] |
| 34 | line = f.readline() |
| 35 | return line, stack |
| 36 | |
| 37 | def 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 | |
| 49 | def 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 | |
| 60 | def ProcessRun(line, f): |
| 61 | if not line.startswith('MallocFreeTracer: START'): |
| 62 | return ProcessMalloc(line, f, {}) |
| 63 | |
| 64 | allocs = {} |
delcypher | 66c64f6 | 2018-04-20 06:46:09 +0000 | [diff] [blame] | 65 | print(line.rstrip()) |
vitalybuka | 0239a5b | 2017-11-01 20:27:06 +0000 | [diff] [blame] | 66 | line = f.readline() |
| 67 | while line: |
| 68 | if line.startswith('MallocFreeTracer: STOP'): |
| 69 | global _skip |
| 70 | _skip = _skip - 1 |
delcypher | 66c64f6 | 2018-04-20 06:46:09 +0000 | [diff] [blame] | 71 | for _, (l, s) in allocs.items(): |
vitalybuka | 0239a5b | 2017-11-01 20:27:06 +0000 | [diff] [blame] | 72 | PrintStack(l, s) |
delcypher | 66c64f6 | 2018-04-20 06:46:09 +0000 | [diff] [blame] | 73 | print(line.rstrip()) |
vitalybuka | 0239a5b | 2017-11-01 20:27:06 +0000 | [diff] [blame] | 74 | return f.readline() |
| 75 | line = ProcessMalloc(line, f, allocs) |
| 76 | return line |
| 77 | |
| 78 | def ProcessFile(f): |
| 79 | line = f.readline() |
| 80 | while line: |
| 81 | line = ProcessRun(line, f); |
| 82 | |
| 83 | def 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 | |
| 91 | if __name__ == '__main__': |
| 92 | main(sys.argv) |