1bbaeed4dSRouven Czerwinski#!/usr/bin/env python3 21bb92983SJerome Forissier# SPDX-License-Identifier: BSD-2-Clause 3733a15f2SJerome Forissier# 4733a15f2SJerome Forissier# Copyright (c) 2017, Linaro Limited 5733a15f2SJerome Forissier# 6733a15f2SJerome Forissier 7733a15f2SJerome Forissier 8733a15f2SJerome Forissierimport argparse 9bbaeed4dSRouven Czerwinskiimport errno 10733a15f2SJerome Forissierimport glob 11157e6213SJerome Forissierimport os 12733a15f2SJerome Forissierimport re 13733a15f2SJerome Forissierimport subprocess 14733a15f2SJerome Forissierimport sys 156b4fc675SJerome Forissierimport termios 16733a15f2SJerome Forissier 17733a15f2SJerome ForissierCALL_STACK_RE = re.compile('Call stack:') 18*105e09c2SJerome ForissierTEE_LOAD_ADDR_RE = re.compile(r'Load address @ (?P<load_addr>0x[0-9a-f]+)') 19a2b984bdSJoakim Bech# This gets the address from lines looking like this: 20a2b984bdSJoakim Bech# E/TC:0 0x001044a8 216e7c2e91SJerome ForissierSTACK_ADDR_RE = re.compile( 22531963a5SJens Wiklander r'[UEIDFM]/(TC|LD):(\?*|[0-9]*) [0-9]* +(?P<addr>0x[0-9a-f]+)') 236e7c2e91SJerome ForissierABORT_ADDR_RE = re.compile(r'-abort at address (?P<addr>0x[0-9a-f]+)') 24444c203eSJerome ForissierREGION_RE = re.compile(r'region +[0-9]+: va (?P<addr>0x[0-9a-f]+) ' 256e7c2e91SJerome Forissier r'pa 0x[0-9a-f]+ size (?P<size>0x[0-9a-f]+)' 26531963a5SJens Wiklander r'( flags .{4} (\[(?P<elf_idx>[0-9]+)\])?)?') 27ae252462SJerome ForissierELF_LIST_RE = re.compile(r'\[(?P<idx>[0-9]+)\] (?P<uuid>[0-9a-f\-]+)' 286e7c2e91SJerome Forissier r' @ (?P<load_addr>0x[0-9a-f\-]+)') 29c90b6663SSumit GargFUNC_GRAPH_RE = re.compile(r'Function graph') 30c90b6663SSumit GargGRAPH_ADDR_RE = re.compile(r'(?P<addr>0x[0-9a-f]+)') 31c90b6663SSumit GargGRAPH_RE = re.compile(r'}') 32733a15f2SJerome Forissier 33733a15f2SJerome Forissierepilog = ''' 340c5bedb5SJerome ForissierThis scripts reads an OP-TEE abort or panic message from stdin and adds debug 350c5bedb5SJerome Forissierinformation to the output, such as '<function> at <file>:<line>' next to each 360c5bedb5SJerome Forissieraddress in the call stack. Any message generated by OP-TEE and containing a 370c5bedb5SJerome Forissiercall stack can in principle be processed by this script. This currently 380c5bedb5SJerome Forissierincludes aborts and panics from the TEE core as well as from any TA. 390c5bedb5SJerome ForissierThe paths provided on the command line are used to locate the appropriate ELF 400c5bedb5SJerome Forissierbinary (tee.elf or Trusted Application). The GNU binutils (addr2line, objdump, 41f9089765SJerome Forissiernm) are used to extract the debug info. If the CROSS_COMPILE environment 42f9089765SJerome Forissiervariable is set, it is used as a prefix to the binutils tools. That is, the 43f9089765SJerome Forissierscript will invoke $(CROSS_COMPILE)addr2line etc. If it is not set however, 44f9089765SJerome Forissierthe prefix will be determined automatically for each ELF file based on its 45f9089765SJerome Forissierarchitecture (arm-linux-gnueabihf-, aarch64-linux-gnu-). The resulting command 46f9089765SJerome Forissieris then expected to be found in the user's PATH. 47733a15f2SJerome Forissier 480c5bedb5SJerome ForissierOP-TEE abort and panic messages are sent to the secure console. They look like 490c5bedb5SJerome Forissierthe following: 50733a15f2SJerome Forissier 510c5bedb5SJerome Forissier E/TC:0 User TA data-abort at address 0xffffdecd (alignment fault) 52733a15f2SJerome Forissier ... 530c5bedb5SJerome Forissier E/TC:0 Call stack: 540c5bedb5SJerome Forissier E/TC:0 0x4000549e 550c5bedb5SJerome Forissier E/TC:0 0x40001f4b 560c5bedb5SJerome Forissier E/TC:0 0x4000273f 570c5bedb5SJerome Forissier E/TC:0 0x40005da7 58733a15f2SJerome Forissier 59733a15f2SJerome ForissierInspired by a script of the same name by the Chromium project. 60733a15f2SJerome Forissier 61733a15f2SJerome ForissierSample usage: 62733a15f2SJerome Forissier 63733a15f2SJerome Forissier $ scripts/symbolize.py -d out/arm-plat-hikey/core -d ../optee_test/out/ta/* 64733a15f2SJerome Forissier <paste whole dump here> 65733a15f2SJerome Forissier ^D 66c90b6663SSumit Garg 67c90b6663SSumit GargAlso, this script reads function graph generated for OP-TEE user TA from 68c90b6663SSumit Garg/tmp/ftrace-<ta_uuid>.out file and resolves function addresses to corresponding 69c90b6663SSumit Gargsymbols. 70c90b6663SSumit Garg 71c90b6663SSumit GargSample usage: 72c90b6663SSumit Garg 73c90b6663SSumit Garg $ cat /tmp/ftrace-<ta_uuid>.out | scripts/symbolize.py -d <ta_uuid>.elf 74c90b6663SSumit Garg <paste function graph here> 75c90b6663SSumit Garg ^D 76733a15f2SJerome Forissier''' 77733a15f2SJerome Forissier 78ae252462SJerome Forissier 79733a15f2SJerome Forissierdef get_args(): 80733a15f2SJerome Forissier parser = argparse.ArgumentParser( 81733a15f2SJerome Forissier formatter_class=argparse.RawDescriptionHelpFormatter, 82c90b6663SSumit Garg description='Symbolizes OP-TEE abort dumps or function graphs', 83733a15f2SJerome Forissier epilog=epilog) 84733a15f2SJerome Forissier parser.add_argument('-d', '--dir', action='append', nargs='+', 851d8c2a48SJerome Forissier help='Search for ELF file in DIR. tee.elf is needed ' 861d8c2a48SJerome Forissier 'to decode a TEE Core or pseudo-TA abort, while ' 871d8c2a48SJerome Forissier '<TA_uuid>.elf is required if a user-mode TA has ' 881d8c2a48SJerome Forissier 'crashed. For convenience, ELF files may also be ' 891d8c2a48SJerome Forissier 'given.') 905f7df507SJerome Forissier parser.add_argument('-s', '--strip_path', nargs='?', 911d8c2a48SJerome Forissier help='Strip STRIP_PATH from file paths (default: ' 921d8c2a48SJerome Forissier 'current directory, use -s with no argument to show ' 931d8c2a48SJerome Forissier 'full paths)', default=os.getcwd()) 94733a15f2SJerome Forissier 95733a15f2SJerome Forissier return parser.parse_args() 96733a15f2SJerome Forissier 97ae252462SJerome Forissier 98733a15f2SJerome Forissierclass Symbolizer(object): 99733a15f2SJerome Forissier def __init__(self, out, dirs, strip_path): 100733a15f2SJerome Forissier self._out = out 101733a15f2SJerome Forissier self._dirs = dirs 102733a15f2SJerome Forissier self._strip_path = strip_path 103733a15f2SJerome Forissier self._addr2line = None 104733a15f2SJerome Forissier self.reset() 105733a15f2SJerome Forissier 1061cbf777bSJerome Forissier def my_Popen(self, cmd): 1071cbf777bSJerome Forissier try: 1081cbf777bSJerome Forissier return subprocess.Popen(cmd, stdin=subprocess.PIPE, 109bbaeed4dSRouven Czerwinski stdout=subprocess.PIPE, text=True, 110bbaeed4dSRouven Czerwinski bufsize=1) 1111cbf777bSJerome Forissier except OSError as e: 112bbaeed4dSRouven Czerwinski if e.errno == errno.ENOENT: 113bbaeed4dSRouven Czerwinski print("*** Error:{}: command not found".format(cmd[0]), 114bbaeed4dSRouven Czerwinski file=sys.stderr) 1151cbf777bSJerome Forissier sys.exit(1) 1161cbf777bSJerome Forissier 117733a15f2SJerome Forissier def get_elf(self, elf_or_uuid): 118733a15f2SJerome Forissier if not elf_or_uuid.endswith('.elf'): 119733a15f2SJerome Forissier elf_or_uuid += '.elf' 120733a15f2SJerome Forissier for d in self._dirs: 121157e6213SJerome Forissier if d.endswith(elf_or_uuid) and os.path.isfile(d): 122157e6213SJerome Forissier return d 123733a15f2SJerome Forissier elf = glob.glob(d + '/' + elf_or_uuid) 124733a15f2SJerome Forissier if elf: 125733a15f2SJerome Forissier return elf[0] 126733a15f2SJerome Forissier 127d720431cSJerome Forissier def set_arch(self): 128d720431cSJerome Forissier if self._arch: 129d720431cSJerome Forissier return 1306e7c2e91SJerome Forissier self._arch = os.getenv('CROSS_COMPILE') 1318a6d4a8bSEtienne Carriere if self._arch: 1328a6d4a8bSEtienne Carriere return 133ae252462SJerome Forissier elf = self.get_elf(self._elfs[0][0]) 134ae252462SJerome Forissier if elf is None: 135ae252462SJerome Forissier return 136ae252462SJerome Forissier p = subprocess.Popen(['file', self.get_elf(self._elfs[0][0])], 137d720431cSJerome Forissier stdout=subprocess.PIPE) 138d720431cSJerome Forissier output = p.stdout.readlines() 139d720431cSJerome Forissier p.terminate() 140bbaeed4dSRouven Czerwinski if b'ARM aarch64,' in output[0]: 141d720431cSJerome Forissier self._arch = 'aarch64-linux-gnu-' 142bbaeed4dSRouven Czerwinski elif b'ARM,' in output[0]: 143d720431cSJerome Forissier self._arch = 'arm-linux-gnueabihf-' 144d720431cSJerome Forissier 145142c5cccSJerome Forissier def arch_prefix(self, cmd): 146d720431cSJerome Forissier self.set_arch() 147ae252462SJerome Forissier if self._arch is None: 148ae252462SJerome Forissier return '' 149d720431cSJerome Forissier return self._arch + cmd 150142c5cccSJerome Forissier 151ae252462SJerome Forissier def spawn_addr2line(self, elf_name): 152ae252462SJerome Forissier if elf_name is None: 153ae252462SJerome Forissier return 154ae252462SJerome Forissier if self._addr2line_elf_name is elf_name: 155ae252462SJerome Forissier return 156ae252462SJerome Forissier if self._addr2line: 157ae252462SJerome Forissier self._addr2line.terminate 158ae252462SJerome Forissier self._addr2line = None 159ae252462SJerome Forissier elf = self.get_elf(elf_name) 160733a15f2SJerome Forissier if not elf: 161733a15f2SJerome Forissier return 162142c5cccSJerome Forissier cmd = self.arch_prefix('addr2line') 163142c5cccSJerome Forissier if not cmd: 164733a15f2SJerome Forissier return 165*105e09c2SJerome Forissier args = [cmd] 166*105e09c2SJerome Forissier if elf_name == 'tee.elf' and self._tee_load_addr != '0x0': 167*105e09c2SJerome Forissier args += ['-j.text'] 168*105e09c2SJerome Forissier args += ['-f', '-p', '-e', elf] 169*105e09c2SJerome Forissier self._addr2line = self.my_Popen(args) 170ae252462SJerome Forissier self._addr2line_elf_name = elf_name 171ae252462SJerome Forissier 172ae252462SJerome Forissier # If addr falls into a region that maps a TA ELF file, return the load 173ae252462SJerome Forissier # address of that file. 174ae252462SJerome Forissier def elf_load_addr(self, addr): 175ae252462SJerome Forissier if self._regions: 176ae252462SJerome Forissier for r in self._regions: 177ae252462SJerome Forissier r_addr = int(r[0], 16) 178ae252462SJerome Forissier r_size = int(r[1], 16) 179ae252462SJerome Forissier i_addr = int(addr, 16) 180ae252462SJerome Forissier if (i_addr >= r_addr and i_addr < (r_addr + r_size)): 181ae252462SJerome Forissier # Found region 182ae252462SJerome Forissier elf_idx = r[2] 183ae252462SJerome Forissier if elf_idx is not None: 184ae252462SJerome Forissier return self._elfs[int(elf_idx)][1] 185099918f6SSumit Garg # In case address is not found in TA ELF file, fallback to tee.elf 186099918f6SSumit Garg # especially to symbolize mixed (user-space and kernel) addresses 187099918f6SSumit Garg # which is true when syscall ftrace is enabled along with TA 188099918f6SSumit Garg # ftrace. 189099918f6SSumit Garg return '0x0' 190ae252462SJerome Forissier else: 191ae252462SJerome Forissier # tee.elf 192*105e09c2SJerome Forissier return self._tee_load_addr 193ae252462SJerome Forissier 194ae252462SJerome Forissier def elf_for_addr(self, addr): 195*105e09c2SJerome Forissier if not self._regions: 196*105e09c2SJerome Forissier return 'tee.elf' 197ae252462SJerome Forissier l_addr = self.elf_load_addr(addr) 198ae252462SJerome Forissier if l_addr is None: 199ae252462SJerome Forissier return None 200ae252462SJerome Forissier for k in self._elfs: 201ae252462SJerome Forissier e = self._elfs[k] 202ae252462SJerome Forissier if int(e[1], 16) == int(l_addr, 16): 203ae252462SJerome Forissier return e[0] 204ae252462SJerome Forissier return None 205733a15f2SJerome Forissier 206142c5cccSJerome Forissier def subtract_load_addr(self, addr): 207ae252462SJerome Forissier l_addr = self.elf_load_addr(addr) 208ae252462SJerome Forissier if l_addr is None: 209ae252462SJerome Forissier return None 210ae252462SJerome Forissier if int(l_addr, 16) > int(addr, 16): 211142c5cccSJerome Forissier return '' 212ae252462SJerome Forissier return '0x{:x}'.format(int(addr, 16) - int(l_addr, 16)) 213142c5cccSJerome Forissier 214142c5cccSJerome Forissier def resolve(self, addr): 215142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 216ae252462SJerome Forissier self.spawn_addr2line(self.elf_for_addr(addr)) 217142c5cccSJerome Forissier if not reladdr or not self._addr2line: 218733a15f2SJerome Forissier return '???' 219733a15f2SJerome Forissier try: 220bbaeed4dSRouven Czerwinski print(reladdr, file=self._addr2line.stdin) 221733a15f2SJerome Forissier ret = self._addr2line.stdout.readline().rstrip('\n') 222733a15f2SJerome Forissier except IOError: 223733a15f2SJerome Forissier ret = '!!!' 224733a15f2SJerome Forissier return ret 225733a15f2SJerome Forissier 226142c5cccSJerome Forissier def symbol_plus_offset(self, addr): 227142c5cccSJerome Forissier ret = '' 228142c5cccSJerome Forissier prevsize = 0 229142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 230ae252462SJerome Forissier elf_name = self.elf_for_addr(addr) 231ae252462SJerome Forissier if elf_name is None: 232ae252462SJerome Forissier return '' 233ae252462SJerome Forissier elf = self.get_elf(elf_name) 234142c5cccSJerome Forissier cmd = self.arch_prefix('nm') 235142c5cccSJerome Forissier if not reladdr or not elf or not cmd: 236142c5cccSJerome Forissier return '' 23730999126SJerome Forissier ireladdr = int(reladdr, 16) 2381cbf777bSJerome Forissier nm = self.my_Popen([cmd, '--numeric-sort', '--print-size', elf]) 239142c5cccSJerome Forissier for line in iter(nm.stdout.readline, ''): 240142c5cccSJerome Forissier try: 241142c5cccSJerome Forissier addr, size, _, name = line.split() 2421d8c2a48SJerome Forissier except ValueError: 243142c5cccSJerome Forissier # Size is missing 244b4815427SJerome Forissier try: 245142c5cccSJerome Forissier addr, _, name = line.split() 246142c5cccSJerome Forissier size = '0' 2471d8c2a48SJerome Forissier except ValueError: 248b4815427SJerome Forissier # E.g., undefined (external) symbols (line = "U symbol") 249b4815427SJerome Forissier continue 250142c5cccSJerome Forissier iaddr = int(addr, 16) 251142c5cccSJerome Forissier isize = int(size, 16) 252142c5cccSJerome Forissier if iaddr == ireladdr: 253142c5cccSJerome Forissier ret = name 254142c5cccSJerome Forissier break 255142c5cccSJerome Forissier if iaddr < ireladdr and iaddr + isize >= ireladdr: 256142c5cccSJerome Forissier offs = ireladdr - iaddr 257142c5cccSJerome Forissier ret = name + '+' + str(offs) 258142c5cccSJerome Forissier break 259142c5cccSJerome Forissier if iaddr > ireladdr and prevsize == 0: 260142c5cccSJerome Forissier offs = iaddr + ireladdr 261142c5cccSJerome Forissier ret = prevname + '+' + str(offs) 262142c5cccSJerome Forissier break 263142c5cccSJerome Forissier prevsize = size 264142c5cccSJerome Forissier prevname = name 265142c5cccSJerome Forissier nm.terminate() 266142c5cccSJerome Forissier return ret 267142c5cccSJerome Forissier 268142c5cccSJerome Forissier def section_plus_offset(self, addr): 269142c5cccSJerome Forissier ret = '' 270142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 271ae252462SJerome Forissier elf_name = self.elf_for_addr(addr) 272ae252462SJerome Forissier if elf_name is None: 273ae252462SJerome Forissier return '' 274ae252462SJerome Forissier elf = self.get_elf(elf_name) 275142c5cccSJerome Forissier cmd = self.arch_prefix('objdump') 276142c5cccSJerome Forissier if not reladdr or not elf or not cmd: 277142c5cccSJerome Forissier return '' 27830999126SJerome Forissier iaddr = int(reladdr, 16) 2791cbf777bSJerome Forissier objdump = self.my_Popen([cmd, '--section-headers', elf]) 280142c5cccSJerome Forissier for line in iter(objdump.stdout.readline, ''): 281142c5cccSJerome Forissier try: 282142c5cccSJerome Forissier idx, name, size, vma, lma, offs, algn = line.split() 2831d8c2a48SJerome Forissier except ValueError: 284ae252462SJerome Forissier continue 285142c5cccSJerome Forissier ivma = int(vma, 16) 286142c5cccSJerome Forissier isize = int(size, 16) 287142c5cccSJerome Forissier if ivma == iaddr: 288142c5cccSJerome Forissier ret = name 289142c5cccSJerome Forissier break 290142c5cccSJerome Forissier if ivma < iaddr and ivma + isize >= iaddr: 291142c5cccSJerome Forissier offs = iaddr - ivma 292142c5cccSJerome Forissier ret = name + '+' + str(offs) 293142c5cccSJerome Forissier break 294142c5cccSJerome Forissier objdump.terminate() 295142c5cccSJerome Forissier return ret 296142c5cccSJerome Forissier 297142c5cccSJerome Forissier def process_abort(self, line): 298142c5cccSJerome Forissier ret = '' 299142c5cccSJerome Forissier match = re.search(ABORT_ADDR_RE, line) 300142c5cccSJerome Forissier addr = match.group('addr') 301142c5cccSJerome Forissier pre = match.start('addr') 302142c5cccSJerome Forissier post = match.end('addr') 303142c5cccSJerome Forissier sym = self.symbol_plus_offset(addr) 304142c5cccSJerome Forissier sec = self.section_plus_offset(addr) 305142c5cccSJerome Forissier if sym or sec: 306142c5cccSJerome Forissier ret += line[:pre] 307142c5cccSJerome Forissier ret += addr 308142c5cccSJerome Forissier if sym: 309142c5cccSJerome Forissier ret += ' ' + sym 310142c5cccSJerome Forissier if sec: 311142c5cccSJerome Forissier ret += ' ' + sec 312142c5cccSJerome Forissier ret += line[post:] 313142c5cccSJerome Forissier return ret 314142c5cccSJerome Forissier 31530999126SJerome Forissier # Return all ELF sections with the ALLOC flag 316ae252462SJerome Forissier def read_sections(self, elf_name): 317ae252462SJerome Forissier if elf_name is None: 31830999126SJerome Forissier return 319ae252462SJerome Forissier if elf_name in self._sections: 320ae252462SJerome Forissier return 321ae252462SJerome Forissier elf = self.get_elf(elf_name) 32230999126SJerome Forissier cmd = self.arch_prefix('objdump') 32330999126SJerome Forissier if not elf or not cmd: 32430999126SJerome Forissier return 325ae252462SJerome Forissier self._sections[elf_name] = [] 3261cbf777bSJerome Forissier objdump = self.my_Popen([cmd, '--section-headers', elf]) 32730999126SJerome Forissier for line in iter(objdump.stdout.readline, ''): 32830999126SJerome Forissier try: 32930999126SJerome Forissier _, name, size, vma, _, _, _ = line.split() 3301d8c2a48SJerome Forissier except ValueError: 33130999126SJerome Forissier if 'ALLOC' in line: 332ae252462SJerome Forissier self._sections[elf_name].append([name, int(vma, 16), 333ae252462SJerome Forissier int(size, 16)]) 33430999126SJerome Forissier 33530999126SJerome Forissier def overlaps(self, section, addr, size): 33630999126SJerome Forissier sec_addr = section[1] 33730999126SJerome Forissier sec_size = section[2] 33830999126SJerome Forissier if not size or not sec_size: 33930999126SJerome Forissier return False 340ae252462SJerome Forissier return ((addr <= (sec_addr + sec_size - 1)) and 341ae252462SJerome Forissier ((addr + size - 1) >= sec_addr)) 34230999126SJerome Forissier 343ae252462SJerome Forissier def sections_in_region(self, addr, size, elf_idx): 34430999126SJerome Forissier ret = '' 34530999126SJerome Forissier addr = self.subtract_load_addr(addr) 34630999126SJerome Forissier if not addr: 34730999126SJerome Forissier return '' 34830999126SJerome Forissier iaddr = int(addr, 16) 34930999126SJerome Forissier isize = int(size, 16) 350ae252462SJerome Forissier elf = self._elfs[int(elf_idx)][0] 351ae252462SJerome Forissier if elf is None: 352ae252462SJerome Forissier return '' 353ae252462SJerome Forissier self.read_sections(elf) 354ae252462SJerome Forissier if elf not in self._sections: 355ae252462SJerome Forissier return '' 356ae252462SJerome Forissier for s in self._sections[elf]: 35730999126SJerome Forissier if self.overlaps(s, iaddr, isize): 35830999126SJerome Forissier ret += ' ' + s[0] 35930999126SJerome Forissier return ret 36030999126SJerome Forissier 361733a15f2SJerome Forissier def reset(self): 362733a15f2SJerome Forissier self._call_stack_found = False 363733a15f2SJerome Forissier if self._addr2line: 364733a15f2SJerome Forissier self._addr2line.terminate() 365733a15f2SJerome Forissier self._addr2line = None 366ae252462SJerome Forissier self._addr2line_elf_name = None 367d720431cSJerome Forissier self._arch = None 368142c5cccSJerome Forissier self._saved_abort_line = '' 369ae252462SJerome Forissier self._sections = {} # {elf_name: [[name, addr, size], ...], ...} 370ae252462SJerome Forissier self._regions = [] # [[addr, size, elf_idx, saved line], ...] 371ae252462SJerome Forissier self._elfs = {0: ["tee.elf", 0]} # {idx: [uuid, load_addr], ...} 372*105e09c2SJerome Forissier self._tee_load_addr = 0x0 373c90b6663SSumit Garg self._func_graph_found = False 374c90b6663SSumit Garg self._func_graph_skip_line = True 375733a15f2SJerome Forissier 376095567e5SJerome Forissier def pretty_print_path(self, path): 377095567e5SJerome Forissier if self._strip_path: 378095567e5SJerome Forissier return re.sub(re.escape(self._strip_path) + '/*', '', path) 379095567e5SJerome Forissier return path 380095567e5SJerome Forissier 381733a15f2SJerome Forissier def write(self, line): 382733a15f2SJerome Forissier if self._call_stack_found: 383733a15f2SJerome Forissier match = re.search(STACK_ADDR_RE, line) 384733a15f2SJerome Forissier if match: 385733a15f2SJerome Forissier addr = match.group('addr') 386733a15f2SJerome Forissier pre = match.start('addr') 387733a15f2SJerome Forissier post = match.end('addr') 388733a15f2SJerome Forissier self._out.write(line[:pre]) 389733a15f2SJerome Forissier self._out.write(addr) 390733a15f2SJerome Forissier res = self.resolve(addr) 391095567e5SJerome Forissier res = self.pretty_print_path(res) 392733a15f2SJerome Forissier self._out.write(' ' + res) 393733a15f2SJerome Forissier self._out.write(line[post:]) 394733a15f2SJerome Forissier return 395733a15f2SJerome Forissier else: 396733a15f2SJerome Forissier self.reset() 397c90b6663SSumit Garg if self._func_graph_found: 398c90b6663SSumit Garg match = re.search(GRAPH_ADDR_RE, line) 399c90b6663SSumit Garg match_re = re.search(GRAPH_RE, line) 400c90b6663SSumit Garg if match: 401c90b6663SSumit Garg addr = match.group('addr') 402c90b6663SSumit Garg pre = match.start('addr') 403c90b6663SSumit Garg post = match.end('addr') 404c90b6663SSumit Garg self._out.write(line[:pre]) 405c90b6663SSumit Garg res = self.resolve(addr) 406c90b6663SSumit Garg res_arr = re.split(' ', res) 407c90b6663SSumit Garg self._out.write(res_arr[0]) 408c90b6663SSumit Garg self._out.write(line[post:]) 409c90b6663SSumit Garg self._func_graph_skip_line = False 410c90b6663SSumit Garg return 411c90b6663SSumit Garg elif match_re: 412c90b6663SSumit Garg self._out.write(line) 413c90b6663SSumit Garg return 414c90b6663SSumit Garg elif self._func_graph_skip_line: 415c90b6663SSumit Garg return 416c90b6663SSumit Garg else: 417c90b6663SSumit Garg self.reset() 41830999126SJerome Forissier match = re.search(REGION_RE, line) 41930999126SJerome Forissier if match: 420ae252462SJerome Forissier # Region table: save info for later processing once 421ae252462SJerome Forissier # we know which UUID corresponds to which ELF index 42230999126SJerome Forissier addr = match.group('addr') 42330999126SJerome Forissier size = match.group('size') 424ae252462SJerome Forissier elf_idx = match.group('elf_idx') 425ae252462SJerome Forissier self._regions.append([addr, size, elf_idx, line]) 426ae252462SJerome Forissier return 427ae252462SJerome Forissier match = re.search(ELF_LIST_RE, line) 428ae252462SJerome Forissier if match: 429ae252462SJerome Forissier # ELF list: save info for later. Region table and ELF list 430ae252462SJerome Forissier # will be displayed when the call stack is reached 431ae252462SJerome Forissier i = int(match.group('idx')) 432ae252462SJerome Forissier self._elfs[i] = [match.group('uuid'), match.group('load_addr'), 433ae252462SJerome Forissier line] 43430999126SJerome Forissier return 435*105e09c2SJerome Forissier match = re.search(TEE_LOAD_ADDR_RE, line) 436*105e09c2SJerome Forissier if match: 437*105e09c2SJerome Forissier self._tee_load_addr = match.group('load_addr') 438733a15f2SJerome Forissier match = re.search(CALL_STACK_RE, line) 439733a15f2SJerome Forissier if match: 440733a15f2SJerome Forissier self._call_stack_found = True 441ae252462SJerome Forissier if self._regions: 442ae252462SJerome Forissier for r in self._regions: 443ae252462SJerome Forissier r_addr = r[0] 444ae252462SJerome Forissier r_size = r[1] 445ae252462SJerome Forissier elf_idx = r[2] 446ae252462SJerome Forissier saved_line = r[3] 447ae252462SJerome Forissier if elf_idx is None: 448ae252462SJerome Forissier self._out.write(saved_line) 449ae252462SJerome Forissier else: 450ae252462SJerome Forissier self._out.write(saved_line.strip() + 451ae252462SJerome Forissier self.sections_in_region(r_addr, 452ae252462SJerome Forissier r_size, 453ae252462SJerome Forissier elf_idx) + 454ae252462SJerome Forissier '\n') 455ae252462SJerome Forissier if self._elfs: 456ae252462SJerome Forissier for k in self._elfs: 457ae252462SJerome Forissier e = self._elfs[k] 458ae252462SJerome Forissier if (len(e) >= 3): 4591e6f2ea0SJerome Forissier # TA executable or library 460095567e5SJerome Forissier self._out.write(e[2].strip()) 461095567e5SJerome Forissier elf = self.get_elf(e[0]) 462095567e5SJerome Forissier if elf: 463095567e5SJerome Forissier rpath = os.path.realpath(elf) 464095567e5SJerome Forissier path = self.pretty_print_path(rpath) 465095567e5SJerome Forissier self._out.write(' (' + path + ')') 466095567e5SJerome Forissier self._out.write('\n') 467142c5cccSJerome Forissier # Here is a good place to resolve the abort address because we 468142c5cccSJerome Forissier # have all the information we need 469142c5cccSJerome Forissier if self._saved_abort_line: 470142c5cccSJerome Forissier self._out.write(self.process_abort(self._saved_abort_line)) 471c90b6663SSumit Garg match = re.search(FUNC_GRAPH_RE, line) 472c90b6663SSumit Garg if match: 473c90b6663SSumit Garg self._func_graph_found = True 474142c5cccSJerome Forissier match = re.search(ABORT_ADDR_RE, line) 475142c5cccSJerome Forissier if match: 47627b83ad2SJerome Forissier self.reset() 477142c5cccSJerome Forissier # At this point the arch and TA load address are unknown. 478142c5cccSJerome Forissier # Save the line so We can translate the abort address later. 479142c5cccSJerome Forissier self._saved_abort_line = line 480733a15f2SJerome Forissier self._out.write(line) 481733a15f2SJerome Forissier 482733a15f2SJerome Forissier def flush(self): 483733a15f2SJerome Forissier self._out.flush() 484733a15f2SJerome Forissier 485ae252462SJerome Forissier 486733a15f2SJerome Forissierdef main(): 487733a15f2SJerome Forissier args = get_args() 488733a15f2SJerome Forissier if args.dir: 489733a15f2SJerome Forissier # Flatten list in case -d is used several times *and* with multiple 490733a15f2SJerome Forissier # arguments 491733a15f2SJerome Forissier args.dirs = [item for sublist in args.dir for item in sublist] 492733a15f2SJerome Forissier else: 493733a15f2SJerome Forissier args.dirs = [] 494733a15f2SJerome Forissier symbolizer = Symbolizer(sys.stdout, args.dirs, args.strip_path) 495733a15f2SJerome Forissier 4966b4fc675SJerome Forissier fd = sys.stdin.fileno() 49720d152b8SJerome Forissier isatty = os.isatty(fd) 49820d152b8SJerome Forissier if isatty: 4996b4fc675SJerome Forissier old = termios.tcgetattr(fd) 5006b4fc675SJerome Forissier new = termios.tcgetattr(fd) 5016b4fc675SJerome Forissier new[3] = new[3] & ~termios.ECHO # lflags 5026b4fc675SJerome Forissier try: 50320d152b8SJerome Forissier if isatty: 5046b4fc675SJerome Forissier termios.tcsetattr(fd, termios.TCSADRAIN, new) 505733a15f2SJerome Forissier for line in sys.stdin: 506733a15f2SJerome Forissier symbolizer.write(line) 5076b4fc675SJerome Forissier finally: 508733a15f2SJerome Forissier symbolizer.flush() 50920d152b8SJerome Forissier if isatty: 5106b4fc675SJerome Forissier termios.tcsetattr(fd, termios.TCSADRAIN, old) 511733a15f2SJerome Forissier 5121d8c2a48SJerome Forissier 513733a15f2SJerome Forissierif __name__ == "__main__": 514733a15f2SJerome Forissier main() 515