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