blob: dedff799364e296c8a45f505a3c85def557ed384 [file] [log] [blame]
Harrison Mutaiaf5b49e2023-02-23 10:33:58 +00001#
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
Harrison Mutaid0e30532023-06-07 11:28:16 +010011from memory.mapparser import TfaMapParser
Harrison Mutaiaf5b49e2023-02-23 10:33:58 +000012
13
14class TfaBuildParser:
15 """A class for performing analysis on the memory layout of a TF-A build."""
16
Harrison Mutaid0e30532023-06-07 11:28:16 +010017 def __init__(self, path: Path, map_backend=False):
Harrison Mutaiaf5b49e2023-02-23 10:33:58 +000018 self._modules = dict()
19 self._path = path
Harrison Mutaid0e30532023-06-07 11:28:16 +010020 self.map_backend = map_backend
Harrison Mutaiaf5b49e2023-02-23 10:33:58 +000021 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):
Harrison Mutaid0e30532023-06-07 11:28:16 +010028 """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)
Harrison Mutaiaf5b49e2023-02-23 10:33:58 +000042
43 if not len(self._modules):
44 raise FileNotFoundError(
Harrison Mutaid0e30532023-06-07 11:28:16 +010045 f"failed to find files to analyse in path {self._path}!"
Harrison Mutaiaf5b49e2023-02-23 10:33:58 +000046 )
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
Harrison Mutaid9d5eb12023-02-23 11:30:17 +000064 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():
Harrison Mutaid0e30532023-06-07 11:28:16 +010068 mod_mem_map = v.get_memory_layout()
Harrison Mutaid9d5eb12023-02-23 11:30:17 +000069 if len(mod_mem_map):
70 mem_map[k] = mod_mem_map
71 return mem_map
72
Harrison Mutaicc60aba2023-02-23 11:30:55 +000073 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
Harrison Mutaiaf5b49e2023-02-23 10:33:58 +000085 @property
86 def module_names(self):
87 """Returns sorted list of module names."""
88 return sorted(self._modules.keys())