# # Copyright (c) 2019 Chris Johns . # All rights reserved. # # The license and distribution terms for this file may be # found in the file LICENSE in this distribution or at # http://www.rtems.org/license/LICENSE. # # Check the allocations for libdl: # # 1. Turn on the allocation trace. # # 2. Load and unload object files. # # 3. Capture the trace output and feed to this tool # from __future__ import print_function import argparse class libdl_trace(object): def __init__(self, name): self.name = name self.trace = {'alloc': []} def load(self): with open(self.name, 'r') as f: lc = 0 for line in f: line = line[:-1] lc += 1 if line.startswith('rtl: '): if line.startswith('rtl: alloc: '): self.trace['alloc'] += [(lc, line)] def check_allocs(self): allocs = {} locks = 0 wr_enable = False for lc, line in self.trace['alloc']: ls = line.split(' ') if len(ls) > 3: if ls[2] == 'new:': addr = ls[4].split('=')[1] size = ls[5].split('=')[1] count = 0 if addr in allocs: alc, alloced, asize, count = allocs[addr] if alloced: print( '%5d: already alloced: %5d: addr=%-9s size=%-9s count=%d' % (lc, alc, addr, asize, count)) allocs[addr] = (lc, True, size, count + 1) elif ls[2] == 'del:': addr = ls[4].split('=')[1] if addr != '0': if addr not in allocs: print('%5d: delete never alloced: addr=%s' % (lc, addr)) else: alc, alloced, size, count = allocs[addr] if not alloced: print( '%5d: delete not alloced: %5d: addr=%-9s size=%-9s count=%d' % (lc, alc, addr, size, count)) allocs[addr] = (lc, False, size, count) alloced_remaiing = 0 addresses = sorted(list(allocs.keys())) for addr in addresses: lc, alloced, size, count = allocs[addr] if alloced: print('%5d: never deleted: addr=%-9s size=%-9s count=%d' % (lc, addr, size, count)) alloced_remaiing += int(size) if alloced_remaiing != 0: print("Amount alloced: %d" % (alloced_remaiing)) def run(args): argsp = argparse.ArgumentParser(prog='rtl-alloc-check', description='Audit libdl allocations') argsp.add_argument('traces', help='libdl trace files', nargs='+') opts = argsp.parse_args(args[1:]) for t in opts.traces: trace = libdl_trace(t) trace.load() trace.check_allocs() if __name__ == "__main__": import sys run(sys.argv)