blob: 24dfe2bda91fc17dfbe90a5f9e130687efb74233 [file] [log] [blame]
Simon Glass02489322022-03-04 08:43:07 -07001#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0+
3
4"""Decode the evspy_info linker list in a U-Boot ELF image"""
5
6from argparse import ArgumentParser
7import os
8import re
9import struct
10import sys
11
12our_path = os.path.dirname(os.path.realpath(__file__))
13src_path = os.path.dirname(our_path)
14
15sys.path.insert(1, os.path.join(our_path, '../tools'))
16
17from binman import elf
Simon Glass131444f2023-02-23 18:18:04 -070018from u_boot_pylib import tools
Simon Glass02489322022-03-04 08:43:07 -070019
Simon Glassb169e212022-09-06 20:26:56 -060020# A typical symbol looks like this:
21# _u_boot_list_2_evspy_info_2_EVT_MISC_INIT_F_3_sandbox_misc_init_f
Simon Glass3bfbedd2023-08-21 21:16:48 -060022PREFIX_FULL = '_u_boot_list_2_evspy_info_2_'
23PREFIX_SIMPLE = '_u_boot_list_2_evspy_info_simple_2_'
24RE_EVTYPE_FULL = re.compile('%s(.*)_3_.*' % PREFIX_FULL)
25RE_EVTYPE_SIMPLE = re.compile('%s(.*)_3_.*' % PREFIX_SIMPLE)
Simon Glass02489322022-03-04 08:43:07 -070026
27def show_sym(fname, data, endian, evtype, sym):
28 """Show information about an evspy entry
29
30 Args:
31 fname (str): Filename of ELF file
32 data (bytes): Data for this symbol
33 endian (str): Endianness to use ('little', 'big', 'auto')
34 evtype (str): Event type, e.g. 'MISC_INIT_F'
35 sym (elf.Symbol): Symbol to show
36 """
37 def _unpack_val(sym_data, offset):
38 start = offset * func_size
39 val_data = sym_data[start:start + func_size]
40 fmt = '%s%s' % ('>' if endian == 'big' else '<',
41 'L' if func_size == 4 else 'Q')
42 val = struct.unpack(fmt, val_data)[0]
43 return val
44
45 # Get the data, which is a struct evspy_info
46 sym_data = data[sym.offset:sym.offset + sym.size]
47
48 # Figure out the word size of the struct
49 func_size = 4 if sym.size < 16 else 8
50
51 # Read the function name for evspy_info->func
52 while True:
53 # Switch to big-endian if we see a failure
54 func_addr = _unpack_val(sym_data, 0)
55 func_name = elf.GetSymbolFromAddress(fname, func_addr)
56 if not func_name and endian == 'auto':
57 endian = 'big'
58 else:
59 break
60 has_id = sym.size in [12, 24]
61 if has_id:
62 # Find the address of evspy_info->id in the ELF
63 id_addr = _unpack_val(sym_data, 2)
64
65 # Get the file offset for that address
66 id_ofs = elf.GetFileOffset(fname, id_addr)
67
68 # Read out a nul-terminated string
69 id_data = data[id_ofs:id_ofs + 80]
70 pos = id_data.find(0)
71 if pos:
72 id_data = id_data[:pos]
73 id_str = id_data.decode('utf-8')
74 else:
75 id_str = None
76
77 # Find the file/line for the function
78 cmd = ['addr2line', '-e', fname, '%x' % func_addr]
79 out = tools.run(*cmd).strip()
80
81 # Drop the full path if it is the current directory
82 if out.startswith(src_path):
83 out = out[len(src_path) + 1:]
84 print('%-20s %-30s %s' % (evtype, id_str or f'f:{func_name}', out))
85
86def show_event_spy_list(fname, endian):
87 """Show a the event-spy- list from a U-Boot image
88
89 Args:
90 fname (str): Filename of ELF file
91 endian (str): Endianness to use ('little', 'big', 'auto')
92 """
Simon Glass3bfbedd2023-08-21 21:16:48 -060093 syms = elf.GetSymbolFileOffset(fname, [PREFIX_FULL, PREFIX_SIMPLE])
Simon Glass02489322022-03-04 08:43:07 -070094 data = tools.read_file(fname)
95 print('%-20s %-30s %s' % ('Event type', 'Id', 'Source location'))
96 print('%-20s %-30s %s' % ('-' * 20, '-' * 30, '-' * 30))
97 for name, sym in syms.items():
Simon Glass3bfbedd2023-08-21 21:16:48 -060098 m_evtype = RE_EVTYPE_FULL.search(name)
99 if not m_evtype:
100 m_evtype = RE_EVTYPE_SIMPLE.search(name)
Simon Glass02489322022-03-04 08:43:07 -0700101 evtype = m_evtype .group(1)
102 show_sym(fname, data, endian, evtype, sym)
103
104def main(argv):
105 """Main program
106
107 Args:
108 argv (list of str): List of program arguments, excluding arvg[0]
109 """
110 epilog = 'Show a list of even spies in a U-Boot EFL file'
111 parser = ArgumentParser(epilog=epilog)
112 parser.add_argument('elf', type=str, help='ELF file to decode')
113 parser.add_argument('-e', '--endian', type=str, default='auto',
114 help='Big-endian image')
Simon Glass02489322022-03-04 08:43:07 -0700115 args = parser.parse_args(argv)
116 show_event_spy_list(args.elf, args.endian)
117
118if __name__ == "__main__":
119 main(sys.argv[1:])