blob: 11fd7f02172649bd72164703a799507231f52a2f [file] [log] [blame]
#
# Copyright (c) 2023, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
class TfaPrettyPrinter:
"""A class for printing the memory layout of ELF files.
This class provides interfaces for printing various memory layout views of
ELF files in a TF-A build. It can be used to understand how the memory is
structured and consumed.
"""
def __init__(self, columns: int = None, as_decimal: bool = False):
self.term_size = columns if columns and columns > 120 else 120
self._symbol_map = None
self.as_decimal = as_decimal
def format_args(self, *args, width=10, fmt=None):
if not fmt and type(args[0]) is int:
fmt = f">{width}x" if not self.as_decimal else f">{width}"
return [f"{arg:{fmt}}" if fmt else arg for arg in args]
@staticmethod
def map_elf_symbol(
leading: str,
section_name: str,
rel_pos: int,
columns: int,
width: int = None,
is_edge: bool = False,
):
empty_col = "{:{}{}}"
# Some symbols are longer than the column width, truncate them until
# we find a more elegant way to display them!
len_over = len(section_name) - width
if len_over > 0:
section_name = section_name[len_over:-len_over]
sec_row = f"+{section_name:-^{width-1}}+"
sep, fill = ("+", "-") if is_edge else ("|", "")
sec_row_l = empty_col.format(sep, fill + "<", width) * rel_pos
sec_row_r = empty_col.format(sep, fill + ">", width) * (
columns - rel_pos - 1
)
return leading + sec_row_l + sec_row + sec_row_r
def print_symbol_table(
self,
symbols: list,
modules: list,
start: int = 11,
):
assert len(symbols), "Empty symbol list!"
modules = sorted(modules)
col_width = int((self.term_size - start) / len(modules))
num_fmt = "0=#010x" if not self.as_decimal else ">10"
_symbol_map = [
" " * start
+ "".join(self.format_args(*modules, fmt=f"^{col_width}"))
]
last_addr = None
for i, (name, addr, mod) in enumerate(symbols):
# Do not print out an address twice if two symbols overlap,
# for example, at the end of one region and start of another.
leading = (
f"{addr:{num_fmt}}" + " " if addr != last_addr else " " * start
)
_symbol_map.append(
self.map_elf_symbol(
leading,
name,
modules.index(mod),
len(modules),
width=col_width,
is_edge=(not i or i == len(symbols) - 1),
)
)
last_addr = addr
self._symbol_map = ["Memory Layout:"]
self._symbol_map += list(reversed(_symbol_map))
print("\n".join(self._symbol_map))