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, 340c5bedb5SJerome Forissiernm) are used to extract the debug info. 35733a15f2SJerome Forissier 360c5bedb5SJerome ForissierOP-TEE abort and panic messages are sent to the secure console. They look like 370c5bedb5SJerome Forissierthe following: 38733a15f2SJerome Forissier 390c5bedb5SJerome Forissier E/TC:0 User TA data-abort at address 0xffffdecd (alignment fault) 40733a15f2SJerome Forissier ... 410c5bedb5SJerome Forissier E/TC:0 Call stack: 420c5bedb5SJerome Forissier E/TC:0 0x4000549e 430c5bedb5SJerome Forissier E/TC:0 0x40001f4b 440c5bedb5SJerome Forissier E/TC:0 0x4000273f 450c5bedb5SJerome Forissier E/TC:0 0x40005da7 46733a15f2SJerome Forissier 47733a15f2SJerome ForissierInspired by a script of the same name by the Chromium project. 48733a15f2SJerome Forissier 49733a15f2SJerome ForissierSample usage: 50733a15f2SJerome Forissier 51733a15f2SJerome Forissier $ scripts/symbolize.py -d out/arm-plat-hikey/core -d ../optee_test/out/ta/* 52733a15f2SJerome Forissier <paste whole dump here> 53733a15f2SJerome Forissier ^D 54733a15f2SJerome Forissier''' 55733a15f2SJerome Forissier 56ae252462SJerome Forissier 57733a15f2SJerome Forissierdef get_args(): 58733a15f2SJerome Forissier parser = argparse.ArgumentParser( 59733a15f2SJerome Forissier formatter_class=argparse.RawDescriptionHelpFormatter, 60733a15f2SJerome Forissier description='Symbolizes OP-TEE abort dumps', 61733a15f2SJerome Forissier epilog=epilog) 62733a15f2SJerome Forissier parser.add_argument('-d', '--dir', action='append', nargs='+', 631d8c2a48SJerome Forissier help='Search for ELF file in DIR. tee.elf is needed ' 641d8c2a48SJerome Forissier 'to decode a TEE Core or pseudo-TA abort, while ' 651d8c2a48SJerome Forissier '<TA_uuid>.elf is required if a user-mode TA has ' 661d8c2a48SJerome Forissier 'crashed. For convenience, ELF files may also be ' 671d8c2a48SJerome Forissier 'given.') 685f7df507SJerome Forissier parser.add_argument('-s', '--strip_path', nargs='?', 691d8c2a48SJerome Forissier help='Strip STRIP_PATH from file paths (default: ' 701d8c2a48SJerome Forissier 'current directory, use -s with no argument to show ' 711d8c2a48SJerome Forissier 'full paths)', default=os.getcwd()) 72733a15f2SJerome Forissier 73733a15f2SJerome Forissier return parser.parse_args() 74733a15f2SJerome Forissier 75ae252462SJerome Forissier 76733a15f2SJerome Forissierclass Symbolizer(object): 77733a15f2SJerome Forissier def __init__(self, out, dirs, strip_path): 78733a15f2SJerome Forissier self._out = out 79733a15f2SJerome Forissier self._dirs = dirs 80733a15f2SJerome Forissier self._strip_path = strip_path 81733a15f2SJerome Forissier self._addr2line = None 82733a15f2SJerome Forissier self.reset() 83733a15f2SJerome Forissier 84*1cbf777bSJerome Forissier def my_Popen(self, cmd): 85*1cbf777bSJerome Forissier try: 86*1cbf777bSJerome Forissier return subprocess.Popen(cmd, stdin=subprocess.PIPE, 87*1cbf777bSJerome Forissier stdout=subprocess.PIPE) 88*1cbf777bSJerome Forissier except OSError as e: 89*1cbf777bSJerome Forissier if e.errno == os.errno.ENOENT: 90*1cbf777bSJerome Forissier print >> sys.stderr, "*** Error:", cmd[0] + \ 91*1cbf777bSJerome Forissier ": command not found" 92*1cbf777bSJerome Forissier sys.exit(1) 93*1cbf777bSJerome Forissier 94733a15f2SJerome Forissier def get_elf(self, elf_or_uuid): 95733a15f2SJerome Forissier if not elf_or_uuid.endswith('.elf'): 96733a15f2SJerome Forissier elf_or_uuid += '.elf' 97733a15f2SJerome Forissier for d in self._dirs: 98157e6213SJerome Forissier if d.endswith(elf_or_uuid) and os.path.isfile(d): 99157e6213SJerome Forissier return d 100733a15f2SJerome Forissier elf = glob.glob(d + '/' + elf_or_uuid) 101733a15f2SJerome Forissier if elf: 102733a15f2SJerome Forissier return elf[0] 103733a15f2SJerome Forissier 104d720431cSJerome Forissier def set_arch(self): 105d720431cSJerome Forissier if self._arch: 106d720431cSJerome Forissier return 107ae252462SJerome Forissier elf = self.get_elf(self._elfs[0][0]) 108ae252462SJerome Forissier if elf is None: 109ae252462SJerome Forissier return 110ae252462SJerome Forissier p = subprocess.Popen(['file', self.get_elf(self._elfs[0][0])], 111d720431cSJerome Forissier stdout=subprocess.PIPE) 112d720431cSJerome Forissier output = p.stdout.readlines() 113d720431cSJerome Forissier p.terminate() 114d720431cSJerome Forissier if 'ARM aarch64,' in output[0]: 115d720431cSJerome Forissier self._arch = 'aarch64-linux-gnu-' 116d720431cSJerome Forissier elif 'ARM,' in output[0]: 117d720431cSJerome Forissier self._arch = 'arm-linux-gnueabihf-' 118d720431cSJerome Forissier 119142c5cccSJerome Forissier def arch_prefix(self, cmd): 120d720431cSJerome Forissier self.set_arch() 121ae252462SJerome Forissier if self._arch is None: 122ae252462SJerome Forissier return '' 123d720431cSJerome Forissier return self._arch + cmd 124142c5cccSJerome Forissier 125ae252462SJerome Forissier def spawn_addr2line(self, elf_name): 126ae252462SJerome Forissier if elf_name is None: 127ae252462SJerome Forissier return 128ae252462SJerome Forissier if self._addr2line_elf_name is elf_name: 129ae252462SJerome Forissier return 130ae252462SJerome Forissier if self._addr2line: 131ae252462SJerome Forissier self._addr2line.terminate 132ae252462SJerome Forissier self._addr2line = None 133ae252462SJerome Forissier elf = self.get_elf(elf_name) 134733a15f2SJerome Forissier if not elf: 135733a15f2SJerome Forissier return 136142c5cccSJerome Forissier cmd = self.arch_prefix('addr2line') 137142c5cccSJerome Forissier if not cmd: 138733a15f2SJerome Forissier return 139*1cbf777bSJerome Forissier self._addr2line = self.my_Popen([cmd, '-f', '-p', '-e', elf]) 140ae252462SJerome Forissier self._addr2line_elf_name = elf_name 141ae252462SJerome Forissier 142ae252462SJerome Forissier # If addr falls into a region that maps a TA ELF file, return the load 143ae252462SJerome Forissier # address of that file. 144ae252462SJerome Forissier def elf_load_addr(self, addr): 145ae252462SJerome Forissier if self._regions: 146ae252462SJerome Forissier for r in self._regions: 147ae252462SJerome Forissier r_addr = int(r[0], 16) 148ae252462SJerome Forissier r_size = int(r[1], 16) 149ae252462SJerome Forissier i_addr = int(addr, 16) 150ae252462SJerome Forissier if (i_addr >= r_addr and i_addr < (r_addr + r_size)): 151ae252462SJerome Forissier # Found region 152ae252462SJerome Forissier elf_idx = r[2] 153ae252462SJerome Forissier if elf_idx is not None: 154ae252462SJerome Forissier return self._elfs[int(elf_idx)][1] 155ae252462SJerome Forissier return None 156ae252462SJerome Forissier else: 157ae252462SJerome Forissier # tee.elf 158ae252462SJerome Forissier return '0x0' 159ae252462SJerome Forissier 160ae252462SJerome Forissier def elf_for_addr(self, addr): 161ae252462SJerome Forissier l_addr = self.elf_load_addr(addr) 162ae252462SJerome Forissier if l_addr is None: 163ae252462SJerome Forissier return None 164ae252462SJerome Forissier if l_addr is '0x0': 165ae252462SJerome Forissier return 'tee.elf' 166ae252462SJerome Forissier for k in self._elfs: 167ae252462SJerome Forissier e = self._elfs[k] 168ae252462SJerome Forissier if int(e[1], 16) == int(l_addr, 16): 169ae252462SJerome Forissier return e[0] 170ae252462SJerome Forissier return None 171733a15f2SJerome Forissier 172142c5cccSJerome Forissier def subtract_load_addr(self, addr): 173ae252462SJerome Forissier l_addr = self.elf_load_addr(addr) 174ae252462SJerome Forissier if l_addr is None: 175ae252462SJerome Forissier return None 176ae252462SJerome Forissier if int(l_addr, 16) > int(addr, 16): 177142c5cccSJerome Forissier return '' 178ae252462SJerome Forissier return '0x{:x}'.format(int(addr, 16) - int(l_addr, 16)) 179142c5cccSJerome Forissier 180142c5cccSJerome Forissier def resolve(self, addr): 181142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 182ae252462SJerome Forissier self.spawn_addr2line(self.elf_for_addr(addr)) 183142c5cccSJerome Forissier if not reladdr or not self._addr2line: 184733a15f2SJerome Forissier return '???' 185733a15f2SJerome Forissier try: 186733a15f2SJerome Forissier print >> self._addr2line.stdin, reladdr 187733a15f2SJerome Forissier ret = self._addr2line.stdout.readline().rstrip('\n') 188733a15f2SJerome Forissier except IOError: 189733a15f2SJerome Forissier ret = '!!!' 190733a15f2SJerome Forissier return ret 191733a15f2SJerome Forissier 192142c5cccSJerome Forissier def symbol_plus_offset(self, addr): 193142c5cccSJerome Forissier ret = '' 194142c5cccSJerome Forissier prevsize = 0 195142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 196ae252462SJerome Forissier elf_name = self.elf_for_addr(addr) 197ae252462SJerome Forissier if elf_name is None: 198ae252462SJerome Forissier return '' 199ae252462SJerome Forissier elf = self.get_elf(elf_name) 200142c5cccSJerome Forissier cmd = self.arch_prefix('nm') 201142c5cccSJerome Forissier if not reladdr or not elf or not cmd: 202142c5cccSJerome Forissier return '' 20330999126SJerome Forissier ireladdr = int(reladdr, 16) 204*1cbf777bSJerome Forissier nm = self.my_Popen([cmd, '--numeric-sort', '--print-size', elf]) 205142c5cccSJerome Forissier for line in iter(nm.stdout.readline, ''): 206142c5cccSJerome Forissier try: 207142c5cccSJerome Forissier addr, size, _, name = line.split() 2081d8c2a48SJerome Forissier except ValueError: 209142c5cccSJerome Forissier # Size is missing 210b4815427SJerome Forissier try: 211142c5cccSJerome Forissier addr, _, name = line.split() 212142c5cccSJerome Forissier size = '0' 2131d8c2a48SJerome Forissier except ValueError: 214b4815427SJerome Forissier # E.g., undefined (external) symbols (line = "U symbol") 215b4815427SJerome Forissier continue 216142c5cccSJerome Forissier iaddr = int(addr, 16) 217142c5cccSJerome Forissier isize = int(size, 16) 218142c5cccSJerome Forissier if iaddr == ireladdr: 219142c5cccSJerome Forissier ret = name 220142c5cccSJerome Forissier break 221142c5cccSJerome Forissier if iaddr < ireladdr and iaddr + isize >= ireladdr: 222142c5cccSJerome Forissier offs = ireladdr - iaddr 223142c5cccSJerome Forissier ret = name + '+' + str(offs) 224142c5cccSJerome Forissier break 225142c5cccSJerome Forissier if iaddr > ireladdr and prevsize == 0: 226142c5cccSJerome Forissier offs = iaddr + ireladdr 227142c5cccSJerome Forissier ret = prevname + '+' + str(offs) 228142c5cccSJerome Forissier break 229142c5cccSJerome Forissier prevsize = size 230142c5cccSJerome Forissier prevname = name 231142c5cccSJerome Forissier nm.terminate() 232142c5cccSJerome Forissier return ret 233142c5cccSJerome Forissier 234142c5cccSJerome Forissier def section_plus_offset(self, addr): 235142c5cccSJerome Forissier ret = '' 236142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 237ae252462SJerome Forissier elf_name = self.elf_for_addr(addr) 238ae252462SJerome Forissier if elf_name is None: 239ae252462SJerome Forissier return '' 240ae252462SJerome Forissier elf = self.get_elf(elf_name) 241142c5cccSJerome Forissier cmd = self.arch_prefix('objdump') 242142c5cccSJerome Forissier if not reladdr or not elf or not cmd: 243142c5cccSJerome Forissier return '' 24430999126SJerome Forissier iaddr = int(reladdr, 16) 245*1cbf777bSJerome Forissier objdump = self.my_Popen([cmd, '--section-headers', elf]) 246142c5cccSJerome Forissier for line in iter(objdump.stdout.readline, ''): 247142c5cccSJerome Forissier try: 248142c5cccSJerome Forissier idx, name, size, vma, lma, offs, algn = line.split() 2491d8c2a48SJerome Forissier except ValueError: 250ae252462SJerome Forissier continue 251142c5cccSJerome Forissier ivma = int(vma, 16) 252142c5cccSJerome Forissier isize = int(size, 16) 253142c5cccSJerome Forissier if ivma == iaddr: 254142c5cccSJerome Forissier ret = name 255142c5cccSJerome Forissier break 256142c5cccSJerome Forissier if ivma < iaddr and ivma + isize >= iaddr: 257142c5cccSJerome Forissier offs = iaddr - ivma 258142c5cccSJerome Forissier ret = name + '+' + str(offs) 259142c5cccSJerome Forissier break 260142c5cccSJerome Forissier objdump.terminate() 261142c5cccSJerome Forissier return ret 262142c5cccSJerome Forissier 263142c5cccSJerome Forissier def process_abort(self, line): 264142c5cccSJerome Forissier ret = '' 265142c5cccSJerome Forissier match = re.search(ABORT_ADDR_RE, line) 266142c5cccSJerome Forissier addr = match.group('addr') 267142c5cccSJerome Forissier pre = match.start('addr') 268142c5cccSJerome Forissier post = match.end('addr') 269142c5cccSJerome Forissier sym = self.symbol_plus_offset(addr) 270142c5cccSJerome Forissier sec = self.section_plus_offset(addr) 271142c5cccSJerome Forissier if sym or sec: 272142c5cccSJerome Forissier ret += line[:pre] 273142c5cccSJerome Forissier ret += addr 274142c5cccSJerome Forissier if sym: 275142c5cccSJerome Forissier ret += ' ' + sym 276142c5cccSJerome Forissier if sec: 277142c5cccSJerome Forissier ret += ' ' + sec 278142c5cccSJerome Forissier ret += line[post:] 279142c5cccSJerome Forissier return ret 280142c5cccSJerome Forissier 28130999126SJerome Forissier # Return all ELF sections with the ALLOC flag 282ae252462SJerome Forissier def read_sections(self, elf_name): 283ae252462SJerome Forissier if elf_name is None: 28430999126SJerome Forissier return 285ae252462SJerome Forissier if elf_name in self._sections: 286ae252462SJerome Forissier return 287ae252462SJerome Forissier elf = self.get_elf(elf_name) 28830999126SJerome Forissier cmd = self.arch_prefix('objdump') 28930999126SJerome Forissier if not elf or not cmd: 29030999126SJerome Forissier return 291ae252462SJerome Forissier self._sections[elf_name] = [] 292*1cbf777bSJerome Forissier objdump = self.my_Popen([cmd, '--section-headers', elf]) 29330999126SJerome Forissier for line in iter(objdump.stdout.readline, ''): 29430999126SJerome Forissier try: 29530999126SJerome Forissier _, name, size, vma, _, _, _ = line.split() 2961d8c2a48SJerome Forissier except ValueError: 29730999126SJerome Forissier if 'ALLOC' in line: 298ae252462SJerome Forissier self._sections[elf_name].append([name, int(vma, 16), 299ae252462SJerome Forissier int(size, 16)]) 30030999126SJerome Forissier 30130999126SJerome Forissier def overlaps(self, section, addr, size): 30230999126SJerome Forissier sec_addr = section[1] 30330999126SJerome Forissier sec_size = section[2] 30430999126SJerome Forissier if not size or not sec_size: 30530999126SJerome Forissier return False 306ae252462SJerome Forissier return ((addr <= (sec_addr + sec_size - 1)) and 307ae252462SJerome Forissier ((addr + size - 1) >= sec_addr)) 30830999126SJerome Forissier 309ae252462SJerome Forissier def sections_in_region(self, addr, size, elf_idx): 31030999126SJerome Forissier ret = '' 31130999126SJerome Forissier addr = self.subtract_load_addr(addr) 31230999126SJerome Forissier if not addr: 31330999126SJerome Forissier return '' 31430999126SJerome Forissier iaddr = int(addr, 16) 31530999126SJerome Forissier isize = int(size, 16) 316ae252462SJerome Forissier elf = self._elfs[int(elf_idx)][0] 317ae252462SJerome Forissier if elf is None: 318ae252462SJerome Forissier return '' 319ae252462SJerome Forissier self.read_sections(elf) 320ae252462SJerome Forissier if elf not in self._sections: 321ae252462SJerome Forissier return '' 322ae252462SJerome Forissier for s in self._sections[elf]: 32330999126SJerome Forissier if self.overlaps(s, iaddr, isize): 32430999126SJerome Forissier ret += ' ' + s[0] 32530999126SJerome Forissier return ret 32630999126SJerome Forissier 327733a15f2SJerome Forissier def reset(self): 328733a15f2SJerome Forissier self._call_stack_found = False 329733a15f2SJerome Forissier if self._addr2line: 330733a15f2SJerome Forissier self._addr2line.terminate() 331733a15f2SJerome Forissier self._addr2line = None 332ae252462SJerome Forissier self._addr2line_elf_name = None 333d720431cSJerome Forissier self._arch = None 334142c5cccSJerome Forissier self._saved_abort_line = '' 335ae252462SJerome Forissier self._sections = {} # {elf_name: [[name, addr, size], ...], ...} 336ae252462SJerome Forissier self._regions = [] # [[addr, size, elf_idx, saved line], ...] 337ae252462SJerome Forissier self._elfs = {0: ["tee.elf", 0]} # {idx: [uuid, load_addr], ...} 338733a15f2SJerome Forissier 339095567e5SJerome Forissier def pretty_print_path(self, path): 340095567e5SJerome Forissier if self._strip_path: 341095567e5SJerome Forissier return re.sub(re.escape(self._strip_path) + '/*', '', path) 342095567e5SJerome Forissier return path 343095567e5SJerome Forissier 344733a15f2SJerome Forissier def write(self, line): 345733a15f2SJerome Forissier if self._call_stack_found: 346733a15f2SJerome Forissier match = re.search(STACK_ADDR_RE, line) 347733a15f2SJerome Forissier if match: 348733a15f2SJerome Forissier addr = match.group('addr') 349733a15f2SJerome Forissier pre = match.start('addr') 350733a15f2SJerome Forissier post = match.end('addr') 351733a15f2SJerome Forissier self._out.write(line[:pre]) 352733a15f2SJerome Forissier self._out.write(addr) 353733a15f2SJerome Forissier res = self.resolve(addr) 354095567e5SJerome Forissier res = self.pretty_print_path(res) 355733a15f2SJerome Forissier self._out.write(' ' + res) 356733a15f2SJerome Forissier self._out.write(line[post:]) 357733a15f2SJerome Forissier return 358733a15f2SJerome Forissier else: 359733a15f2SJerome Forissier self.reset() 36030999126SJerome Forissier match = re.search(REGION_RE, line) 36130999126SJerome Forissier if match: 362ae252462SJerome Forissier # Region table: save info for later processing once 363ae252462SJerome Forissier # we know which UUID corresponds to which ELF index 36430999126SJerome Forissier addr = match.group('addr') 36530999126SJerome Forissier size = match.group('size') 366ae252462SJerome Forissier elf_idx = match.group('elf_idx') 367ae252462SJerome Forissier self._regions.append([addr, size, elf_idx, line]) 368ae252462SJerome Forissier return 369ae252462SJerome Forissier match = re.search(ELF_LIST_RE, line) 370ae252462SJerome Forissier if match: 371ae252462SJerome Forissier # ELF list: save info for later. Region table and ELF list 372ae252462SJerome Forissier # will be displayed when the call stack is reached 373ae252462SJerome Forissier i = int(match.group('idx')) 374ae252462SJerome Forissier self._elfs[i] = [match.group('uuid'), match.group('load_addr'), 375ae252462SJerome Forissier line] 37630999126SJerome Forissier return 377733a15f2SJerome Forissier match = re.search(CALL_STACK_RE, line) 378733a15f2SJerome Forissier if match: 379733a15f2SJerome Forissier self._call_stack_found = True 380ae252462SJerome Forissier if self._regions: 381ae252462SJerome Forissier for r in self._regions: 382ae252462SJerome Forissier r_addr = r[0] 383ae252462SJerome Forissier r_size = r[1] 384ae252462SJerome Forissier elf_idx = r[2] 385ae252462SJerome Forissier saved_line = r[3] 386ae252462SJerome Forissier if elf_idx is None: 387ae252462SJerome Forissier self._out.write(saved_line) 388ae252462SJerome Forissier else: 389ae252462SJerome Forissier self._out.write(saved_line.strip() + 390ae252462SJerome Forissier self.sections_in_region(r_addr, 391ae252462SJerome Forissier r_size, 392ae252462SJerome Forissier elf_idx) + 393ae252462SJerome Forissier '\n') 394ae252462SJerome Forissier if self._elfs: 395ae252462SJerome Forissier for k in self._elfs: 396ae252462SJerome Forissier e = self._elfs[k] 397ae252462SJerome Forissier if (len(e) >= 3): 3981e6f2ea0SJerome Forissier # TA executable or library 399095567e5SJerome Forissier self._out.write(e[2].strip()) 400095567e5SJerome Forissier elf = self.get_elf(e[0]) 401095567e5SJerome Forissier if elf: 402095567e5SJerome Forissier rpath = os.path.realpath(elf) 403095567e5SJerome Forissier path = self.pretty_print_path(rpath) 404095567e5SJerome Forissier self._out.write(' (' + path + ')') 405095567e5SJerome Forissier self._out.write('\n') 406142c5cccSJerome Forissier # Here is a good place to resolve the abort address because we 407142c5cccSJerome Forissier # have all the information we need 408142c5cccSJerome Forissier if self._saved_abort_line: 409142c5cccSJerome Forissier self._out.write(self.process_abort(self._saved_abort_line)) 410142c5cccSJerome Forissier match = re.search(ABORT_ADDR_RE, line) 411142c5cccSJerome Forissier if match: 41227b83ad2SJerome Forissier self.reset() 413142c5cccSJerome Forissier # At this point the arch and TA load address are unknown. 414142c5cccSJerome Forissier # Save the line so We can translate the abort address later. 415142c5cccSJerome Forissier self._saved_abort_line = line 416733a15f2SJerome Forissier self._out.write(line) 417733a15f2SJerome Forissier 418733a15f2SJerome Forissier def flush(self): 419733a15f2SJerome Forissier self._out.flush() 420733a15f2SJerome Forissier 421ae252462SJerome Forissier 422733a15f2SJerome Forissierdef main(): 423733a15f2SJerome Forissier args = get_args() 424733a15f2SJerome Forissier if args.dir: 425733a15f2SJerome Forissier # Flatten list in case -d is used several times *and* with multiple 426733a15f2SJerome Forissier # arguments 427733a15f2SJerome Forissier args.dirs = [item for sublist in args.dir for item in sublist] 428733a15f2SJerome Forissier else: 429733a15f2SJerome Forissier args.dirs = [] 430733a15f2SJerome Forissier symbolizer = Symbolizer(sys.stdout, args.dirs, args.strip_path) 431733a15f2SJerome Forissier 432733a15f2SJerome Forissier for line in sys.stdin: 433733a15f2SJerome Forissier symbolizer.write(line) 434733a15f2SJerome Forissier symbolizer.flush() 435733a15f2SJerome Forissier 4361d8c2a48SJerome Forissier 437733a15f2SJerome Forissierif __name__ == "__main__": 438733a15f2SJerome Forissier main() 439