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='+', 63733a15f2SJerome Forissier help='Search for ELF file in DIR. tee.elf is needed to decode ' 64733a15f2SJerome Forissier 'a TEE Core or pseudo-TA abort, while <TA_uuid>.elf is required ' 65157e6213SJerome Forissier 'if a user-mode TA has crashed. For convenience, ELF files ' 66157e6213SJerome Forissier 'may also be given.') 675f7df507SJerome Forissier parser.add_argument('-s', '--strip_path', nargs='?', 685f7df507SJerome Forissier help='Strip STRIP_PATH from file paths (default: current directory, ' 695f7df507SJerome Forissier 'use -s with no argument to show full paths)', 705f7df507SJerome Forissier default=os.getcwd()) 71733a15f2SJerome Forissier 72733a15f2SJerome Forissier return parser.parse_args() 73733a15f2SJerome Forissier 74ae252462SJerome Forissier 75733a15f2SJerome Forissierclass Symbolizer(object): 76733a15f2SJerome Forissier def __init__(self, out, dirs, strip_path): 77733a15f2SJerome Forissier self._out = out 78733a15f2SJerome Forissier self._dirs = dirs 79733a15f2SJerome Forissier self._strip_path = strip_path 80733a15f2SJerome Forissier self._addr2line = None 81733a15f2SJerome Forissier self.reset() 82733a15f2SJerome Forissier 83733a15f2SJerome Forissier def get_elf(self, elf_or_uuid): 84733a15f2SJerome Forissier if not elf_or_uuid.endswith('.elf'): 85733a15f2SJerome Forissier elf_or_uuid += '.elf' 86733a15f2SJerome Forissier for d in self._dirs: 87157e6213SJerome Forissier if d.endswith(elf_or_uuid) and os.path.isfile(d): 88157e6213SJerome Forissier return d 89733a15f2SJerome Forissier elf = glob.glob(d + '/' + elf_or_uuid) 90733a15f2SJerome Forissier if elf: 91733a15f2SJerome Forissier return elf[0] 92733a15f2SJerome Forissier 93d720431cSJerome Forissier def set_arch(self): 94d720431cSJerome Forissier if self._arch: 95d720431cSJerome Forissier return 96ae252462SJerome Forissier elf = self.get_elf(self._elfs[0][0]) 97ae252462SJerome Forissier if elf is None: 98ae252462SJerome Forissier return 99ae252462SJerome Forissier p = subprocess.Popen(['file', self.get_elf(self._elfs[0][0])], 100d720431cSJerome Forissier stdout=subprocess.PIPE) 101d720431cSJerome Forissier output = p.stdout.readlines() 102d720431cSJerome Forissier p.terminate() 103d720431cSJerome Forissier if 'ARM aarch64,' in output[0]: 104d720431cSJerome Forissier self._arch = 'aarch64-linux-gnu-' 105d720431cSJerome Forissier elif 'ARM,' in output[0]: 106d720431cSJerome Forissier self._arch = 'arm-linux-gnueabihf-' 107d720431cSJerome Forissier 108142c5cccSJerome Forissier def arch_prefix(self, cmd): 109d720431cSJerome Forissier self.set_arch() 110ae252462SJerome Forissier if self._arch is None: 111ae252462SJerome Forissier return '' 112d720431cSJerome Forissier return self._arch + cmd 113142c5cccSJerome Forissier 114ae252462SJerome Forissier def spawn_addr2line(self, elf_name): 115ae252462SJerome Forissier if elf_name is None: 116ae252462SJerome Forissier return 117ae252462SJerome Forissier if self._addr2line_elf_name is elf_name: 118ae252462SJerome Forissier return 119ae252462SJerome Forissier if self._addr2line: 120ae252462SJerome Forissier self._addr2line.terminate 121ae252462SJerome Forissier self._addr2line = None 122ae252462SJerome Forissier elf = self.get_elf(elf_name) 123733a15f2SJerome Forissier if not elf: 124733a15f2SJerome Forissier return 125142c5cccSJerome Forissier cmd = self.arch_prefix('addr2line') 126142c5cccSJerome Forissier if not cmd: 127733a15f2SJerome Forissier return 128733a15f2SJerome Forissier self._addr2line = subprocess.Popen([cmd, '-f', '-p', '-e', elf], 129733a15f2SJerome Forissier stdin=subprocess.PIPE, 130733a15f2SJerome Forissier stdout=subprocess.PIPE) 131ae252462SJerome Forissier self._addr2line_elf_name = elf_name 132ae252462SJerome Forissier 133ae252462SJerome Forissier # If addr falls into a region that maps a TA ELF file, return the load 134ae252462SJerome Forissier # address of that file. 135ae252462SJerome Forissier def elf_load_addr(self, addr): 136ae252462SJerome Forissier if self._regions: 137ae252462SJerome Forissier for r in self._regions: 138ae252462SJerome Forissier r_addr = int(r[0], 16) 139ae252462SJerome Forissier r_size = int(r[1], 16) 140ae252462SJerome Forissier i_addr = int(addr, 16) 141ae252462SJerome Forissier if (i_addr >= r_addr and i_addr < (r_addr + r_size)): 142ae252462SJerome Forissier # Found region 143ae252462SJerome Forissier elf_idx = r[2] 144ae252462SJerome Forissier if elf_idx is not None: 145ae252462SJerome Forissier return self._elfs[int(elf_idx)][1] 146ae252462SJerome Forissier return None 147ae252462SJerome Forissier else: 148ae252462SJerome Forissier # tee.elf 149ae252462SJerome Forissier return '0x0' 150ae252462SJerome Forissier 151ae252462SJerome Forissier def elf_for_addr(self, addr): 152ae252462SJerome Forissier l_addr = self.elf_load_addr(addr) 153ae252462SJerome Forissier if l_addr is None: 154ae252462SJerome Forissier return None 155ae252462SJerome Forissier if l_addr is '0x0': 156ae252462SJerome Forissier return 'tee.elf' 157ae252462SJerome Forissier for k in self._elfs: 158ae252462SJerome Forissier e = self._elfs[k] 159ae252462SJerome Forissier if int(e[1], 16) == int(l_addr, 16): 160ae252462SJerome Forissier return e[0] 161ae252462SJerome Forissier return None 162733a15f2SJerome Forissier 163142c5cccSJerome Forissier def subtract_load_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 int(l_addr, 16) > int(addr, 16): 168142c5cccSJerome Forissier return '' 169ae252462SJerome Forissier return '0x{:x}'.format(int(addr, 16) - int(l_addr, 16)) 170142c5cccSJerome Forissier 171142c5cccSJerome Forissier def resolve(self, addr): 172142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 173ae252462SJerome Forissier self.spawn_addr2line(self.elf_for_addr(addr)) 174142c5cccSJerome Forissier if not reladdr or not self._addr2line: 175733a15f2SJerome Forissier return '???' 176733a15f2SJerome Forissier try: 177733a15f2SJerome Forissier print >> self._addr2line.stdin, reladdr 178733a15f2SJerome Forissier ret = self._addr2line.stdout.readline().rstrip('\n') 179733a15f2SJerome Forissier except IOError: 180733a15f2SJerome Forissier ret = '!!!' 181733a15f2SJerome Forissier return ret 182733a15f2SJerome Forissier 183142c5cccSJerome Forissier def symbol_plus_offset(self, addr): 184142c5cccSJerome Forissier ret = '' 185142c5cccSJerome Forissier prevsize = 0 186142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 187ae252462SJerome Forissier elf_name = self.elf_for_addr(addr) 188ae252462SJerome Forissier if elf_name is None: 189ae252462SJerome Forissier return '' 190ae252462SJerome Forissier elf = self.get_elf(elf_name) 191142c5cccSJerome Forissier cmd = self.arch_prefix('nm') 192142c5cccSJerome Forissier if not reladdr or not elf or not cmd: 193142c5cccSJerome Forissier return '' 19430999126SJerome Forissier ireladdr = int(reladdr, 16) 195142c5cccSJerome Forissier nm = subprocess.Popen([cmd, '--numeric-sort', '--print-size', elf], 196142c5cccSJerome Forissier stdin=subprocess.PIPE, 197142c5cccSJerome Forissier stdout=subprocess.PIPE) 198142c5cccSJerome Forissier for line in iter(nm.stdout.readline, ''): 199142c5cccSJerome Forissier try: 200142c5cccSJerome Forissier addr, size, _, name = line.split() 201142c5cccSJerome Forissier except: 202142c5cccSJerome Forissier # Size is missing 203142c5cccSJerome Forissier addr, _, name = line.split() 204142c5cccSJerome Forissier size = '0' 205142c5cccSJerome Forissier iaddr = int(addr, 16) 206142c5cccSJerome Forissier isize = int(size, 16) 207142c5cccSJerome Forissier if iaddr == ireladdr: 208142c5cccSJerome Forissier ret = name 209142c5cccSJerome Forissier break 210142c5cccSJerome Forissier if iaddr < ireladdr and iaddr + isize >= ireladdr: 211142c5cccSJerome Forissier offs = ireladdr - iaddr 212142c5cccSJerome Forissier ret = name + '+' + str(offs) 213142c5cccSJerome Forissier break 214142c5cccSJerome Forissier if iaddr > ireladdr and prevsize == 0: 215142c5cccSJerome Forissier offs = iaddr + ireladdr 216142c5cccSJerome Forissier ret = prevname + '+' + str(offs) 217142c5cccSJerome Forissier break 218142c5cccSJerome Forissier prevsize = size 219142c5cccSJerome Forissier prevname = name 220142c5cccSJerome Forissier nm.terminate() 221142c5cccSJerome Forissier return ret 222142c5cccSJerome Forissier 223142c5cccSJerome Forissier def section_plus_offset(self, addr): 224142c5cccSJerome Forissier ret = '' 225142c5cccSJerome Forissier reladdr = self.subtract_load_addr(addr) 226ae252462SJerome Forissier elf_name = self.elf_for_addr(addr) 227ae252462SJerome Forissier if elf_name is None: 228ae252462SJerome Forissier return '' 229ae252462SJerome Forissier elf = self.get_elf(elf_name) 230142c5cccSJerome Forissier cmd = self.arch_prefix('objdump') 231142c5cccSJerome Forissier if not reladdr or not elf or not cmd: 232142c5cccSJerome Forissier return '' 23330999126SJerome Forissier iaddr = int(reladdr, 16) 234142c5cccSJerome Forissier objdump = subprocess.Popen([cmd, '--section-headers', elf], 235142c5cccSJerome Forissier stdin=subprocess.PIPE, 236142c5cccSJerome Forissier stdout=subprocess.PIPE) 237142c5cccSJerome Forissier for line in iter(objdump.stdout.readline, ''): 238142c5cccSJerome Forissier try: 239142c5cccSJerome Forissier idx, name, size, vma, lma, offs, algn = line.split() 240142c5cccSJerome Forissier except: 241ae252462SJerome Forissier continue 242142c5cccSJerome Forissier ivma = int(vma, 16) 243142c5cccSJerome Forissier isize = int(size, 16) 244142c5cccSJerome Forissier if ivma == iaddr: 245142c5cccSJerome Forissier ret = name 246142c5cccSJerome Forissier break 247142c5cccSJerome Forissier if ivma < iaddr and ivma + isize >= iaddr: 248142c5cccSJerome Forissier offs = iaddr - ivma 249142c5cccSJerome Forissier ret = name + '+' + str(offs) 250142c5cccSJerome Forissier break 251142c5cccSJerome Forissier objdump.terminate() 252142c5cccSJerome Forissier return ret 253142c5cccSJerome Forissier 254142c5cccSJerome Forissier def process_abort(self, line): 255142c5cccSJerome Forissier ret = '' 256142c5cccSJerome Forissier match = re.search(ABORT_ADDR_RE, line) 257142c5cccSJerome Forissier addr = match.group('addr') 258142c5cccSJerome Forissier pre = match.start('addr') 259142c5cccSJerome Forissier post = match.end('addr') 260142c5cccSJerome Forissier sym = self.symbol_plus_offset(addr) 261142c5cccSJerome Forissier sec = self.section_plus_offset(addr) 262142c5cccSJerome Forissier if sym or sec: 263142c5cccSJerome Forissier ret += line[:pre] 264142c5cccSJerome Forissier ret += addr 265142c5cccSJerome Forissier if sym: 266142c5cccSJerome Forissier ret += ' ' + sym 267142c5cccSJerome Forissier if sec: 268142c5cccSJerome Forissier ret += ' ' + sec 269142c5cccSJerome Forissier ret += line[post:] 270142c5cccSJerome Forissier return ret 271142c5cccSJerome Forissier 27230999126SJerome Forissier # Return all ELF sections with the ALLOC flag 273ae252462SJerome Forissier def read_sections(self, elf_name): 274ae252462SJerome Forissier if elf_name is None: 27530999126SJerome Forissier return 276ae252462SJerome Forissier if elf_name in self._sections: 277ae252462SJerome Forissier return 278ae252462SJerome Forissier elf = self.get_elf(elf_name) 27930999126SJerome Forissier cmd = self.arch_prefix('objdump') 28030999126SJerome Forissier if not elf or not cmd: 28130999126SJerome Forissier return 282ae252462SJerome Forissier self._sections[elf_name] = [] 28330999126SJerome Forissier objdump = subprocess.Popen([cmd, '--section-headers', elf], 28430999126SJerome Forissier stdin=subprocess.PIPE, 28530999126SJerome Forissier stdout=subprocess.PIPE) 28630999126SJerome Forissier for line in iter(objdump.stdout.readline, ''): 28730999126SJerome Forissier try: 28830999126SJerome Forissier _, name, size, vma, _, _, _ = line.split() 28930999126SJerome Forissier except: 29030999126SJerome Forissier if 'ALLOC' in line: 291ae252462SJerome Forissier self._sections[elf_name].append([name, int(vma, 16), 292ae252462SJerome Forissier int(size, 16)]) 29330999126SJerome Forissier 29430999126SJerome Forissier def overlaps(self, section, addr, size): 29530999126SJerome Forissier sec_addr = section[1] 29630999126SJerome Forissier sec_size = section[2] 29730999126SJerome Forissier if not size or not sec_size: 29830999126SJerome Forissier return False 299ae252462SJerome Forissier return ((addr <= (sec_addr + sec_size - 1)) and 300ae252462SJerome Forissier ((addr + size - 1) >= sec_addr)) 30130999126SJerome Forissier 302ae252462SJerome Forissier def sections_in_region(self, addr, size, elf_idx): 30330999126SJerome Forissier ret = '' 30430999126SJerome Forissier addr = self.subtract_load_addr(addr) 30530999126SJerome Forissier if not addr: 30630999126SJerome Forissier return '' 30730999126SJerome Forissier iaddr = int(addr, 16) 30830999126SJerome Forissier isize = int(size, 16) 309ae252462SJerome Forissier elf = self._elfs[int(elf_idx)][0] 310ae252462SJerome Forissier if elf is None: 311ae252462SJerome Forissier return '' 312ae252462SJerome Forissier self.read_sections(elf) 313ae252462SJerome Forissier if elf not in self._sections: 314ae252462SJerome Forissier return '' 315ae252462SJerome Forissier for s in self._sections[elf]: 31630999126SJerome Forissier if self.overlaps(s, iaddr, isize): 31730999126SJerome Forissier ret += ' ' + s[0] 31830999126SJerome Forissier return ret 31930999126SJerome Forissier 320733a15f2SJerome Forissier def reset(self): 321733a15f2SJerome Forissier self._call_stack_found = False 322733a15f2SJerome Forissier if self._addr2line: 323733a15f2SJerome Forissier self._addr2line.terminate() 324733a15f2SJerome Forissier self._addr2line = None 325ae252462SJerome Forissier self._addr2line_elf_name = None 326d720431cSJerome Forissier self._arch = None 327142c5cccSJerome Forissier self._saved_abort_line = '' 328ae252462SJerome Forissier self._sections = {} # {elf_name: [[name, addr, size], ...], ...} 329ae252462SJerome Forissier self._regions = [] # [[addr, size, elf_idx, saved line], ...] 330ae252462SJerome Forissier self._elfs = {0: ["tee.elf", 0]} # {idx: [uuid, load_addr], ...} 331733a15f2SJerome Forissier 332*095567e5SJerome Forissier 333*095567e5SJerome Forissier def pretty_print_path(self, path): 334*095567e5SJerome Forissier if self._strip_path: 335*095567e5SJerome Forissier return re.sub(re.escape(self._strip_path) + '/*', '', path) 336*095567e5SJerome Forissier return path 337*095567e5SJerome Forissier 338*095567e5SJerome Forissier 339733a15f2SJerome Forissier def write(self, line): 340733a15f2SJerome Forissier if self._call_stack_found: 341733a15f2SJerome Forissier match = re.search(STACK_ADDR_RE, line) 342733a15f2SJerome Forissier if match: 343733a15f2SJerome Forissier addr = match.group('addr') 344733a15f2SJerome Forissier pre = match.start('addr') 345733a15f2SJerome Forissier post = match.end('addr') 346733a15f2SJerome Forissier self._out.write(line[:pre]) 347733a15f2SJerome Forissier self._out.write(addr) 348733a15f2SJerome Forissier res = self.resolve(addr) 349*095567e5SJerome Forissier res = self.pretty_print_path(res) 350733a15f2SJerome Forissier self._out.write(' ' + res) 351733a15f2SJerome Forissier self._out.write(line[post:]) 352733a15f2SJerome Forissier return 353733a15f2SJerome Forissier else: 354733a15f2SJerome Forissier self.reset() 35530999126SJerome Forissier match = re.search(REGION_RE, line) 35630999126SJerome Forissier if match: 357ae252462SJerome Forissier # Region table: save info for later processing once 358ae252462SJerome Forissier # we know which UUID corresponds to which ELF index 35930999126SJerome Forissier addr = match.group('addr') 36030999126SJerome Forissier size = match.group('size') 361ae252462SJerome Forissier elf_idx = match.group('elf_idx') 362ae252462SJerome Forissier self._regions.append([addr, size, elf_idx, line]) 363ae252462SJerome Forissier return 364ae252462SJerome Forissier match = re.search(ELF_LIST_RE, line) 365ae252462SJerome Forissier if match: 366ae252462SJerome Forissier # ELF list: save info for later. Region table and ELF list 367ae252462SJerome Forissier # will be displayed when the call stack is reached 368ae252462SJerome Forissier i = int(match.group('idx')) 369ae252462SJerome Forissier self._elfs[i] = [match.group('uuid'), match.group('load_addr'), 370ae252462SJerome Forissier line] 37130999126SJerome Forissier return 372733a15f2SJerome Forissier match = re.search(CALL_STACK_RE, line) 373733a15f2SJerome Forissier if match: 374733a15f2SJerome Forissier self._call_stack_found = True 375ae252462SJerome Forissier if self._regions: 376ae252462SJerome Forissier for r in self._regions: 377ae252462SJerome Forissier r_addr = r[0] 378ae252462SJerome Forissier r_size = r[1] 379ae252462SJerome Forissier elf_idx = r[2] 380ae252462SJerome Forissier saved_line = r[3] 381ae252462SJerome Forissier if elf_idx is None: 382ae252462SJerome Forissier self._out.write(saved_line) 383ae252462SJerome Forissier else: 384ae252462SJerome Forissier self._out.write(saved_line.strip() + 385ae252462SJerome Forissier self.sections_in_region(r_addr, 386ae252462SJerome Forissier r_size, 387ae252462SJerome Forissier elf_idx) + 388ae252462SJerome Forissier '\n') 389ae252462SJerome Forissier if self._elfs: 390ae252462SJerome Forissier for k in self._elfs: 391ae252462SJerome Forissier e = self._elfs[k] 392ae252462SJerome Forissier if (len(e) >= 3): 393*095567e5SJerome Forissier self._out.write(e[2].strip()) 394*095567e5SJerome Forissier elf = self.get_elf(e[0]) 395*095567e5SJerome Forissier if elf: 396*095567e5SJerome Forissier rpath = os.path.realpath(elf) 397*095567e5SJerome Forissier path = self.pretty_print_path(rpath) 398*095567e5SJerome Forissier self._out.write(' (' + path + ')') 399*095567e5SJerome Forissier self._out.write('\n') 400142c5cccSJerome Forissier # Here is a good place to resolve the abort address because we 401142c5cccSJerome Forissier # have all the information we need 402142c5cccSJerome Forissier if self._saved_abort_line: 403142c5cccSJerome Forissier self._out.write(self.process_abort(self._saved_abort_line)) 404142c5cccSJerome Forissier match = re.search(ABORT_ADDR_RE, line) 405142c5cccSJerome Forissier if match: 40627b83ad2SJerome Forissier self.reset() 407142c5cccSJerome Forissier # At this point the arch and TA load address are unknown. 408142c5cccSJerome Forissier # Save the line so We can translate the abort address later. 409142c5cccSJerome Forissier self._saved_abort_line = line 410733a15f2SJerome Forissier self._out.write(line) 411733a15f2SJerome Forissier 412733a15f2SJerome Forissier def flush(self): 413733a15f2SJerome Forissier self._out.flush() 414733a15f2SJerome Forissier 415ae252462SJerome Forissier 416733a15f2SJerome Forissierdef main(): 417733a15f2SJerome Forissier args = get_args() 418733a15f2SJerome Forissier if args.dir: 419733a15f2SJerome Forissier # Flatten list in case -d is used several times *and* with multiple 420733a15f2SJerome Forissier # arguments 421733a15f2SJerome Forissier args.dirs = [item for sublist in args.dir for item in sublist] 422733a15f2SJerome Forissier else: 423733a15f2SJerome Forissier args.dirs = [] 424733a15f2SJerome Forissier symbolizer = Symbolizer(sys.stdout, args.dirs, args.strip_path) 425733a15f2SJerome Forissier 426733a15f2SJerome Forissier for line in sys.stdin: 427733a15f2SJerome Forissier symbolizer.write(line) 428733a15f2SJerome Forissier symbolizer.flush() 429733a15f2SJerome Forissier 430733a15f2SJerome Forissierif __name__ == "__main__": 431733a15f2SJerome Forissier main() 432