summaryrefslogtreecommitdiff
path: root/controller
diff options
context:
space:
mode:
Diffstat (limited to 'controller')
-rw-r--r--controller/fw/tools/linkmem.py32
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():