diff options
-rw-r--r-- | controller/fw/tools/linkmem.py | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/controller/fw/tools/linkmem.py b/controller/fw/tools/linkmem.py index 164c7cf..4cfceb5 100644 --- a/controller/fw/tools/linkmem.py +++ b/controller/fw/tools/linkmem.py @@ -11,7 +11,8 @@ import colorsys import cxxfilt from elftools.elf.elffile import ELFFile -from elftools.elf.descriptions import describe_symbol_type +from elftools.elf.enums import ENUM_ST_SHNDX +from elftools.elf.descriptions import describe_symbol_type, describe_sh_type import libarchive import matplotlib.cm @@ -63,6 +64,12 @@ def trace_source_files(linker, cmdline, trace_sections=[]): name_normalized = name.replace(' ', '') if name_normalized in symtab_demangled: entry = symtab.get_symbol(symtab_demangled[name_normalized]) + index = entry['st_shndx'] + if index in ENUM_ST_SHNDX: + return 'no bits' + sec = elf.get_section(index) + if describe_sh_type(sec['sh_type']) == 'NOBITS': + return 'no bits' return entry['st_size'] else: return None @@ -71,16 +78,16 @@ def trace_source_files(linker, cmdline, trace_sections=[]): s = set() sec_map = { sec.name: i for i, sec in enumerate(elf.iter_sections()) } - sec_name = f'.rel.text.{sym}' matches = [ i for name, i in sec_map.items() if re.match(f'\.rel\..*\.{sym}', name) ] if matches: sec = elf.get_section(matches[0]) for reloc in sec.iter_relocations(): refsym = symtab.get_symbol(reloc['r_info_sym']) - s.add(refsym.name) + name = refsym.name if refsym.name else elf.get_section(refsym['st_shndx']).name.split('.')[-1] + s.add(name) - if refsym.name not in defs: - syms[refsym.name] = fn, lookup_size(refsym.name) + if name not in defs: + syms[name] = fn, lookup_size(name) refs[sym] = s for tsec in trace_sections: @@ -98,7 +105,7 @@ def trace_source_files(linker, cmdline, trace_sections=[]): elf = ELFFile(f) symtab = elf.get_section_by_name('.symtab') for sym in symtab.iter_symbols(): - if describe_symbol_type(sym['st_info']['type']) == 'FUNC': + if describe_symbol_type(sym['st_info']['type']) in ('FUNC', 'OBJECT'): syms_out.add(sym.name) #for sym in defs: # entry = symtab.get_symbol_by_name(sym) @@ -141,7 +148,7 @@ if __name__ == '__main__': 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): + if path.basename(obj) in args.trim_stubs and (not isinstance(size, int) or size <= 8) and not refs.get(name): syms_out.discard(name) clusters = defaultdict(lambda: []) @@ -151,9 +158,9 @@ if __name__ == '__main__': obj_size = defaultdict(lambda: 0) for sym, (obj, size) in syms.items(): - if size is not None and sym in syms_out: + if isinstance(size, int) and sym in syms_out: obj_size[obj] += size - max_size = max([ size for _obj, size in syms.values() if size is not None ]) + max_size = max([ size for _obj, size in syms.values() if isinstance(size, int) ]) max_osize = max(obj_size.values()) @@ -174,6 +181,8 @@ if __name__ == '__main__': with wrap('digraph G', print) as lvl1print: print('rankdir=LR;') + print('ranksep=1;') + print('nodesep=0.2;') print() for i, (obj, syms) in enumerate(clusters.items()): @@ -191,8 +200,9 @@ if __name__ == '__main__': lvl2print() for sym, size in syms: if sym in syms_out: - 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];') + size_s = f'{size}B' if isinstance(size, int) else size + fc, cc = vhex(size/max_size if isinstance(size, int) else 0) + lvl2print(f'{mangle(sym)}[label = "{sym} ({size_s})", style="rounded,filled", shape="box", fillcolor="{fc}", fontname="carlito", fontcolor="{cc}" color=none];') lvl1print() for start, ends in refs.items(): |