blob: 5928932df1d9f75911bf255d4d7b2b65b30de038 [file] [log] [blame]
Rouven Czerwinskibbaeed42019-08-07 20:07:00 +02001#!/usr/bin/env python3
Jerome Forissier1bb92982017-12-15 14:27:02 +01002# SPDX-License-Identifier: BSD-2-Clause
Jerome Forissier733a15f2017-05-19 17:40:17 +02003#
4# Copyright (c) 2017, Linaro Limited
Jerome Forissier733a15f2017-05-19 17:40:17 +02005#
Jerome Forissier733a15f2017-05-19 17:40:17 +02006
7
8import argparse
Rouven Czerwinskibbaeed42019-08-07 20:07:00 +02009import errno
Jerome Forissier733a15f2017-05-19 17:40:17 +020010import glob
Jerome Forissier157e6212017-08-24 15:49:16 +020011import os
Jerome Forissier733a15f2017-05-19 17:40:17 +020012import re
13import subprocess
14import sys
Jerome Forissier6b4fc672019-09-23 09:49:32 +020015import termios
Jerome Forissier733a15f2017-05-19 17:40:17 +020016
Jerome Forissier733a15f2017-05-19 17:40:17 +020017CALL_STACK_RE = re.compile('Call stack:')
Joakim Becha2b984b2017-12-15 14:34:56 +010018# This gets the address from lines looking like this:
19# E/TC:0 0x001044a8
Jerome Forissier6e7c2e92018-11-14 11:02:49 +010020STACK_ADDR_RE = re.compile(
Jens Wiklander531963a2019-05-23 17:42:15 +020021 r'[UEIDFM]/(TC|LD):(\?*|[0-9]*) [0-9]* +(?P<addr>0x[0-9a-f]+)')
Jerome Forissier6e7c2e92018-11-14 11:02:49 +010022ABORT_ADDR_RE = re.compile(r'-abort at address (?P<addr>0x[0-9a-f]+)')
Jerome Forissier444c2032019-03-13 18:00:56 +010023REGION_RE = re.compile(r'region +[0-9]+: va (?P<addr>0x[0-9a-f]+) '
Jerome Forissier6e7c2e92018-11-14 11:02:49 +010024 r'pa 0x[0-9a-f]+ size (?P<size>0x[0-9a-f]+)'
Jens Wiklander531963a2019-05-23 17:42:15 +020025 r'( flags .{4} (\[(?P<elf_idx>[0-9]+)\])?)?')
Jerome Forissierae252462018-05-25 15:07:28 +020026ELF_LIST_RE = re.compile(r'\[(?P<idx>[0-9]+)\] (?P<uuid>[0-9a-f\-]+)'
Jerome Forissier6e7c2e92018-11-14 11:02:49 +010027 r' @ (?P<load_addr>0x[0-9a-f\-]+)')
Sumit Gargc90b6662019-03-28 18:24:21 +053028FUNC_GRAPH_RE = re.compile(r'Function graph')
29GRAPH_ADDR_RE = re.compile(r'(?P<addr>0x[0-9a-f]+)')
30GRAPH_RE = re.compile(r'}')
Jerome Forissier733a15f2017-05-19 17:40:17 +020031
32epilog = '''
Jerome Forissier0c5bedb2018-02-15 17:20:36 +010033This scripts reads an OP-TEE abort or panic message from stdin and adds debug
34information to the output, such as '<function> at <file>:<line>' next to each
35address in the call stack. Any message generated by OP-TEE and containing a
36call stack can in principle be processed by this script. This currently
37includes aborts and panics from the TEE core as well as from any TA.
38The paths provided on the command line are used to locate the appropriate ELF
39binary (tee.elf or Trusted Application). The GNU binutils (addr2line, objdump,
Jerome Forissierf9089762018-10-02 10:12:32 +020040nm) are used to extract the debug info. If the CROSS_COMPILE environment
41variable is set, it is used as a prefix to the binutils tools. That is, the
42script will invoke $(CROSS_COMPILE)addr2line etc. If it is not set however,
43the prefix will be determined automatically for each ELF file based on its
44architecture (arm-linux-gnueabihf-, aarch64-linux-gnu-). The resulting command
45is then expected to be found in the user's PATH.
Jerome Forissier733a15f2017-05-19 17:40:17 +020046
Jerome Forissier0c5bedb2018-02-15 17:20:36 +010047OP-TEE abort and panic messages are sent to the secure console. They look like
48the following:
Jerome Forissier733a15f2017-05-19 17:40:17 +020049
Jerome Forissier0c5bedb2018-02-15 17:20:36 +010050 E/TC:0 User TA data-abort at address 0xffffdecd (alignment fault)
Jerome Forissier733a15f2017-05-19 17:40:17 +020051 ...
Jerome Forissier0c5bedb2018-02-15 17:20:36 +010052 E/TC:0 Call stack:
53 E/TC:0 0x4000549e
54 E/TC:0 0x40001f4b
55 E/TC:0 0x4000273f
56 E/TC:0 0x40005da7
Jerome Forissier733a15f2017-05-19 17:40:17 +020057
58Inspired by a script of the same name by the Chromium project.
59
60Sample usage:
61
62 $ scripts/symbolize.py -d out/arm-plat-hikey/core -d ../optee_test/out/ta/*
63 <paste whole dump here>
64 ^D
Sumit Gargc90b6662019-03-28 18:24:21 +053065
66Also, this script reads function graph generated for OP-TEE user TA from
67/tmp/ftrace-<ta_uuid>.out file and resolves function addresses to corresponding
68symbols.
69
70Sample usage:
71
72 $ cat /tmp/ftrace-<ta_uuid>.out | scripts/symbolize.py -d <ta_uuid>.elf
73 <paste function graph here>
74 ^D
Jerome Forissier733a15f2017-05-19 17:40:17 +020075'''
76
Jerome Forissierae252462018-05-25 15:07:28 +020077
Jerome Forissier733a15f2017-05-19 17:40:17 +020078def get_args():
79 parser = argparse.ArgumentParser(
Jerome Forissier6e7c2e92018-11-14 11:02:49 +010080 formatter_class=argparse.RawDescriptionHelpFormatter,
Sumit Gargc90b6662019-03-28 18:24:21 +053081 description='Symbolizes OP-TEE abort dumps or function graphs',
Jerome Forissier6e7c2e92018-11-14 11:02:49 +010082 epilog=epilog)
Jerome Forissier733a15f2017-05-19 17:40:17 +020083 parser.add_argument('-d', '--dir', action='append', nargs='+',
Jerome Forissier1d8c2a42018-09-07 17:05:21 +020084 help='Search for ELF file in DIR. tee.elf is needed '
85 'to decode a TEE Core or pseudo-TA abort, while '
86 '<TA_uuid>.elf is required if a user-mode TA has '
87 'crashed. For convenience, ELF files may also be '
88 'given.')
Jerome Forissier5f7df502018-02-15 16:57:55 +010089 parser.add_argument('-s', '--strip_path', nargs='?',
Jerome Forissier1d8c2a42018-09-07 17:05:21 +020090 help='Strip STRIP_PATH from file paths (default: '
91 'current directory, use -s with no argument to show '
92 'full paths)', default=os.getcwd())
Jerome Forissier733a15f2017-05-19 17:40:17 +020093
94 return parser.parse_args()
95
Jerome Forissierae252462018-05-25 15:07:28 +020096
Jerome Forissier733a15f2017-05-19 17:40:17 +020097class Symbolizer(object):
98 def __init__(self, out, dirs, strip_path):
99 self._out = out
100 self._dirs = dirs
101 self._strip_path = strip_path
102 self._addr2line = None
Jerome Forissier733a15f2017-05-19 17:40:17 +0200103 self.reset()
104
Jerome Forissier1cbf7772018-09-07 17:08:23 +0200105 def my_Popen(self, cmd):
106 try:
107 return subprocess.Popen(cmd, stdin=subprocess.PIPE,
Rouven Czerwinskibbaeed42019-08-07 20:07:00 +0200108 stdout=subprocess.PIPE, text=True,
109 bufsize=1)
Jerome Forissier1cbf7772018-09-07 17:08:23 +0200110 except OSError as e:
Rouven Czerwinskibbaeed42019-08-07 20:07:00 +0200111 if e.errno == errno.ENOENT:
112 print("*** Error:{}: command not found".format(cmd[0]),
113 file=sys.stderr)
Jerome Forissier1cbf7772018-09-07 17:08:23 +0200114 sys.exit(1)
115
Jerome Forissier733a15f2017-05-19 17:40:17 +0200116 def get_elf(self, elf_or_uuid):
117 if not elf_or_uuid.endswith('.elf'):
118 elf_or_uuid += '.elf'
119 for d in self._dirs:
Jerome Forissier157e6212017-08-24 15:49:16 +0200120 if d.endswith(elf_or_uuid) and os.path.isfile(d):
121 return d
Jerome Forissier733a15f2017-05-19 17:40:17 +0200122 elf = glob.glob(d + '/' + elf_or_uuid)
123 if elf:
124 return elf[0]
125
Jerome Forissierd7204312017-09-04 17:58:52 +0200126 def set_arch(self):
127 if self._arch:
128 return
Jerome Forissier6e7c2e92018-11-14 11:02:49 +0100129 self._arch = os.getenv('CROSS_COMPILE')
Etienne Carriere8a6d4a82018-10-01 09:58:31 +0200130 if self._arch:
131 return
Jerome Forissierae252462018-05-25 15:07:28 +0200132 elf = self.get_elf(self._elfs[0][0])
133 if elf is None:
134 return
135 p = subprocess.Popen(['file', self.get_elf(self._elfs[0][0])],
136 stdout=subprocess.PIPE)
137 output = p.stdout.readlines()
138 p.terminate()
Rouven Czerwinskibbaeed42019-08-07 20:07:00 +0200139 if b'ARM aarch64,' in output[0]:
Jerome Forissierae252462018-05-25 15:07:28 +0200140 self._arch = 'aarch64-linux-gnu-'
Rouven Czerwinskibbaeed42019-08-07 20:07:00 +0200141 elif b'ARM,' in output[0]:
Jerome Forissierae252462018-05-25 15:07:28 +0200142 self._arch = 'arm-linux-gnueabihf-'
Jerome Forissierd7204312017-09-04 17:58:52 +0200143
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200144 def arch_prefix(self, cmd):
Jerome Forissierd7204312017-09-04 17:58:52 +0200145 self.set_arch()
Jerome Forissierae252462018-05-25 15:07:28 +0200146 if self._arch is None:
147 return ''
Jerome Forissierd7204312017-09-04 17:58:52 +0200148 return self._arch + cmd
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200149
Jerome Forissierae252462018-05-25 15:07:28 +0200150 def spawn_addr2line(self, elf_name):
151 if elf_name is None:
152 return
153 if self._addr2line_elf_name is elf_name:
154 return
155 if self._addr2line:
156 self._addr2line.terminate
157 self._addr2line = None
158 elf = self.get_elf(elf_name)
159 if not elf:
160 return
161 cmd = self.arch_prefix('addr2line')
162 if not cmd:
163 return
Jerome Forissier1cbf7772018-09-07 17:08:23 +0200164 self._addr2line = self.my_Popen([cmd, '-f', '-p', '-e', elf])
Jerome Forissierae252462018-05-25 15:07:28 +0200165 self._addr2line_elf_name = elf_name
166
167 # If addr falls into a region that maps a TA ELF file, return the load
168 # address of that file.
169 def elf_load_addr(self, addr):
170 if self._regions:
171 for r in self._regions:
172 r_addr = int(r[0], 16)
173 r_size = int(r[1], 16)
174 i_addr = int(addr, 16)
175 if (i_addr >= r_addr and i_addr < (r_addr + r_size)):
176 # Found region
177 elf_idx = r[2]
178 if elf_idx is not None:
179 return self._elfs[int(elf_idx)][1]
180 return None
181 else:
182 # tee.elf
183 return '0x0'
184
185 def elf_for_addr(self, addr):
186 l_addr = self.elf_load_addr(addr)
187 if l_addr is None:
188 return None
189 if l_addr is '0x0':
190 return 'tee.elf'
191 for k in self._elfs:
192 e = self._elfs[k]
193 if int(e[1], 16) == int(l_addr, 16):
194 return e[0]
195 return None
Jerome Forissier733a15f2017-05-19 17:40:17 +0200196
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200197 def subtract_load_addr(self, addr):
Jerome Forissierae252462018-05-25 15:07:28 +0200198 l_addr = self.elf_load_addr(addr)
199 if l_addr is None:
200 return None
201 if int(l_addr, 16) > int(addr, 16):
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200202 return ''
Jerome Forissierae252462018-05-25 15:07:28 +0200203 return '0x{:x}'.format(int(addr, 16) - int(l_addr, 16))
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200204
205 def resolve(self, addr):
206 reladdr = self.subtract_load_addr(addr)
Jerome Forissierae252462018-05-25 15:07:28 +0200207 self.spawn_addr2line(self.elf_for_addr(addr))
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200208 if not reladdr or not self._addr2line:
Jerome Forissier733a15f2017-05-19 17:40:17 +0200209 return '???'
210 try:
Rouven Czerwinskibbaeed42019-08-07 20:07:00 +0200211 print(reladdr, file=self._addr2line.stdin)
Jerome Forissier733a15f2017-05-19 17:40:17 +0200212 ret = self._addr2line.stdout.readline().rstrip('\n')
213 except IOError:
214 ret = '!!!'
215 return ret
216
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200217 def symbol_plus_offset(self, addr):
218 ret = ''
219 prevsize = 0
220 reladdr = self.subtract_load_addr(addr)
Jerome Forissierae252462018-05-25 15:07:28 +0200221 elf_name = self.elf_for_addr(addr)
222 if elf_name is None:
223 return ''
224 elf = self.get_elf(elf_name)
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200225 cmd = self.arch_prefix('nm')
226 if not reladdr or not elf or not cmd:
227 return ''
Jerome Forissier30999122017-08-25 18:42:58 +0200228 ireladdr = int(reladdr, 16)
Jerome Forissier1cbf7772018-09-07 17:08:23 +0200229 nm = self.my_Popen([cmd, '--numeric-sort', '--print-size', elf])
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200230 for line in iter(nm.stdout.readline, ''):
231 try:
232 addr, size, _, name = line.split()
Jerome Forissier1d8c2a42018-09-07 17:05:21 +0200233 except ValueError:
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200234 # Size is missing
Jerome Forissierb4815422018-06-20 09:43:33 +0200235 try:
236 addr, _, name = line.split()
237 size = '0'
Jerome Forissier1d8c2a42018-09-07 17:05:21 +0200238 except ValueError:
Jerome Forissierb4815422018-06-20 09:43:33 +0200239 # E.g., undefined (external) symbols (line = "U symbol")
240 continue
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200241 iaddr = int(addr, 16)
242 isize = int(size, 16)
243 if iaddr == ireladdr:
244 ret = name
245 break
246 if iaddr < ireladdr and iaddr + isize >= ireladdr:
247 offs = ireladdr - iaddr
248 ret = name + '+' + str(offs)
249 break
250 if iaddr > ireladdr and prevsize == 0:
251 offs = iaddr + ireladdr
252 ret = prevname + '+' + str(offs)
253 break
254 prevsize = size
255 prevname = name
256 nm.terminate()
257 return ret
258
259 def section_plus_offset(self, addr):
260 ret = ''
261 reladdr = self.subtract_load_addr(addr)
Jerome Forissierae252462018-05-25 15:07:28 +0200262 elf_name = self.elf_for_addr(addr)
263 if elf_name is None:
264 return ''
265 elf = self.get_elf(elf_name)
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200266 cmd = self.arch_prefix('objdump')
267 if not reladdr or not elf or not cmd:
268 return ''
Jerome Forissier30999122017-08-25 18:42:58 +0200269 iaddr = int(reladdr, 16)
Jerome Forissier1cbf7772018-09-07 17:08:23 +0200270 objdump = self.my_Popen([cmd, '--section-headers', elf])
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200271 for line in iter(objdump.stdout.readline, ''):
272 try:
273 idx, name, size, vma, lma, offs, algn = line.split()
Jerome Forissier1d8c2a42018-09-07 17:05:21 +0200274 except ValueError:
Jerome Forissierae252462018-05-25 15:07:28 +0200275 continue
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200276 ivma = int(vma, 16)
277 isize = int(size, 16)
278 if ivma == iaddr:
279 ret = name
280 break
281 if ivma < iaddr and ivma + isize >= iaddr:
282 offs = iaddr - ivma
283 ret = name + '+' + str(offs)
284 break
285 objdump.terminate()
286 return ret
287
288 def process_abort(self, line):
289 ret = ''
290 match = re.search(ABORT_ADDR_RE, line)
291 addr = match.group('addr')
292 pre = match.start('addr')
293 post = match.end('addr')
294 sym = self.symbol_plus_offset(addr)
295 sec = self.section_plus_offset(addr)
296 if sym or sec:
297 ret += line[:pre]
298 ret += addr
299 if sym:
300 ret += ' ' + sym
301 if sec:
302 ret += ' ' + sec
303 ret += line[post:]
304 return ret
305
Jerome Forissier30999122017-08-25 18:42:58 +0200306 # Return all ELF sections with the ALLOC flag
Jerome Forissierae252462018-05-25 15:07:28 +0200307 def read_sections(self, elf_name):
308 if elf_name is None:
Jerome Forissier30999122017-08-25 18:42:58 +0200309 return
Jerome Forissierae252462018-05-25 15:07:28 +0200310 if elf_name in self._sections:
311 return
312 elf = self.get_elf(elf_name)
Jerome Forissier30999122017-08-25 18:42:58 +0200313 cmd = self.arch_prefix('objdump')
314 if not elf or not cmd:
315 return
Jerome Forissierae252462018-05-25 15:07:28 +0200316 self._sections[elf_name] = []
Jerome Forissier1cbf7772018-09-07 17:08:23 +0200317 objdump = self.my_Popen([cmd, '--section-headers', elf])
Jerome Forissier30999122017-08-25 18:42:58 +0200318 for line in iter(objdump.stdout.readline, ''):
319 try:
320 _, name, size, vma, _, _, _ = line.split()
Jerome Forissier1d8c2a42018-09-07 17:05:21 +0200321 except ValueError:
Jerome Forissier30999122017-08-25 18:42:58 +0200322 if 'ALLOC' in line:
Jerome Forissierae252462018-05-25 15:07:28 +0200323 self._sections[elf_name].append([name, int(vma, 16),
324 int(size, 16)])
Jerome Forissier30999122017-08-25 18:42:58 +0200325
326 def overlaps(self, section, addr, size):
327 sec_addr = section[1]
328 sec_size = section[2]
329 if not size or not sec_size:
330 return False
Jerome Forissierae252462018-05-25 15:07:28 +0200331 return ((addr <= (sec_addr + sec_size - 1)) and
332 ((addr + size - 1) >= sec_addr))
Jerome Forissier30999122017-08-25 18:42:58 +0200333
Jerome Forissierae252462018-05-25 15:07:28 +0200334 def sections_in_region(self, addr, size, elf_idx):
Jerome Forissier30999122017-08-25 18:42:58 +0200335 ret = ''
336 addr = self.subtract_load_addr(addr)
337 if not addr:
338 return ''
339 iaddr = int(addr, 16)
340 isize = int(size, 16)
Jerome Forissierae252462018-05-25 15:07:28 +0200341 elf = self._elfs[int(elf_idx)][0]
342 if elf is None:
343 return ''
344 self.read_sections(elf)
345 if elf not in self._sections:
346 return ''
347 for s in self._sections[elf]:
Jerome Forissier30999122017-08-25 18:42:58 +0200348 if self.overlaps(s, iaddr, isize):
349 ret += ' ' + s[0]
350 return ret
351
Jerome Forissier733a15f2017-05-19 17:40:17 +0200352 def reset(self):
353 self._call_stack_found = False
Jerome Forissier733a15f2017-05-19 17:40:17 +0200354 if self._addr2line:
355 self._addr2line.terminate()
356 self._addr2line = None
Jerome Forissierae252462018-05-25 15:07:28 +0200357 self._addr2line_elf_name = None
Jerome Forissierd7204312017-09-04 17:58:52 +0200358 self._arch = None
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200359 self._saved_abort_line = ''
Jerome Forissierae252462018-05-25 15:07:28 +0200360 self._sections = {} # {elf_name: [[name, addr, size], ...], ...}
361 self._regions = [] # [[addr, size, elf_idx, saved line], ...]
362 self._elfs = {0: ["tee.elf", 0]} # {idx: [uuid, load_addr], ...}
Sumit Gargc90b6662019-03-28 18:24:21 +0530363 self._func_graph_found = False
364 self._func_graph_skip_line = True
Jerome Forissier733a15f2017-05-19 17:40:17 +0200365
Jerome Forissier095567e2018-05-29 17:42:34 +0200366 def pretty_print_path(self, path):
367 if self._strip_path:
368 return re.sub(re.escape(self._strip_path) + '/*', '', path)
369 return path
370
Jerome Forissier733a15f2017-05-19 17:40:17 +0200371 def write(self, line):
Jerome Forissier6e7c2e92018-11-14 11:02:49 +0100372 if self._call_stack_found:
373 match = re.search(STACK_ADDR_RE, line)
Jerome Forissier30999122017-08-25 18:42:58 +0200374 if match:
375 addr = match.group('addr')
Jerome Forissier6e7c2e92018-11-14 11:02:49 +0100376 pre = match.start('addr')
377 post = match.end('addr')
378 self._out.write(line[:pre])
379 self._out.write(addr)
380 res = self.resolve(addr)
381 res = self.pretty_print_path(res)
382 self._out.write(' ' + res)
383 self._out.write(line[post:])
Jerome Forissierae252462018-05-25 15:07:28 +0200384 return
Jerome Forissier6e7c2e92018-11-14 11:02:49 +0100385 else:
Jerome Forissier27b83ad2017-10-06 13:37:35 +0200386 self.reset()
Sumit Gargc90b6662019-03-28 18:24:21 +0530387 if self._func_graph_found:
388 match = re.search(GRAPH_ADDR_RE, line)
389 match_re = re.search(GRAPH_RE, line)
390 if match:
391 addr = match.group('addr')
392 pre = match.start('addr')
393 post = match.end('addr')
394 self._out.write(line[:pre])
395 res = self.resolve(addr)
396 res_arr = re.split(' ', res)
397 self._out.write(res_arr[0])
398 self._out.write(line[post:])
399 self._func_graph_skip_line = False
400 return
401 elif match_re:
402 self._out.write(line)
403 return
404 elif self._func_graph_skip_line:
405 return
406 else:
407 self.reset()
Jerome Forissier6e7c2e92018-11-14 11:02:49 +0100408 match = re.search(REGION_RE, line)
409 if match:
410 # Region table: save info for later processing once
411 # we know which UUID corresponds to which ELF index
412 addr = match.group('addr')
413 size = match.group('size')
414 elf_idx = match.group('elf_idx')
415 self._regions.append([addr, size, elf_idx, line])
416 return
417 match = re.search(ELF_LIST_RE, line)
418 if match:
419 # ELF list: save info for later. Region table and ELF list
420 # will be displayed when the call stack is reached
421 i = int(match.group('idx'))
422 self._elfs[i] = [match.group('uuid'), match.group('load_addr'),
423 line]
424 return
425 match = re.search(CALL_STACK_RE, line)
426 if match:
427 self._call_stack_found = True
428 if self._regions:
429 for r in self._regions:
430 r_addr = r[0]
431 r_size = r[1]
432 elf_idx = r[2]
433 saved_line = r[3]
434 if elf_idx is None:
435 self._out.write(saved_line)
436 else:
437 self._out.write(saved_line.strip() +
438 self.sections_in_region(r_addr,
439 r_size,
440 elf_idx) +
441 '\n')
442 if self._elfs:
443 for k in self._elfs:
444 e = self._elfs[k]
445 if (len(e) >= 3):
446 # TA executable or library
447 self._out.write(e[2].strip())
448 elf = self.get_elf(e[0])
449 if elf:
450 rpath = os.path.realpath(elf)
451 path = self.pretty_print_path(rpath)
452 self._out.write(' (' + path + ')')
453 self._out.write('\n')
454 # Here is a good place to resolve the abort address because we
455 # have all the information we need
456 if self._saved_abort_line:
457 self._out.write(self.process_abort(self._saved_abort_line))
Sumit Gargc90b6662019-03-28 18:24:21 +0530458 match = re.search(FUNC_GRAPH_RE, line)
459 if match:
460 self._func_graph_found = True
Jerome Forissier6e7c2e92018-11-14 11:02:49 +0100461 match = re.search(ABORT_ADDR_RE, line)
462 if match:
463 self.reset()
464 # At this point the arch and TA load address are unknown.
465 # Save the line so We can translate the abort address later.
466 self._saved_abort_line = line
467 self._out.write(line)
Jerome Forissier733a15f2017-05-19 17:40:17 +0200468
469 def flush(self):
470 self._out.flush()
471
Jerome Forissierae252462018-05-25 15:07:28 +0200472
Jerome Forissier733a15f2017-05-19 17:40:17 +0200473def main():
474 args = get_args()
475 if args.dir:
476 # Flatten list in case -d is used several times *and* with multiple
477 # arguments
478 args.dirs = [item for sublist in args.dir for item in sublist]
479 else:
480 args.dirs = []
481 symbolizer = Symbolizer(sys.stdout, args.dirs, args.strip_path)
482
Jerome Forissier6b4fc672019-09-23 09:49:32 +0200483 fd = sys.stdin.fileno()
Jerome Forissier20d152b2019-09-25 20:28:33 +0200484 isatty = os.isatty(fd)
485 if isatty:
486 old = termios.tcgetattr(fd)
487 new = termios.tcgetattr(fd)
488 new[3] = new[3] & ~termios.ECHO # lflags
Jerome Forissier6b4fc672019-09-23 09:49:32 +0200489 try:
Jerome Forissier20d152b2019-09-25 20:28:33 +0200490 if isatty:
491 termios.tcsetattr(fd, termios.TCSADRAIN, new)
Jerome Forissier6b4fc672019-09-23 09:49:32 +0200492 for line in sys.stdin:
493 symbolizer.write(line)
494 finally:
495 symbolizer.flush()
Jerome Forissier20d152b2019-09-25 20:28:33 +0200496 if isatty:
497 termios.tcsetattr(fd, termios.TCSADRAIN, old)
Jerome Forissier733a15f2017-05-19 17:40:17 +0200498
Jerome Forissier1d8c2a42018-09-07 17:05:21 +0200499
Jerome Forissier733a15f2017-05-19 17:40:17 +0200500if __name__ == "__main__":
501 main()