diff options
Diffstat (limited to 'controller/fw/tools')
-rw-r--r-- | controller/fw/tools/linkmem.py | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/controller/fw/tools/linkmem.py b/controller/fw/tools/linkmem.py index a04f31e..494217a 100644 --- a/controller/fw/tools/linkmem.py +++ b/controller/fw/tools/linkmem.py @@ -7,12 +7,13 @@ import re import subprocess from contextlib import contextmanager from collections import defaultdict +import colorsys import cxxfilt - from elftools.elf.elffile import ELFFile from elftools.elf.descriptions import describe_symbol_type import libarchive +import matplotlib.cm @contextmanager def chdir(newdir): @@ -117,10 +118,19 @@ def wrap(leader='', print=print, left='{', right='}'): def mangle(name): return re.sub('[^a-zA-Z0-9_]', '_', name) +hexcolor = lambda r, g, b: f'#{int(r*255):02x}{int(g*255):02x}{int(b*255):02x}' +def vhex(val): + r,g,b,_a = matplotlib.cm.viridis(1.0-val) + fc = hexcolor(r, g, b) + h,s,v = colorsys.rgb_to_hsv(r,g,b) + cc = '#000000' if v > 0.8 else '#ffffff' + return fc, cc + if __name__ == '__main__': import argparse parser = argparse.ArgumentParser() parser.add_argument('--trace-sections', type=str, action='append', default=[]) + parser.add_argument('--trim-stubs', type=str, action='append', default=[]) parser.add_argument('linker_binary') parser.add_argument('linker_args', nargs=argparse.REMAINDER) args = parser.parse_args() @@ -129,6 +139,10 @@ if __name__ == '__main__': trace_sections_mangled = { sec.replace('.', '_') for sec in trace_sections } syms, refs, syms_out = trace_source_files(args.linker_binary, args.linker_args, trace_sections) + for name, (obj, size) in syms.items(): + if path.basename(obj) in args.trim_stubs and size <= 8 and not refs.get(name): + syms_out.discard(name) + clusters = defaultdict(lambda: []) for sym, (obj, size) in syms.items(): clusters[obj].append((sym, size)) @@ -137,6 +151,9 @@ if __name__ == '__main__': for name, (obj, size) in syms.items(): if size is not None: obj_size[obj] += size + max_size = max([ size for _obj, size in syms.values() if size is not None ]) + + max_osize = max(obj_size.values()) with wrap('digraph G', print) as lvl1print: print('rankdir=LR;') @@ -144,18 +161,20 @@ if __name__ == '__main__': for i, (obj, syms) in enumerate(clusters.items()): with wrap(f'subgraph cluster_{i}', lvl1print) as lvl2print: - lvl2print(f'label = "{obj} <{obj_size[obj]}>";') + fc, cc = vhex(obj_size[obj]/max_osize) + lvl2print(f'label = <<table border="0"><tr><td border="0" cellpadding="5" bgcolor="{fc}"><font face="carlito" color="{cc}"><b>{path.basename(obj)} ({obj_size[obj]}B)</b></font></td></tr></table>>;') lvl2print() for sym, size in syms: if sym in syms_out: - lvl2print(f'{mangle(sym)}[label = "{sym} <{size}>"];') + fc, cc = vhex(size/max_size) + lvl2print(f'{mangle(sym)}[label = "{sym} ({size}B)", style="rounded,filled", shape="box", fillcolor="{fc}", fontname="carlito", fontcolor="{cc}" color=None];') lvl1print() for start, ends in refs.items(): for end in ends: if end and (start in syms_out or start in trace_sections_mangled) and end in syms_out: - lvl1print(f'{mangle(start)} -> {mangle(end)};') + lvl1print(f'{mangle(start)} -> {mangle(end)} [style="bold", color="#333333"];') for sec in trace_sections: - lvl1print(f'{sec.replace(".", "_")} [label = "section {sec}"];') + lvl1print(f'{sec.replace(".", "_")} [label = "section {sec}", shape="box", style="filled,bold"];') |