1# 2# Copyright (c) 2023, Arm Limited. All rights reserved. 3# 4# SPDX-License-Identifier: BSD-3-Clause 5# 6 7import re 8from pathlib import Path 9 10from memory.elfparser import TfaElfParser 11from memory.mapparser import TfaMapParser 12 13 14class TfaBuildParser: 15 """A class for performing analysis on the memory layout of a TF-A build.""" 16 17 def __init__(self, path: Path, map_backend=False): 18 self._modules = dict() 19 self._path = path 20 self.map_backend = map_backend 21 self._parse_modules() 22 23 def __getitem__(self, module: str): 24 """Returns an TfaElfParser instance indexed by module.""" 25 return self._modules[module] 26 27 def _parse_modules(self): 28 """Parse the build files using the selected backend.""" 29 backend = TfaElfParser 30 files = list(self._path.glob("**/*.elf")) 31 io_perms = "rb" 32 33 if self.map_backend or len(files) == 0: 34 backend = TfaMapParser 35 files = self._path.glob("**/*.map") 36 io_perms = "r" 37 38 for file in files: 39 module_name = file.name.split("/")[-1].split(".")[0] 40 with open(file, io_perms) as f: 41 self._modules[module_name] = backend(f) 42 43 if not len(self._modules): 44 raise FileNotFoundError( 45 f"failed to find files to analyse in path {self._path}!" 46 ) 47 48 @property 49 def symbols(self) -> list: 50 return [ 51 (*sym, k) for k, v in self._modules.items() for sym in v.symbols 52 ] 53 54 @staticmethod 55 def filter_symbols(symbols: list, regex: str = None) -> list: 56 """Returns a map of symbols to modules.""" 57 regex = r".*" if not regex else regex 58 return sorted( 59 filter(lambda s: re.match(regex, s[0]), symbols), 60 key=lambda s: (-s[1], s[0]), 61 reverse=True, 62 ) 63 64 def get_mem_usage_dict(self) -> dict: 65 """Returns map of memory usage per memory type for each module.""" 66 mem_map = {} 67 for k, v in self._modules.items(): 68 mod_mem_map = v.get_memory_layout() 69 if len(mod_mem_map): 70 mem_map[k] = mod_mem_map 71 return mem_map 72 73 def get_mem_tree_as_dict(self) -> dict: 74 """Returns _tree of modules, segments and segments and their total 75 memory usage.""" 76 return { 77 k: { 78 "name": k, 79 **v.get_mod_mem_usage_dict(), 80 **{"children": v.get_seg_map_as_dict()}, 81 } 82 for k, v in self._modules.items() 83 } 84 85 @property 86 def module_names(self): 87 """Returns sorted list of module names.""" 88 return sorted(self._modules.keys()) 89