1733a15f2SJerome Forissier#!/usr/bin/env python 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 9733a15f2SJerome Forissierimport glob 10157e6213SJerome Forissierimport os 11733a15f2SJerome Forissierimport re 12733a15f2SJerome Forissierimport subprocess 13733a15f2SJerome Forissierimport sys 14733a15f2SJerome Forissier 15733a15f2SJerome ForissierCALL_STACK_RE = re.compile('Call stack:') 16a2b984bdSJoakim Bech# This gets the address from lines looking like this: 17a2b984bdSJoakim Bech# E/TC:0 0x001044a8 18a2b984bdSJoakim BechSTACK_ADDR_RE = re.compile(r'[UEIDFM]/T[AC]:.*(?P<addr>0x[0-9a-f]+)') 19142c5cccSJerome ForissierABORT_ADDR_RE = re.compile('-abort at address (?P<addr>0x[0-9a-f]+)') 2030999126SJerome ForissierREGION_RE = re.compile('region [0-9]+: va (?P<addr>0x[0-9a-f]+) ' 21ae252462SJerome Forissier 'pa 0x[0-9a-f]+ size (?P<size>0x[0-9a-f]+)' 22ae252462SJerome Forissier '( flags .{6} (\[(?P<elf_idx>[0-9]+)\])?)?') 23ae252462SJerome ForissierELF_LIST_RE = re.compile(r'\[(?P<idx>[0-9]+)\] (?P<uuid>[0-9a-f\-]+)' 24ae252462SJerome Forissier ' @ (?P<load_addr>0x[0-9a-f\-]+)') 25733a15f2SJerome Forissier 26733a15f2SJerome Forissierepilog = ''' 270c5bedb5SJerome ForissierThis scripts reads an OP-TEE abort or panic message from stdin and adds debug 280c5bedb5SJerome Forissierinformation to the output, such as '<function> at <file>:<line>' next to each 290c5bedb5SJerome Forissieraddress in the call stack. Any message generated by OP-TEE and containing a 300c5bedb5SJerome Forissiercall stack can in principle be processed by this script. This currently 310c5bedb5SJerome Forissierincludes aborts and panics from the TEE core as well as from any TA. 320c5bedb5SJerome ForissierThe paths provided on the command line are used to locate the appropriate ELF 330c5bedb5SJerome Forissierbinary (tee.elf or Trusted Application). The GNU binutils (addr2line, objdump, 34*f9089765SJerome Forissiernm) are used to extract the debug info. If the CROSS_COMPILE environment 35*f9089765SJerome Forissiervariable is set, it is used as a prefix to the binutils tools. That is, the 36*f9089765SJerome Forissierscript will invoke $(CROSS_COMPILE)addr2line etc. If it is not set however, 37*f9089765SJerome Forissierthe prefix will be determined automatically for each ELF file based on its 38*f9089765SJerome Forissierarchitecture (arm-linux-gnueabihf-, aarch64-linux-gnu-). The resulting command 39*f9089765SJerome Forissieris then expected to be found in the user's PATH. 40733a15f2SJerome Forissier 410c5bedb5SJerome ForissierOP-TEE abort and panic messages are sent to the secure console. They look like 420c5bedb5SJerome Forissierthe following: 43733a15f2SJerome Forissier 440c5bedb5SJerome Forissier E/TC:0 User TA data-abort at address 0xffffdecd (alignment fault) 45733a15f2SJerome Forissier ... 460c5bedb5SJerome Forissier E/TC:0 Call stack: 470c5bedb5SJerome Forissier E/TC:0 0x4000549e 480c5bedb5SJerome Forissier E/TC:0 0x40001f4b 490c5bedb5SJerome Forissier E/TC:0 0x4000273f 500c5bedb5SJerome Forissier E/TC:0 0x40005da7 51733a15f2SJerome Forissier 52733a15f2SJerome ForissierInspired by a script of the same name by the Chromium project. 53733a15f2SJerome Forissier 54733a15f2SJerome ForissierSample usage: 55733a15f2SJerome Forissier 56733a15f2SJerome Forissier $ scripts/symbolize.py -d out/arm-plat-hikey/core -d ../optee_test/out/ta/* 57733a15f2SJerome Forissier <paste whole dump here> 58733a15f2SJerome Forissier ^D 59733a15f2SJerome Forissier''' 60733a15f2SJerome Forissier 61ae252462SJerome Forissier 62733a15f2SJerome Forissierdef get_args(): 63733a15f2SJerome Forissier parser = argparse.ArgumentParser( 64733a15f2SJerome Forissier formatter_class=argparse.RawDescriptionHelpFormatter, 65733a15f2SJerome Forissier description='Symbolizes OP-TEE abort dumps', 66733a15f2SJerome Forissier epilog=epilog) 67733a15f2SJerome Forissier parser.add_argument('-d', '--dir', action='append', nargs='+', 681d8c2a48SJerome Forissier help='Search for ELF file in DIR. tee.elf is needed ' 691d8c2a48SJerome Forissier 'to decode a TEE Core or pseudo-TA abort, while ' 701d8c2a48SJerome Forissier '<TA_uuid>.elf is required if a user-mode TA has ' 711d8c2a48SJerome Forissier 'crashed. For convenience, ELF files may also be ' 721d8c2a48SJerome Forissier 'given.') 735f7df507SJerome Forissier parser.add_argument('-s', '--strip_path', nargs='?', 741d8c2a48SJerome Forissier help='Strip STRIP_PATH from file paths (default: ' 751d8c2a48SJerome Forissier 'current directory, use -s with no argument to show ' 761d8c2a48SJerome Forissier 'full paths)', default=os.getcwd()) 77733a15f2SJerome Forissier 78733a15f2SJerome Forissier return parser.parse_args() 79733a15f2SJerome Forissier 80ae252462SJerome Forissier 81733a15f2SJerome Forissierclass Symbolizer(object): 82733a15f2SJerome Forissier def __init__(self, out, dirs, strip_path): 83733a15f2SJerome Forissier self._out = out 84733a15f2SJerome Forissier self._dirs = dirs 85733a15f2SJerome Forissier self._strip_path = strip_path 86733a15f2SJerome Forissier self._addr2line = None 87733a15f2SJerome Forissier self.reset() 88733a15f2SJerome Forissier 891cbf777bSJerome Forissier def my_Popen(self, cmd): 901cbf777bSJerome Forissier try: 911cbf777bSJerome Forissier return subprocess.Popen(cmd, stdin=subprocess.PIPE, 921cbf777bSJerome Forissier stdout=subprocess.PIPE) 931cbf777bSJerome Forissier except OSError as e: 941cbf777bSJerome Forissier if e.errno == os.errno.ENOENT: 951cbf777bSJerome Forissier print >> sys.stderr, "*** Error:", cmd[0] + \ 961cbf777bSJerome Forissier ": command not found" 971cbf777bSJerome Forissier sys.exit(1) 981cbf777bSJerome Forissier 99733a15f2SJerome Forissier def get_elf(self, elf_or_uuid): 100733a15f2SJerome Forissier if not elf_or_uuid.endswith('.elf'): 101733a15f2SJerome Forissier elf_or_uuid += '.elf' 102733a15f2SJerome Forissier for d in self._dirs: 103157e6213SJerome Forissier if d.endswith(elf_or_uuid) and os.path.isfile(d): 104157e6213SJerome Forissier return d 105733a15f2SJerome Forissier elf = glob.glob(d + '/' + elf_or_uuid) 106733a15f2SJerome Forissier if elf: 107733a15f2SJerome Forissier return elf[0] 108733a15f2SJerome Forissier 109d720431cSJerome Forissier def set_arch(self): 110d720431cSJerome Forissier if self._arch: 111d720431cSJerome Forissier return 1128a6d4a8bSEtienne Carriere self._arch = os.getenv('CROSS_COMPILE'); 1138a6d4a8bSEtienne Carriere if self._arch: 1148a6d4a8bSEtienne Carriere return 115ae252462SJerome Forissier elf = self.get_elf(self._elfs[0][0]) 116ae252462SJerome Forissier if elf is None: 117ae252462SJerome Forissier return 118ae252462SJerome Forissier p = subprocess.Popen(['file', self.get_elf(self._elfs[0][0])], 119d720431cSJerome Forissier stdout=subprocess.PIPE) 120d720431cSJerome Forissier output = p.stdout.readlines() 121d720431cSJerome Forissier p.terminate() 122d720431cSJerome Forissier if 'ARM aarch64,' in output[0]: 123d720431cSJerome Forissier self._arch = 'aarch64-linux-gnu-' 124d720431cSJerome Forissier elif 'ARM,' in output[0]: 125d720431cSJerome Forissier self._arch = 'arm-linux-gnueabihf-' 126d720431cSJerome Forissier 127142c5cccSJerome Forissier def arch_prefix(self, cmd): 128d720431cSJerome Forissier self.set_arch() 129ae252462SJerome Forissier if self._arch is None: 130ae252462SJerome Forissier return '' 131d720431cSJerome Forissier return self._arch + cmd 132142c5cccSJerome Forissier 133ae252462SJerome Forissier def spawn_addr2line(self, elf_name): 134ae252462SJerome Forissier if elf_name is None: 135ae252462SJerome Forissier return 136ae252462SJerome Forissier if self._addr2line_elf_name is elf_name: 137ae252462SJerome Forissier return 138ae252462SJerome Forissier if self._addr2line: 139ae252462SJerome Forissier self._addr2line.terminate 140ae252462SJerome Forissier self._addr2line = None 141ae252462SJerome Forissier elf = self.get_elf(elf_name) 142733a15f2SJerome Forissier if not elf: 143733a15f2SJerome Forissier return 144142c5cccSJerome Forissier cmd = self.arch_prefix('addr2line') 145142c5cccSJerome Forissier if not cmd: 146733a15f2SJerome Forissier return 1471cbf777bSJerome Forissier self._addr2line = self.my_Popen([cmd, '-f', '-p', '-e', elf]) 148ae252462SJerome Forissier self._addr2line_elf_name = elf_name 149ae252462SJerome Forissier 150ae252462SJerome Forissier # If addr falls into a region that maps a TA ELF file, return the load 151ae252462SJerome Forissier # address of that file. 152ae252462SJerome Forissier def elf_load_addr(self, addr): 153ae252462SJerome Forissier if self._regions: 154ae252462SJerome Forissier for r in self._regions: 155ae252462SJerome Forissier r_addr = int(r[0], 16) 156ae252462SJerome Forissier r_size = int(r[1], 16) 157ae252462SJerome Forissier i_addr = int(addr, 16) 158ae252462SJerome Forissier if (i_addr >= r_addr and i_addr < (r_addr + r_size)): 159ae252462SJerome Forissier # Found region 160ae252462SJerome Forissier elf_idx = r[2] 161ae252462SJerome Forissier if elf_idx is not None: 162ae252462SJerome Forissier return self._elfs[int(elf_idx)][1] 163ae252462SJerome Forissier return None 164ae252462SJerome Forissier else: 165ae252462SJerome Forissier # tee.elf 166ae252462SJerome Forissier return '0x0' 167ae252462SJerome Forissier 168ae252462SJerome Forissier def elf_for_addr(self, addr): 169ae252462SJerome Forissier l_addr = self.elf_load_addr(addr) 170ae252462SJerome Forissier if l_addr is None: 171ae252462SJerome Forissier return None 172ae252462SJerome Forissier if l_addr is '0x0': 173ae252462SJerome Forissier return 'tee.elf' 174ae252462SJerome Forissier for k in self._elfs: 175ae252462SJerome Forissier e = self._elfs[k] 176ae252462SJerome Forissier if int(e[1], 16) == int(l_addr, 16): 177ae252462SJerome Forissier return e[0] 178ae252462SJerome Forissier return None 179733a15f2SJerome Forissier 180142c5cccSJerome Forissier def subtract_load_addr(self, addr): 181ae252462SJerome Forissier l_addr = self.elf_load_addr(addr) 182ae252462SJerome Forissier if l_addr is None: 183ae252462SJerome Forissier return None 184ae252462SJerome Forissier if int(l_addr, 16) > int(addr, 16): 185142c5cccSJerome Forissier return '' 186ae252462SJerome Forissier return '0x{:x}'.format(int(addr, 16) - int(l_addr, 16)) 187142c5cccSJerome Forissier 188142c5cccSJerome Forissier def resolve(self, addr): 189142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 190ae252462SJerome Forissier self.spawn_addr2line(self.elf_for_addr(addr)) 191142c5cccSJerome Forissier if not reladdr or not self._addr2line: 192733a15f2SJerome Forissier return '???' 193733a15f2SJerome Forissier try: 194733a15f2SJerome Forissier print >> self._addr2line.stdin, reladdr 195733a15f2SJerome Forissier ret = self._addr2line.stdout.readline().rstrip('\n') 196733a15f2SJerome Forissier except IOError: 197733a15f2SJerome Forissier ret = '!!!' 198733a15f2SJerome Forissier return ret 199733a15f2SJerome Forissier 200142c5cccSJerome Forissier def symbol_plus_offset(self, addr): 201142c5cccSJerome Forissier ret = '' 202142c5cccSJerome Forissier prevsize = 0 203142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 204ae252462SJerome Forissier elf_name = self.elf_for_addr(addr) 205ae252462SJerome Forissier if elf_name is None: 206ae252462SJerome Forissier return '' 207ae252462SJerome Forissier elf = self.get_elf(elf_name) 208142c5cccSJerome Forissier cmd = self.arch_prefix('nm') 209142c5cccSJerome Forissier if not reladdr or not elf or not cmd: 210142c5cccSJerome Forissier return '' 21130999126SJerome Forissier ireladdr = int(reladdr, 16) 2121cbf777bSJerome Forissier nm = self.my_Popen([cmd, '--numeric-sort', '--print-size', elf]) 213142c5cccSJerome Forissier for line in iter(nm.stdout.readline, ''): 214142c5cccSJerome Forissier try: 215142c5cccSJerome Forissier addr, size, _, name = line.split() 2161d8c2a48SJerome Forissier except ValueError: 217142c5cccSJerome Forissier # Size is missing 218b4815427SJerome Forissier try: 219142c5cccSJerome Forissier addr, _, name = line.split() 220142c5cccSJerome Forissier size = '0' 2211d8c2a48SJerome Forissier except ValueError: 222b4815427SJerome Forissier # E.g., undefined (external) symbols (line = "U symbol") 223b4815427SJerome Forissier continue 224142c5cccSJerome Forissier iaddr = int(addr, 16) 225142c5cccSJerome Forissier isize = int(size, 16) 226142c5cccSJerome Forissier if iaddr == ireladdr: 227142c5cccSJerome Forissier ret = name 228142c5cccSJerome Forissier break 229142c5cccSJerome Forissier if iaddr < ireladdr and iaddr + isize >= ireladdr: 230142c5cccSJerome Forissier offs = ireladdr - iaddr 231142c5cccSJerome Forissier ret = name + '+' + str(offs) 232142c5cccSJerome Forissier break 233142c5cccSJerome Forissier if iaddr > ireladdr and prevsize == 0: 234142c5cccSJerome Forissier offs = iaddr + ireladdr 235142c5cccSJerome Forissier ret = prevname + '+' + str(offs) 236142c5cccSJerome Forissier break 237142c5cccSJerome Forissier prevsize = size 238142c5cccSJerome Forissier prevname = name 239142c5cccSJerome Forissier nm.terminate() 240142c5cccSJerome Forissier return ret 241142c5cccSJerome Forissier 242142c5cccSJerome Forissier def section_plus_offset(self, addr): 243142c5cccSJerome Forissier ret = '' 244142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 245ae252462SJerome Forissier elf_name = self.elf_for_addr(addr) 246ae252462SJerome Forissier if elf_name is None: 247ae252462SJerome Forissier return '' 248ae252462SJerome Forissier elf = self.get_elf(elf_name) 249142c5cccSJerome Forissier cmd = self.arch_prefix('objdump') 250142c5cccSJerome Forissier if not reladdr or not elf or not cmd: 251142c5cccSJerome Forissier return '' 25230999126SJerome Forissier iaddr = int(reladdr, 16) 2531cbf777bSJerome Forissier objdump = self.my_Popen([cmd, '--section-headers', elf]) 254142c5cccSJerome Forissier for line in iter(objdump.stdout.readline, ''): 255142c5cccSJerome Forissier try: 256142c5cccSJerome Forissier idx, name, size, vma, lma, offs, algn = line.split() 2571d8c2a48SJerome Forissier except ValueError: 258ae252462SJerome Forissier continue 259142c5cccSJerome Forissier ivma = int(vma, 16) 260142c5cccSJerome Forissier isize = int(size, 16) 261142c5cccSJerome Forissier if ivma == iaddr: 262142c5cccSJerome Forissier ret = name 263142c5cccSJerome Forissier break 264142c5cccSJerome Forissier if ivma < iaddr and ivma + isize >= iaddr: 265142c5cccSJerome Forissier offs = iaddr - ivma 266142c5cccSJerome Forissier ret = name + '+' + str(offs) 267142c5cccSJerome Forissier break 268142c5cccSJerome Forissier objdump.terminate() 269142c5cccSJerome Forissier return ret 270142c5cccSJerome Forissier 271142c5cccSJerome Forissier def process_abort(self, line): 272142c5cccSJerome Forissier ret = '' 273142c5cccSJerome Forissier match = re.search(ABORT_ADDR_RE, line) 274142c5cccSJerome Forissier addr = match.group('addr') 275142c5cccSJerome Forissier pre = match.start('addr') 276142c5cccSJerome Forissier post = match.end('addr') 277142c5cccSJerome Forissier sym = self.symbol_plus_offset(addr) 278142c5cccSJerome Forissier sec = self.section_plus_offset(addr) 279142c5cccSJerome Forissier if sym or sec: 280142c5cccSJerome Forissier ret += line[:pre] 281142c5cccSJerome Forissier ret += addr 282142c5cccSJerome Forissier if sym: 283142c5cccSJerome Forissier ret += ' ' + sym 284142c5cccSJerome Forissier if sec: 285142c5cccSJerome Forissier ret += ' ' + sec 286142c5cccSJerome Forissier ret += line[post:] 287142c5cccSJerome Forissier return ret 288142c5cccSJerome Forissier 28930999126SJerome Forissier # Return all ELF sections with the ALLOC flag 290ae252462SJerome Forissier def read_sections(self, elf_name): 291ae252462SJerome Forissier if elf_name is None: 29230999126SJerome Forissier return 293ae252462SJerome Forissier if elf_name in self._sections: 294ae252462SJerome Forissier return 295ae252462SJerome Forissier elf = self.get_elf(elf_name) 29630999126SJerome Forissier cmd = self.arch_prefix('objdump') 29730999126SJerome Forissier if not elf or not cmd: 29830999126SJerome Forissier return 299ae252462SJerome Forissier self._sections[elf_name] = [] 3001cbf777bSJerome Forissier objdump = self.my_Popen([cmd, '--section-headers', elf]) 30130999126SJerome Forissier for line in iter(objdump.stdout.readline, ''): 30230999126SJerome Forissier try: 30330999126SJerome Forissier _, name, size, vma, _, _, _ = line.split() 3041d8c2a48SJerome Forissier except ValueError: 30530999126SJerome Forissier if 'ALLOC' in line: 306ae252462SJerome Forissier self._sections[elf_name].append([name, int(vma, 16), 307ae252462SJerome Forissier int(size, 16)]) 30830999126SJerome Forissier 30930999126SJerome Forissier def overlaps(self, section, addr, size): 31030999126SJerome Forissier sec_addr = section[1] 31130999126SJerome Forissier sec_size = section[2] 31230999126SJerome Forissier if not size or not sec_size: 31330999126SJerome Forissier return False 314ae252462SJerome Forissier return ((addr <= (sec_addr + sec_size - 1)) and 315ae252462SJerome Forissier ((addr + size - 1) >= sec_addr)) 31630999126SJerome Forissier 317ae252462SJerome Forissier def sections_in_region(self, addr, size, elf_idx): 31830999126SJerome Forissier ret = '' 31930999126SJerome Forissier addr = self.subtract_load_addr(addr) 32030999126SJerome Forissier if not addr: 32130999126SJerome Forissier return '' 32230999126SJerome Forissier iaddr = int(addr, 16) 32330999126SJerome Forissier isize = int(size, 16) 324ae252462SJerome Forissier elf = self._elfs[int(elf_idx)][0] 325ae252462SJerome Forissier if elf is None: 326ae252462SJerome Forissier return '' 327ae252462SJerome Forissier self.read_sections(elf) 328ae252462SJerome Forissier if elf not in self._sections: 329ae252462SJerome Forissier return '' 330ae252462SJerome Forissier for s in self._sections[elf]: 33130999126SJerome Forissier if self.overlaps(s, iaddr, isize): 33230999126SJerome Forissier ret += ' ' + s[0] 33330999126SJerome Forissier return ret 33430999126SJerome Forissier 335733a15f2SJerome Forissier def reset(self): 336733a15f2SJerome Forissier self._call_stack_found = False 337733a15f2SJerome Forissier if self._addr2line: 338733a15f2SJerome Forissier self._addr2line.terminate() 339733a15f2SJerome Forissier self._addr2line = None 340ae252462SJerome Forissier self._addr2line_elf_name = None 341d720431cSJerome Forissier self._arch = None 342142c5cccSJerome Forissier self._saved_abort_line = '' 343ae252462SJerome Forissier self._sections = {} # {elf_name: [[name, addr, size], ...], ...} 344ae252462SJerome Forissier self._regions = [] # [[addr, size, elf_idx, saved line], ...] 345ae252462SJerome Forissier self._elfs = {0: ["tee.elf", 0]} # {idx: [uuid, load_addr], ...} 346733a15f2SJerome Forissier 347095567e5SJerome Forissier def pretty_print_path(self, path): 348095567e5SJerome Forissier if self._strip_path: 349095567e5SJerome Forissier return re.sub(re.escape(self._strip_path) + '/*', '', path) 350095567e5SJerome Forissier return path 351095567e5SJerome Forissier 352733a15f2SJerome Forissier def write(self, line): 353733a15f2SJerome Forissier if self._call_stack_found: 354733a15f2SJerome Forissier match = re.search(STACK_ADDR_RE, line) 355733a15f2SJerome Forissier if match: 356733a15f2SJerome Forissier addr = match.group('addr') 357733a15f2SJerome Forissier pre = match.start('addr') 358733a15f2SJerome Forissier post = match.end('addr') 359733a15f2SJerome Forissier self._out.write(line[:pre]) 360733a15f2SJerome Forissier self._out.write(addr) 361733a15f2SJerome Forissier res = self.resolve(addr) 362095567e5SJerome Forissier res = self.pretty_print_path(res) 363733a15f2SJerome Forissier self._out.write(' ' + res) 364733a15f2SJerome Forissier self._out.write(line[post:]) 365733a15f2SJerome Forissier return 366733a15f2SJerome Forissier else: 367733a15f2SJerome Forissier self.reset() 36830999126SJerome Forissier match = re.search(REGION_RE, line) 36930999126SJerome Forissier if match: 370ae252462SJerome Forissier # Region table: save info for later processing once 371ae252462SJerome Forissier # we know which UUID corresponds to which ELF index 37230999126SJerome Forissier addr = match.group('addr') 37330999126SJerome Forissier size = match.group('size') 374ae252462SJerome Forissier elf_idx = match.group('elf_idx') 375ae252462SJerome Forissier self._regions.append([addr, size, elf_idx, line]) 376ae252462SJerome Forissier return 377ae252462SJerome Forissier match = re.search(ELF_LIST_RE, line) 378ae252462SJerome Forissier if match: 379ae252462SJerome Forissier # ELF list: save info for later. Region table and ELF list 380ae252462SJerome Forissier # will be displayed when the call stack is reached 381ae252462SJerome Forissier i = int(match.group('idx')) 382ae252462SJerome Forissier self._elfs[i] = [match.group('uuid'), match.group('load_addr'), 383ae252462SJerome Forissier line] 38430999126SJerome Forissier return 385733a15f2SJerome Forissier match = re.search(CALL_STACK_RE, line) 386733a15f2SJerome Forissier if match: 387733a15f2SJerome Forissier self._call_stack_found = True 388ae252462SJerome Forissier if self._regions: 389ae252462SJerome Forissier for r in self._regions: 390ae252462SJerome Forissier r_addr = r[0] 391ae252462SJerome Forissier r_size = r[1] 392ae252462SJerome Forissier elf_idx = r[2] 393ae252462SJerome Forissier saved_line = r[3] 394ae252462SJerome Forissier if elf_idx is None: 395ae252462SJerome Forissier self._out.write(saved_line) 396ae252462SJerome Forissier else: 397ae252462SJerome Forissier self._out.write(saved_line.strip() + 398ae252462SJerome Forissier self.sections_in_region(r_addr, 399ae252462SJerome Forissier r_size, 400ae252462SJerome Forissier elf_idx) + 401ae252462SJerome Forissier '\n') 402ae252462SJerome Forissier if self._elfs: 403ae252462SJerome Forissier for k in self._elfs: 404ae252462SJerome Forissier e = self._elfs[k] 405ae252462SJerome Forissier if (len(e) >= 3): 4061e6f2ea0SJerome Forissier # TA executable or library 407095567e5SJerome Forissier self._out.write(e[2].strip()) 408095567e5SJerome Forissier elf = self.get_elf(e[0]) 409095567e5SJerome Forissier if elf: 410095567e5SJerome Forissier rpath = os.path.realpath(elf) 411095567e5SJerome Forissier path = self.pretty_print_path(rpath) 412095567e5SJerome Forissier self._out.write(' (' + path + ')') 413095567e5SJerome Forissier self._out.write('\n') 414142c5cccSJerome Forissier # Here is a good place to resolve the abort address because we 415142c5cccSJerome Forissier # have all the information we need 416142c5cccSJerome Forissier if self._saved_abort_line: 417142c5cccSJerome Forissier self._out.write(self.process_abort(self._saved_abort_line)) 418142c5cccSJerome Forissier match = re.search(ABORT_ADDR_RE, line) 419142c5cccSJerome Forissier if match: 42027b83ad2SJerome Forissier self.reset() 421142c5cccSJerome Forissier # At this point the arch and TA load address are unknown. 422142c5cccSJerome Forissier # Save the line so We can translate the abort address later. 423142c5cccSJerome Forissier self._saved_abort_line = line 424733a15f2SJerome Forissier self._out.write(line) 425733a15f2SJerome Forissier 426733a15f2SJerome Forissier def flush(self): 427733a15f2SJerome Forissier self._out.flush() 428733a15f2SJerome Forissier 429ae252462SJerome Forissier 430733a15f2SJerome Forissierdef main(): 431733a15f2SJerome Forissier args = get_args() 432733a15f2SJerome Forissier if args.dir: 433733a15f2SJerome Forissier # Flatten list in case -d is used several times *and* with multiple 434733a15f2SJerome Forissier # arguments 435733a15f2SJerome Forissier args.dirs = [item for sublist in args.dir for item in sublist] 436733a15f2SJerome Forissier else: 437733a15f2SJerome Forissier args.dirs = [] 438733a15f2SJerome Forissier symbolizer = Symbolizer(sys.stdout, args.dirs, args.strip_path) 439733a15f2SJerome Forissier 440733a15f2SJerome Forissier for line in sys.stdin: 441733a15f2SJerome Forissier symbolizer.write(line) 442733a15f2SJerome Forissier symbolizer.flush() 443733a15f2SJerome Forissier 4441d8c2a48SJerome Forissier 445733a15f2SJerome Forissierif __name__ == "__main__": 446733a15f2SJerome Forissier main() 447