scripts: size_report: alter how nodes are grouped together
This changes how the tree is generated. Symbols with no paths are now grouped together instead of scattering throughout the tree. If paths in ELF file are not all under ZEPHYR_BASE, it will create additional node groups as 2nd level. This is useful when not all source files are under ZEPHYR_BASE, and provides a better indications of where they are. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
parent
3e695ccef9
commit
e87c82df51
1 changed files with 79 additions and 8 deletions
|
@ -508,6 +508,20 @@ def set_root_path_for_unmapped_symbols(symbol_dict, addr_range, processed):
|
|||
processed['mapped_addr'] = mapped_addresses
|
||||
processed['unmapped_symbols'] = unmapped_symbols
|
||||
|
||||
def find_common_path_prefix(symbol_dict):
|
||||
"""
|
||||
Find the common path prefix of all mapped files.
|
||||
Must be called before set_root_path_for_unmapped_symbols().
|
||||
"""
|
||||
paths = list()
|
||||
|
||||
for _, sym in symbol_dict.items():
|
||||
for symbol in sym:
|
||||
for file in symbol['mapped_files']:
|
||||
paths.append(file)
|
||||
|
||||
return os.path.commonpath(paths)
|
||||
|
||||
|
||||
class TreeNode(NodeMixin):
|
||||
"""
|
||||
|
@ -527,11 +541,35 @@ class TreeNode(NodeMixin):
|
|||
return self.name
|
||||
|
||||
|
||||
def generate_any_tree(symbol_dict):
|
||||
def sum_node_children_size(node):
|
||||
"""
|
||||
Calculate the sum of symbol size of all direct children.
|
||||
"""
|
||||
size = 0
|
||||
|
||||
for child in node.children:
|
||||
size += child.size
|
||||
|
||||
return size
|
||||
|
||||
|
||||
def generate_any_tree(symbol_dict, path_prefix):
|
||||
"""
|
||||
Generate a symbol tree for output.
|
||||
"""
|
||||
root = TreeNode('root', ":")
|
||||
root = TreeNode('Symbols', ":")
|
||||
node_no_paths = TreeNode('(no paths)', ":", parent=root)
|
||||
|
||||
if Path(path_prefix) == Path(args.zephyrbase):
|
||||
# All source files are under ZEPHYR_BASE so there is
|
||||
# no need for another level.
|
||||
node_zephyr_base = root
|
||||
node_output_dir = root
|
||||
node_others = root
|
||||
else:
|
||||
node_zephyr_base = TreeNode('ZEPHYR_BASE', args.zephyrbase)
|
||||
node_output_dir = TreeNode('OUTPUT_DIR', args.output)
|
||||
node_others = TreeNode("/", "/")
|
||||
|
||||
# A set of helper function for building a simple tree with a path-like
|
||||
# hierarchy.
|
||||
|
@ -555,17 +593,49 @@ def generate_any_tree(symbol_dict):
|
|||
parent = node
|
||||
node = TreeNode(name=str(part), identifier=cur, size=size, parent=parent)
|
||||
|
||||
zbase = Path(args.zephyrbase)
|
||||
outd = Path(args.output)
|
||||
|
||||
for name, sym in symbol_dict.items():
|
||||
for symbol in sym:
|
||||
size = get_symbol_size(symbol['symbol'])
|
||||
for file in symbol['mapped_files']:
|
||||
path = Path(file, name)
|
||||
if path.is_absolute():
|
||||
zb = Path(args.zephyrbase)
|
||||
if zb in path.parents:
|
||||
path = path.relative_to(zb)
|
||||
if zbase in path.parents:
|
||||
path = path.relative_to(zbase)
|
||||
dest_node = node_zephyr_base
|
||||
elif outd in path.parents:
|
||||
path = path.relative_to(outd)
|
||||
dest_node = node_output_dir
|
||||
else:
|
||||
dest_node = node_others
|
||||
else:
|
||||
dest_node = node_no_paths
|
||||
|
||||
_insert_one_elem(root, path, size)
|
||||
_insert_one_elem(dest_node, path, size)
|
||||
|
||||
|
||||
if node_zephyr_base is not root:
|
||||
# ZEPHYR_BASE and OUTPUT_DIR nodes don't have sum of symbol size
|
||||
# so calculate them here.
|
||||
node_zephyr_base.size = sum_node_children_size(node_zephyr_base)
|
||||
node_output_dir.size = sum_node_children_size(node_output_dir)
|
||||
|
||||
# Find out which nodes need to be in the tree.
|
||||
# "(no path)", ZEPHYR_BASE nodes are essential.
|
||||
children = [node_no_paths, node_zephyr_base]
|
||||
if node_output_dir.height != 0:
|
||||
# OUTPUT_DIR may be under ZEPHYR_BASE.
|
||||
children.append(node_output_dir)
|
||||
if node_others.height != 0:
|
||||
# Only include "others" node if there is something.
|
||||
children.append(node_others)
|
||||
|
||||
root.children = children
|
||||
|
||||
# Root node doesn't have sum of symbol size. So sum them up.
|
||||
root.size = sum_node_children_size(root)
|
||||
|
||||
return root
|
||||
|
||||
|
@ -597,7 +667,7 @@ def print_any_tree(root, total_size, depth):
|
|||
cc = Fore.GREEN
|
||||
cr = Fore.RESET
|
||||
|
||||
print(f"{row.pre}{cc}{row.node.name}{cr} {s} {Fore.BLUE}{percent:.2f}%{Fore.RESET}")
|
||||
print(f"{row.pre}{cc}{row.node.name}{cr} {s} {Fore.BLUE}{percent:5.2f}%{Fore.RESET}")
|
||||
print('=' * 110)
|
||||
print(f'{total_size:>101}')
|
||||
|
||||
|
@ -670,13 +740,14 @@ def main():
|
|||
mark_address_aliases(symbol_dict, processed)
|
||||
do_address_range_matching(elf, symbol_dict, processed)
|
||||
mark_address_aliases(symbol_dict, processed)
|
||||
common_path_prefix = find_common_path_prefix(symbol_dict)
|
||||
set_root_path_for_unmapped_symbols(symbol_dict, ranges, processed)
|
||||
|
||||
if args.verbose:
|
||||
for sym in processed['unmapped_symbols']:
|
||||
print("INFO: Unmapped symbol: {0}".format(sym))
|
||||
|
||||
root = generate_any_tree(symbol_dict)
|
||||
root = generate_any_tree(symbol_dict, common_path_prefix)
|
||||
print_any_tree(root, symsize, args.depth)
|
||||
|
||||
if args.json:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue