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 841cbf777bSJerome Forissier def my_Popen(self, cmd): 851cbf777bSJerome Forissier try: 861cbf777bSJerome Forissier return subprocess.Popen(cmd, stdin=subprocess.PIPE, 871cbf777bSJerome Forissier stdout=subprocess.PIPE) 881cbf777bSJerome Forissier except OSError as e: 891cbf777bSJerome Forissier if e.errno == os.errno.ENOENT: 901cbf777bSJerome Forissier print >> sys.stderr, "*** Error:", cmd[0] + \ 911cbf777bSJerome Forissier ": command not found" 921cbf777bSJerome Forissier sys.exit(1) 931cbf777bSJerome 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 107*8a6d4a8bSEtienne Carriere self._arch = os.getenv('CROSS_COMPILE'); 108*8a6d4a8bSEtienne Carriere if self._arch: 109*8a6d4a8bSEtienne Carriere return 110ae252462SJerome Forissier elf = self.get_elf(self._elfs[0][0]) 111ae252462SJerome Forissier if elf is None: 112ae252462SJerome Forissier return 113ae252462SJerome Forissier p = subprocess.Popen(['file', self.get_elf(self._elfs[0][0])], 114d720431cSJerome Forissier stdout=subprocess.PIPE) 115d720431cSJerome Forissier output = p.stdout.readlines() 116d720431cSJerome Forissier p.terminate() 117d720431cSJerome Forissier if 'ARM aarch64,' in output[0]: 118d720431cSJerome Forissier self._arch = 'aarch64-linux-gnu-' 119d720431cSJerome Forissier elif 'ARM,' in output[0]: 120d720431cSJerome Forissier self._arch = 'arm-linux-gnueabihf-' 121d720431cSJerome Forissier 122142c5cccSJerome Forissier def arch_prefix(self, cmd): 123d720431cSJerome Forissier self.set_arch() 124ae252462SJerome Forissier if self._arch is None: 125ae252462SJerome Forissier return '' 126d720431cSJerome Forissier return self._arch + cmd 127142c5cccSJerome Forissier 128ae252462SJerome Forissier def spawn_addr2line(self, elf_name): 129ae252462SJerome Forissier if elf_name is None: 130ae252462SJerome Forissier return 131ae252462SJerome Forissier if self._addr2line_elf_name is elf_name: 132ae252462SJerome Forissier return 133ae252462SJerome Forissier if self._addr2line: 134ae252462SJerome Forissier self._addr2line.terminate 135ae252462SJerome Forissier self._addr2line = None 136ae252462SJerome Forissier elf = self.get_elf(elf_name) 137733a15f2SJerome Forissier if not elf: 138733a15f2SJerome Forissier return 139142c5cccSJerome Forissier cmd = self.arch_prefix('addr2line') 140142c5cccSJerome Forissier if not cmd: 141733a15f2SJerome Forissier return 1421cbf777bSJerome Forissier self._addr2line = self.my_Popen([cmd, '-f', '-p', '-e', elf]) 143ae252462SJerome Forissier self._addr2line_elf_name = elf_name 144ae252462SJerome Forissier 145ae252462SJerome Forissier # If addr falls into a region that maps a TA ELF file, return the load 146ae252462SJerome Forissier # address of that file. 147ae252462SJerome Forissier def elf_load_addr(self, addr): 148ae252462SJerome Forissier if self._regions: 149ae252462SJerome Forissier for r in self._regions: 150ae252462SJerome Forissier r_addr = int(r[0], 16) 151ae252462SJerome Forissier r_size = int(r[1], 16) 152ae252462SJerome Forissier i_addr = int(addr, 16) 153ae252462SJerome Forissier if (i_addr >= r_addr and i_addr < (r_addr + r_size)): 154ae252462SJerome Forissier # Found region 155ae252462SJerome Forissier elf_idx = r[2] 156ae252462SJerome Forissier if elf_idx is not None: 157ae252462SJerome Forissier return self._elfs[int(elf_idx)][1] 158ae252462SJerome Forissier return None 159ae252462SJerome Forissier else: 160ae252462SJerome Forissier # tee.elf 161ae252462SJerome Forissier return '0x0' 162ae252462SJerome Forissier 163ae252462SJerome Forissier def elf_for_addr(self, addr): 164ae252462SJerome Forissier l_addr = self.elf_load_addr(addr) 165ae252462SJerome Forissier if l_addr is None: 166ae252462SJerome Forissier return None 167ae252462SJerome Forissier if l_addr is '0x0': 168ae252462SJerome Forissier return 'tee.elf' 169ae252462SJerome Forissier for k in self._elfs: 170ae252462SJerome Forissier e = self._elfs[k] 171ae252462SJerome Forissier if int(e[1], 16) == int(l_addr, 16): 172ae252462SJerome Forissier return e[0] 173ae252462SJerome Forissier return None 174733a15f2SJerome Forissier 175142c5cccSJerome Forissier def subtract_load_addr(self, addr): 176ae252462SJerome Forissier l_addr = self.elf_load_addr(addr) 177ae252462SJerome Forissier if l_addr is None: 178ae252462SJerome Forissier return None 179ae252462SJerome Forissier if int(l_addr, 16) > int(addr, 16): 180142c5cccSJerome Forissier return '' 181ae252462SJerome Forissier return '0x{:x}'.format(int(addr, 16) - int(l_addr, 16)) 182142c5cccSJerome Forissier 183142c5cccSJerome Forissier def resolve(self, addr): 184142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 185ae252462SJerome Forissier self.spawn_addr2line(self.elf_for_addr(addr)) 186142c5cccSJerome Forissier if not reladdr or not self._addr2line: 187733a15f2SJerome Forissier return '???' 188733a15f2SJerome Forissier try: 189733a15f2SJerome Forissier print >> self._addr2line.stdin, reladdr 190733a15f2SJerome Forissier ret = self._addr2line.stdout.readline().rstrip('\n') 191733a15f2SJerome Forissier except IOError: 192733a15f2SJerome Forissier ret = '!!!' 193733a15f2SJerome Forissier return ret 194733a15f2SJerome Forissier 195142c5cccSJerome Forissier def symbol_plus_offset(self, addr): 196142c5cccSJerome Forissier ret = '' 197142c5cccSJerome Forissier prevsize = 0 198142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 199ae252462SJerome Forissier elf_name = self.elf_for_addr(addr) 200ae252462SJerome Forissier if elf_name is None: 201ae252462SJerome Forissier return '' 202ae252462SJerome Forissier elf = self.get_elf(elf_name) 203142c5cccSJerome Forissier cmd = self.arch_prefix('nm') 204142c5cccSJerome Forissier if not reladdr or not elf or not cmd: 205142c5cccSJerome Forissier return '' 20630999126SJerome Forissier ireladdr = int(reladdr, 16) 2071cbf777bSJerome Forissier nm = self.my_Popen([cmd, '--numeric-sort', '--print-size', elf]) 208142c5cccSJerome Forissier for line in iter(nm.stdout.readline, ''): 209142c5cccSJerome Forissier try: 210142c5cccSJerome Forissier addr, size, _, name = line.split() 2111d8c2a48SJerome Forissier except ValueError: 212142c5cccSJerome Forissier # Size is missing 213b4815427SJerome Forissier try: 214142c5cccSJerome Forissier addr, _, name = line.split() 215142c5cccSJerome Forissier size = '0' 2161d8c2a48SJerome Forissier except ValueError: 217b4815427SJerome Forissier # E.g., undefined (external) symbols (line = "U symbol") 218b4815427SJerome Forissier continue 219142c5cccSJerome Forissier iaddr = int(addr, 16) 220142c5cccSJerome Forissier isize = int(size, 16) 221142c5cccSJerome Forissier if iaddr == ireladdr: 222142c5cccSJerome Forissier ret = name 223142c5cccSJerome Forissier break 224142c5cccSJerome Forissier if iaddr < ireladdr and iaddr + isize >= ireladdr: 225142c5cccSJerome Forissier offs = ireladdr - iaddr 226142c5cccSJerome Forissier ret = name + '+' + str(offs) 227142c5cccSJerome Forissier break 228142c5cccSJerome Forissier if iaddr > ireladdr and prevsize == 0: 229142c5cccSJerome Forissier offs = iaddr + ireladdr 230142c5cccSJerome Forissier ret = prevname + '+' + str(offs) 231142c5cccSJerome Forissier break 232142c5cccSJerome Forissier prevsize = size 233142c5cccSJerome Forissier prevname = name 234142c5cccSJerome Forissier nm.terminate() 235142c5cccSJerome Forissier return ret 236142c5cccSJerome Forissier 237142c5cccSJerome Forissier def section_plus_offset(self, addr): 238142c5cccSJerome Forissier ret = '' 239142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 240ae252462SJerome Forissier elf_name = self.elf_for_addr(addr) 241ae252462SJerome Forissier if elf_name is None: 242ae252462SJerome Forissier return '' 243ae252462SJerome Forissier elf = self.get_elf(elf_name) 244142c5cccSJerome Forissier cmd = self.arch_prefix('objdump') 245142c5cccSJerome Forissier if not reladdr or not elf or not cmd: 246142c5cccSJerome Forissier return '' 24730999126SJerome Forissier iaddr = int(reladdr, 16) 2481cbf777bSJerome Forissier objdump = self.my_Popen([cmd, '--section-headers', elf]) 249142c5cccSJerome Forissier for line in iter(objdump.stdout.readline, ''): 250142c5cccSJerome Forissier try: 251142c5cccSJerome Forissier idx, name, size, vma, lma, offs, algn = line.split() 2521d8c2a48SJerome Forissier except ValueError: 253ae252462SJerome Forissier continue 254142c5cccSJerome Forissier ivma = int(vma, 16) 255142c5cccSJerome Forissier isize = int(size, 16) 256142c5cccSJerome Forissier if ivma == iaddr: 257142c5cccSJerome Forissier ret = name 258142c5cccSJerome Forissier break 259142c5cccSJerome Forissier if ivma < iaddr and ivma + isize >= iaddr: 260142c5cccSJerome Forissier offs = iaddr - ivma 261142c5cccSJerome Forissier ret = name + '+' + str(offs) 262142c5cccSJerome Forissier break 263142c5cccSJerome Forissier objdump.terminate() 264142c5cccSJerome Forissier return ret 265142c5cccSJerome Forissier 266142c5cccSJerome Forissier def process_abort(self, line): 267142c5cccSJerome Forissier ret = '' 268142c5cccSJerome Forissier match = re.search(ABORT_ADDR_RE, line) 269142c5cccSJerome Forissier addr = match.group('addr') 270142c5cccSJerome Forissier pre = match.start('addr') 271142c5cccSJerome Forissier post = match.end('addr') 272142c5cccSJerome Forissier sym = self.symbol_plus_offset(addr) 273142c5cccSJerome Forissier sec = self.section_plus_offset(addr) 274142c5cccSJerome Forissier if sym or sec: 275142c5cccSJerome Forissier ret += line[:pre] 276142c5cccSJerome Forissier ret += addr 277142c5cccSJerome Forissier if sym: 278142c5cccSJerome Forissier ret += ' ' + sym 279142c5cccSJerome Forissier if sec: 280142c5cccSJerome Forissier ret += ' ' + sec 281142c5cccSJerome Forissier ret += line[post:] 282142c5cccSJerome Forissier return ret 283142c5cccSJerome Forissier 28430999126SJerome Forissier # Return all ELF sections with the ALLOC flag 285ae252462SJerome Forissier def read_sections(self, elf_name): 286ae252462SJerome Forissier if elf_name is None: 28730999126SJerome Forissier return 288ae252462SJerome Forissier if elf_name in self._sections: 289ae252462SJerome Forissier return 290ae252462SJerome Forissier elf = self.get_elf(elf_name) 29130999126SJerome Forissier cmd = self.arch_prefix('objdump') 29230999126SJerome Forissier if not elf or not cmd: 29330999126SJerome Forissier return 294ae252462SJerome Forissier self._sections[elf_name] = [] 2951cbf777bSJerome Forissier objdump = self.my_Popen([cmd, '--section-headers', elf]) 29630999126SJerome Forissier for line in iter(objdump.stdout.readline, ''): 29730999126SJerome Forissier try: 29830999126SJerome Forissier _, name, size, vma, _, _, _ = line.split() 2991d8c2a48SJerome Forissier except ValueError: 30030999126SJerome Forissier if 'ALLOC' in line: 301ae252462SJerome Forissier self._sections[elf_name].append([name, int(vma, 16), 302ae252462SJerome Forissier int(size, 16)]) 30330999126SJerome Forissier 30430999126SJerome Forissier def overlaps(self, section, addr, size): 30530999126SJerome Forissier sec_addr = section[1] 30630999126SJerome Forissier sec_size = section[2] 30730999126SJerome Forissier if not size or not sec_size: 30830999126SJerome Forissier return False 309ae252462SJerome Forissier return ((addr <= (sec_addr + sec_size - 1)) and 310ae252462SJerome Forissier ((addr + size - 1) >= sec_addr)) 31130999126SJerome Forissier 312ae252462SJerome Forissier def sections_in_region(self, addr, size, elf_idx): 31330999126SJerome Forissier ret = '' 31430999126SJerome Forissier addr = self.subtract_load_addr(addr) 31530999126SJerome Forissier if not addr: 31630999126SJerome Forissier return '' 31730999126SJerome Forissier iaddr = int(addr, 16) 31830999126SJerome Forissier isize = int(size, 16) 319ae252462SJerome Forissier elf = self._elfs[int(elf_idx)][0] 320ae252462SJerome Forissier if elf is None: 321ae252462SJerome Forissier return '' 322ae252462SJerome Forissier self.read_sections(elf) 323ae252462SJerome Forissier if elf not in self._sections: 324ae252462SJerome Forissier return '' 325ae252462SJerome Forissier for s in self._sections[elf]: 32630999126SJerome Forissier if self.overlaps(s, iaddr, isize): 32730999126SJerome Forissier ret += ' ' + s[0] 32830999126SJerome Forissier return ret 32930999126SJerome Forissier 330733a15f2SJerome Forissier def reset(self): 331733a15f2SJerome Forissier self._call_stack_found = False 332733a15f2SJerome Forissier if self._addr2line: 333733a15f2SJerome Forissier self._addr2line.terminate() 334733a15f2SJerome Forissier self._addr2line = None 335ae252462SJerome Forissier self._addr2line_elf_name = None 336d720431cSJerome Forissier self._arch = None 337142c5cccSJerome Forissier self._saved_abort_line = '' 338ae252462SJerome Forissier self._sections = {} # {elf_name: [[name, addr, size], ...], ...} 339ae252462SJerome Forissier self._regions = [] # [[addr, size, elf_idx, saved line], ...] 340ae252462SJerome Forissier self._elfs = {0: ["tee.elf", 0]} # {idx: [uuid, load_addr], ...} 341733a15f2SJerome Forissier 342095567e5SJerome Forissier def pretty_print_path(self, path): 343095567e5SJerome Forissier if self._strip_path: 344095567e5SJerome Forissier return re.sub(re.escape(self._strip_path) + '/*', '', path) 345095567e5SJerome Forissier return path 346095567e5SJerome Forissier 347733a15f2SJerome Forissier def write(self, line): 348733a15f2SJerome Forissier if self._call_stack_found: 349733a15f2SJerome Forissier match = re.search(STACK_ADDR_RE, line) 350733a15f2SJerome Forissier if match: 351733a15f2SJerome Forissier addr = match.group('addr') 352733a15f2SJerome Forissier pre = match.start('addr') 353733a15f2SJerome Forissier post = match.end('addr') 354733a15f2SJerome Forissier self._out.write(line[:pre]) 355733a15f2SJerome Forissier self._out.write(addr) 356733a15f2SJerome Forissier res = self.resolve(addr) 357095567e5SJerome Forissier res = self.pretty_print_path(res) 358733a15f2SJerome Forissier self._out.write(' ' + res) 359733a15f2SJerome Forissier self._out.write(line[post:]) 360733a15f2SJerome Forissier return 361733a15f2SJerome Forissier else: 362733a15f2SJerome Forissier self.reset() 36330999126SJerome Forissier match = re.search(REGION_RE, line) 36430999126SJerome Forissier if match: 365ae252462SJerome Forissier # Region table: save info for later processing once 366ae252462SJerome Forissier # we know which UUID corresponds to which ELF index 36730999126SJerome Forissier addr = match.group('addr') 36830999126SJerome Forissier size = match.group('size') 369ae252462SJerome Forissier elf_idx = match.group('elf_idx') 370ae252462SJerome Forissier self._regions.append([addr, size, elf_idx, line]) 371ae252462SJerome Forissier return 372ae252462SJerome Forissier match = re.search(ELF_LIST_RE, line) 373ae252462SJerome Forissier if match: 374ae252462SJerome Forissier # ELF list: save info for later. Region table and ELF list 375ae252462SJerome Forissier # will be displayed when the call stack is reached 376ae252462SJerome Forissier i = int(match.group('idx')) 377ae252462SJerome Forissier self._elfs[i] = [match.group('uuid'), match.group('load_addr'), 378ae252462SJerome Forissier line] 37930999126SJerome Forissier return 380733a15f2SJerome Forissier match = re.search(CALL_STACK_RE, line) 381733a15f2SJerome Forissier if match: 382733a15f2SJerome Forissier self._call_stack_found = True 383ae252462SJerome Forissier if self._regions: 384ae252462SJerome Forissier for r in self._regions: 385ae252462SJerome Forissier r_addr = r[0] 386ae252462SJerome Forissier r_size = r[1] 387ae252462SJerome Forissier elf_idx = r[2] 388ae252462SJerome Forissier saved_line = r[3] 389ae252462SJerome Forissier if elf_idx is None: 390ae252462SJerome Forissier self._out.write(saved_line) 391ae252462SJerome Forissier else: 392ae252462SJerome Forissier self._out.write(saved_line.strip() + 393ae252462SJerome Forissier self.sections_in_region(r_addr, 394ae252462SJerome Forissier r_size, 395ae252462SJerome Forissier elf_idx) + 396ae252462SJerome Forissier '\n') 397ae252462SJerome Forissier if self._elfs: 398ae252462SJerome Forissier for k in self._elfs: 399ae252462SJerome Forissier e = self._elfs[k] 400ae252462SJerome Forissier if (len(e) >= 3): 4011e6f2ea0SJerome Forissier # TA executable or library 402095567e5SJerome Forissier self._out.write(e[2].strip()) 403095567e5SJerome Forissier elf = self.get_elf(e[0]) 404095567e5SJerome Forissier if elf: 405095567e5SJerome Forissier rpath = os.path.realpath(elf) 406095567e5SJerome Forissier path = self.pretty_print_path(rpath) 407095567e5SJerome Forissier self._out.write(' (' + path + ')') 408095567e5SJerome Forissier self._out.write('\n') 409142c5cccSJerome Forissier # Here is a good place to resolve the abort address because we 410142c5cccSJerome Forissier # have all the information we need 411142c5cccSJerome Forissier if self._saved_abort_line: 412142c5cccSJerome Forissier self._out.write(self.process_abort(self._saved_abort_line)) 413142c5cccSJerome Forissier match = re.search(ABORT_ADDR_RE, line) 414142c5cccSJerome Forissier if match: 41527b83ad2SJerome Forissier self.reset() 416142c5cccSJerome Forissier # At this point the arch and TA load address are unknown. 417142c5cccSJerome Forissier # Save the line so We can translate the abort address later. 418142c5cccSJerome Forissier self._saved_abort_line = line 419733a15f2SJerome Forissier self._out.write(line) 420733a15f2SJerome Forissier 421733a15f2SJerome Forissier def flush(self): 422733a15f2SJerome Forissier self._out.flush() 423733a15f2SJerome Forissier 424ae252462SJerome Forissier 425733a15f2SJerome Forissierdef main(): 426733a15f2SJerome Forissier args = get_args() 427733a15f2SJerome Forissier if args.dir: 428733a15f2SJerome Forissier # Flatten list in case -d is used several times *and* with multiple 429733a15f2SJerome Forissier # arguments 430733a15f2SJerome Forissier args.dirs = [item for sublist in args.dir for item in sublist] 431733a15f2SJerome Forissier else: 432733a15f2SJerome Forissier args.dirs = [] 433733a15f2SJerome Forissier symbolizer = Symbolizer(sys.stdout, args.dirs, args.strip_path) 434733a15f2SJerome Forissier 435733a15f2SJerome Forissier for line in sys.stdin: 436733a15f2SJerome Forissier symbolizer.write(line) 437733a15f2SJerome Forissier symbolizer.flush() 438733a15f2SJerome Forissier 4391d8c2a48SJerome Forissier 440733a15f2SJerome Forissierif __name__ == "__main__": 441733a15f2SJerome Forissier main() 442