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