blob: 631ae6e11d581fc0b196be733c2ec6c437c1adb6 [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]
Sumit Garg099918f2019-09-05 13:23:01 +0530180 # In case address is not found in TA ELF file, fallback to tee.elf
181 # especially to symbolize mixed (user-space and kernel) addresses
182 # which is true when syscall ftrace is enabled along with TA
183 # ftrace.
184 return '0x0'
Jerome Forissierae252462018-05-25 15:07:28 +0200185 else:
186 # tee.elf
187 return '0x0'
188
189 def elf_for_addr(self, addr):
190 l_addr = self.elf_load_addr(addr)
191 if l_addr is None:
192 return None
193 if l_addr is '0x0':
194 return 'tee.elf'
195 for k in self._elfs:
196 e = self._elfs[k]
197 if int(e[1], 16) == int(l_addr, 16):
198 return e[0]
199 return None
Jerome Forissier733a15f2017-05-19 17:40:17 +0200200
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200201 def subtract_load_addr(self, addr):
Jerome Forissierae252462018-05-25 15:07:28 +0200202 l_addr = self.elf_load_addr(addr)
203 if l_addr is None:
204 return None
205 if int(l_addr, 16) > int(addr, 16):
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200206 return ''
Jerome Forissierae252462018-05-25 15:07:28 +0200207 return '0x{:x}'.format(int(addr, 16) - int(l_addr, 16))
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200208
209 def resolve(self, addr):
210 reladdr = self.subtract_load_addr(addr)
Jerome Forissierae252462018-05-25 15:07:28 +0200211 self.spawn_addr2line(self.elf_for_addr(addr))
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200212 if not reladdr or not self._addr2line:
Jerome Forissier733a15f2017-05-19 17:40:17 +0200213 return '???'
214 try:
Rouven Czerwinskibbaeed42019-08-07 20:07:00 +0200215 print(reladdr, file=self._addr2line.stdin)
Jerome Forissier733a15f2017-05-19 17:40:17 +0200216 ret = self._addr2line.stdout.readline().rstrip('\n')
217 except IOError:
218 ret = '!!!'
219 return ret
220
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200221 def symbol_plus_offset(self, addr):
222 ret = ''
223 prevsize = 0
224 reladdr = self.subtract_load_addr(addr)
Jerome Forissierae252462018-05-25 15:07:28 +0200225 elf_name = self.elf_for_addr(addr)
226 if elf_name is None:
227 return ''
228 elf = self.get_elf(elf_name)
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200229 cmd = self.arch_prefix('nm')
230 if not reladdr or not elf or not cmd:
231 return ''
Jerome Forissier30999122017-08-25 18:42:58 +0200232 ireladdr = int(reladdr, 16)
Jerome Forissier1cbf7772018-09-07 17:08:23 +0200233 nm = self.my_Popen([cmd, '--numeric-sort', '--print-size', elf])
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200234 for line in iter(nm.stdout.readline, ''):
235 try:
236 addr, size, _, name = line.split()
Jerome Forissier1d8c2a42018-09-07 17:05:21 +0200237 except ValueError:
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200238 # Size is missing
Jerome Forissierb4815422018-06-20 09:43:33 +0200239 try:
240 addr, _, name = line.split()
241 size = '0'
Jerome Forissier1d8c2a42018-09-07 17:05:21 +0200242 except ValueError:
Jerome Forissierb4815422018-06-20 09:43:33 +0200243 # E.g., undefined (external) symbols (line = "U symbol")
244 continue
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200245 iaddr = int(addr, 16)
246 isize = int(size, 16)
247 if iaddr == ireladdr:
248 ret = name
249 break
250 if iaddr < ireladdr and iaddr + isize >= ireladdr:
251 offs = ireladdr - iaddr
252 ret = name + '+' + str(offs)
253 break
254 if iaddr > ireladdr and prevsize == 0:
255 offs = iaddr + ireladdr
256 ret = prevname + '+' + str(offs)
257 break
258 prevsize = size
259 prevname = name
260 nm.terminate()
261 return ret
262
263 def section_plus_offset(self, addr):
264 ret = ''
265 reladdr = self.subtract_load_addr(addr)
Jerome Forissierae252462018-05-25 15:07:28 +0200266 elf_name = self.elf_for_addr(addr)
267 if elf_name is None:
268 return ''
269 elf = self.get_elf(elf_name)
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200270 cmd = self.arch_prefix('objdump')
271 if not reladdr or not elf or not cmd:
272 return ''
Jerome Forissier30999122017-08-25 18:42:58 +0200273 iaddr = int(reladdr, 16)
Jerome Forissier1cbf7772018-09-07 17:08:23 +0200274 objdump = self.my_Popen([cmd, '--section-headers', elf])
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200275 for line in iter(objdump.stdout.readline, ''):
276 try:
277 idx, name, size, vma, lma, offs, algn = line.split()
Jerome Forissier1d8c2a42018-09-07 17:05:21 +0200278 except ValueError:
Jerome Forissierae252462018-05-25 15:07:28 +0200279 continue
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200280 ivma = int(vma, 16)
281 isize = int(size, 16)
282 if ivma == iaddr:
283 ret = name
284 break
285 if ivma < iaddr and ivma + isize >= iaddr:
286 offs = iaddr - ivma
287 ret = name + '+' + str(offs)
288 break
289 objdump.terminate()
290 return ret
291
292 def process_abort(self, line):
293 ret = ''
294 match = re.search(ABORT_ADDR_RE, line)
295 addr = match.group('addr')
296 pre = match.start('addr')
297 post = match.end('addr')
298 sym = self.symbol_plus_offset(addr)
299 sec = self.section_plus_offset(addr)
300 if sym or sec:
301 ret += line[:pre]
302 ret += addr
303 if sym:
304 ret += ' ' + sym
305 if sec:
306 ret += ' ' + sec
307 ret += line[post:]
308 return ret
309
Jerome Forissier30999122017-08-25 18:42:58 +0200310 # Return all ELF sections with the ALLOC flag
Jerome Forissierae252462018-05-25 15:07:28 +0200311 def read_sections(self, elf_name):
312 if elf_name is None:
Jerome Forissier30999122017-08-25 18:42:58 +0200313 return
Jerome Forissierae252462018-05-25 15:07:28 +0200314 if elf_name in self._sections:
315 return
316 elf = self.get_elf(elf_name)
Jerome Forissier30999122017-08-25 18:42:58 +0200317 cmd = self.arch_prefix('objdump')
318 if not elf or not cmd:
319 return
Jerome Forissierae252462018-05-25 15:07:28 +0200320 self._sections[elf_name] = []
Jerome Forissier1cbf7772018-09-07 17:08:23 +0200321 objdump = self.my_Popen([cmd, '--section-headers', elf])
Jerome Forissier30999122017-08-25 18:42:58 +0200322 for line in iter(objdump.stdout.readline, ''):
323 try:
324 _, name, size, vma, _, _, _ = line.split()
Jerome Forissier1d8c2a42018-09-07 17:05:21 +0200325 except ValueError:
Jerome Forissier30999122017-08-25 18:42:58 +0200326 if 'ALLOC' in line:
Jerome Forissierae252462018-05-25 15:07:28 +0200327 self._sections[elf_name].append([name, int(vma, 16),
328 int(size, 16)])
Jerome Forissier30999122017-08-25 18:42:58 +0200329
330 def overlaps(self, section, addr, size):
331 sec_addr = section[1]
332 sec_size = section[2]
333 if not size or not sec_size:
334 return False
Jerome Forissierae252462018-05-25 15:07:28 +0200335 return ((addr <= (sec_addr + sec_size - 1)) and
336 ((addr + size - 1) >= sec_addr))
Jerome Forissier30999122017-08-25 18:42:58 +0200337
Jerome Forissierae252462018-05-25 15:07:28 +0200338 def sections_in_region(self, addr, size, elf_idx):
Jerome Forissier30999122017-08-25 18:42:58 +0200339 ret = ''
340 addr = self.subtract_load_addr(addr)
341 if not addr:
342 return ''
343 iaddr = int(addr, 16)
344 isize = int(size, 16)
Jerome Forissierae252462018-05-25 15:07:28 +0200345 elf = self._elfs[int(elf_idx)][0]
346 if elf is None:
347 return ''
348 self.read_sections(elf)
349 if elf not in self._sections:
350 return ''
351 for s in self._sections[elf]:
Jerome Forissier30999122017-08-25 18:42:58 +0200352 if self.overlaps(s, iaddr, isize):
353 ret += ' ' + s[0]
354 return ret
355
Jerome Forissier733a15f2017-05-19 17:40:17 +0200356 def reset(self):
357 self._call_stack_found = False
Jerome Forissier733a15f2017-05-19 17:40:17 +0200358 if self._addr2line:
359 self._addr2line.terminate()
360 self._addr2line = None
Jerome Forissierae252462018-05-25 15:07:28 +0200361 self._addr2line_elf_name = None
Jerome Forissierd7204312017-09-04 17:58:52 +0200362 self._arch = None
Jerome Forissier142c5cc2017-08-24 15:07:17 +0200363 self._saved_abort_line = ''
Jerome Forissierae252462018-05-25 15:07:28 +0200364 self._sections = {} # {elf_name: [[name, addr, size], ...], ...}
365 self._regions = [] # [[addr, size, elf_idx, saved line], ...]
366 self._elfs = {0: ["tee.elf", 0]} # {idx: [uuid, load_addr], ...}
Sumit Gargc90b6662019-03-28 18:24:21 +0530367 self._func_graph_found = False
368 self._func_graph_skip_line = True
Jerome Forissier733a15f2017-05-19 17:40:17 +0200369
Jerome Forissier095567e2018-05-29 17:42:34 +0200370 def pretty_print_path(self, path):
371 if self._strip_path:
372 return re.sub(re.escape(self._strip_path) + '/*', '', path)
373 return path
374
Jerome Forissier733a15f2017-05-19 17:40:17 +0200375 def write(self, line):
Jerome Forissier6e7c2e92018-11-14 11:02:49 +0100376 if self._call_stack_found:
377 match = re.search(STACK_ADDR_RE, line)
Jerome Forissier30999122017-08-25 18:42:58 +0200378 if match:
379 addr = match.group('addr')
Jerome Forissier6e7c2e92018-11-14 11:02:49 +0100380 pre = match.start('addr')
381 post = match.end('addr')
382 self._out.write(line[:pre])
383 self._out.write(addr)
384 res = self.resolve(addr)
385 res = self.pretty_print_path(res)
386 self._out.write(' ' + res)
387 self._out.write(line[post:])
Jerome Forissierae252462018-05-25 15:07:28 +0200388 return
Jerome Forissier6e7c2e92018-11-14 11:02:49 +0100389 else:
Jerome Forissier27b83ad2017-10-06 13:37:35 +0200390 self.reset()
Sumit Gargc90b6662019-03-28 18:24:21 +0530391 if self._func_graph_found:
392 match = re.search(GRAPH_ADDR_RE, line)
393 match_re = re.search(GRAPH_RE, line)
394 if match:
395 addr = match.group('addr')
396 pre = match.start('addr')
397 post = match.end('addr')
398 self._out.write(line[:pre])
399 res = self.resolve(addr)
400 res_arr = re.split(' ', res)
401 self._out.write(res_arr[0])
402 self._out.write(line[post:])
403 self._func_graph_skip_line = False
404 return
405 elif match_re:
406 self._out.write(line)
407 return
408 elif self._func_graph_skip_line:
409 return
410 else:
411 self.reset()
Jerome Forissier6e7c2e92018-11-14 11:02:49 +0100412 match = re.search(REGION_RE, line)
413 if match:
414 # Region table: save info for later processing once
415 # we know which UUID corresponds to which ELF index
416 addr = match.group('addr')
417 size = match.group('size')
418 elf_idx = match.group('elf_idx')
419 self._regions.append([addr, size, elf_idx, line])
420 return
421 match = re.search(ELF_LIST_RE, line)
422 if match:
423 # ELF list: save info for later. Region table and ELF list
424 # will be displayed when the call stack is reached
425 i = int(match.group('idx'))
426 self._elfs[i] = [match.group('uuid'), match.group('load_addr'),
427 line]
428 return
429 match = re.search(CALL_STACK_RE, line)
430 if match:
431 self._call_stack_found = True
432 if self._regions:
433 for r in self._regions:
434 r_addr = r[0]
435 r_size = r[1]
436 elf_idx = r[2]
437 saved_line = r[3]
438 if elf_idx is None:
439 self._out.write(saved_line)
440 else:
441 self._out.write(saved_line.strip() +
442 self.sections_in_region(r_addr,
443 r_size,
444 elf_idx) +
445 '\n')
446 if self._elfs:
447 for k in self._elfs:
448 e = self._elfs[k]
449 if (len(e) >= 3):
450 # TA executable or library
451 self._out.write(e[2].strip())
452 elf = self.get_elf(e[0])
453 if elf:
454 rpath = os.path.realpath(elf)
455 path = self.pretty_print_path(rpath)
456 self._out.write(' (' + path + ')')
457 self._out.write('\n')
458 # Here is a good place to resolve the abort address because we
459 # have all the information we need
460 if self._saved_abort_line:
461 self._out.write(self.process_abort(self._saved_abort_line))
Sumit Gargc90b6662019-03-28 18:24:21 +0530462 match = re.search(FUNC_GRAPH_RE, line)
463 if match:
464 self._func_graph_found = True
Jerome Forissier6e7c2e92018-11-14 11:02:49 +0100465 match = re.search(ABORT_ADDR_RE, line)
466 if match:
467 self.reset()
468 # At this point the arch and TA load address are unknown.
469 # Save the line so We can translate the abort address later.
470 self._saved_abort_line = line
471 self._out.write(line)
Jerome Forissier733a15f2017-05-19 17:40:17 +0200472
473 def flush(self):
474 self._out.flush()
475
Jerome Forissierae252462018-05-25 15:07:28 +0200476
Jerome Forissier733a15f2017-05-19 17:40:17 +0200477def main():
478 args = get_args()
479 if args.dir:
480 # Flatten list in case -d is used several times *and* with multiple
481 # arguments
482 args.dirs = [item for sublist in args.dir for item in sublist]
483 else:
484 args.dirs = []
485 symbolizer = Symbolizer(sys.stdout, args.dirs, args.strip_path)
486
Jerome Forissier6b4fc672019-09-23 09:49:32 +0200487 fd = sys.stdin.fileno()
Jerome Forissier20d152b2019-09-25 20:28:33 +0200488 isatty = os.isatty(fd)
489 if isatty:
490 old = termios.tcgetattr(fd)
491 new = termios.tcgetattr(fd)
492 new[3] = new[3] & ~termios.ECHO # lflags
Jerome Forissier6b4fc672019-09-23 09:49:32 +0200493 try:
Jerome Forissier20d152b2019-09-25 20:28:33 +0200494 if isatty:
495 termios.tcsetattr(fd, termios.TCSADRAIN, new)
Jerome Forissier6b4fc672019-09-23 09:49:32 +0200496 for line in sys.stdin:
497 symbolizer.write(line)
498 finally:
499 symbolizer.flush()
Jerome Forissier20d152b2019-09-25 20:28:33 +0200500 if isatty:
501 termios.tcsetattr(fd, termios.TCSADRAIN, old)
Jerome Forissier733a15f2017-05-19 17:40:17 +0200502
Jerome Forissier1d8c2a42018-09-07 17:05:21 +0200503
Jerome Forissier733a15f2017-05-19 17:40:17 +0200504if __name__ == "__main__":
505 main()