xref: /optee_os/scripts/symbolize.py (revision 095567e5e50cbd8918b4e9b181f70d08be7e8a1b)
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