]>
git.ipfire.org Git - thirdparty/u-boot.git/blob - scripts/event_dump.py
2 # SPDX-License-Identifier: GPL-2.0+
4 """Decode the evspy_info linker list in a U-Boot ELF image"""
6 from argparse
import ArgumentParser
12 our_path
= os
.path
.dirname(os
.path
.realpath(__file__
))
13 src_path
= os
.path
.dirname(our_path
)
15 sys
.path
.insert(1, os
.path
.join(our_path
, '../tools'))
17 from binman
import elf
18 from u_boot_pylib
import tools
20 # A typical symbol looks like this:
21 # _u_boot_list_2_evspy_info_2_EVT_MISC_INIT_F_3_sandbox_misc_init_f
22 PREFIX_FULL
= '_u_boot_list_2_evspy_info_2_'
23 PREFIX_SIMPLE
= '_u_boot_list_2_evspy_info_simple_2_'
24 RE_EVTYPE_FULL
= re
.compile('%s(.*)_3_.*' % PREFIX_FULL
)
25 RE_EVTYPE_SIMPLE
= re
.compile('%s(.*)_3_.*' % PREFIX_SIMPLE
)
27 def show_sym(fname
, data
, endian
, evtype
, sym
):
28 """Show information about an evspy entry
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
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]
45 # Get the data, which is a struct evspy_info
46 sym_data
= data
[sym
.offset
:sym
.offset
+ sym
.size
]
48 # Figure out the word size of the struct
49 func_size
= 4 if sym
.size
< 16 else 8
51 # Read the function name for evspy_info->func
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':
60 has_id
= sym
.size
in [12, 24]
62 # Find the address of evspy_info->id in the ELF
63 id_addr
= _unpack_val(sym_data
, 2)
65 # Get the file offset for that address
66 id_ofs
= elf
.GetFileOffset(fname
, id_addr
)
68 # Read out a nul-terminated string
69 id_data
= data
[id_ofs
:id_ofs
+ 80]
72 id_data
= id_data
[:pos
]
73 id_str
= id_data
.decode('utf-8')
77 # Find the file/line for the function
78 cmd
= ['addr2line', '-e', fname
, '%x' % func_addr
]
79 out
= tools
.run(*cmd
).strip()
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
))
86 def show_event_spy_list(fname
, endian
):
87 """Show a the event-spy- list from a U-Boot image
90 fname (str): Filename of ELF file
91 endian (str): Endianness to use ('little', 'big', 'auto')
93 syms
= elf
.GetSymbolFileOffset(fname
, [PREFIX_FULL
, PREFIX_SIMPLE
])
94 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():
98 m_evtype
= RE_EVTYPE_FULL
.search(name
)
100 m_evtype
= RE_EVTYPE_SIMPLE
.search(name
)
101 evtype
= m_evtype
.group(1)
102 show_sym(fname
, data
, endian
, evtype
, sym
)
108 argv (list of str): List of program arguments, excluding arvg[0]
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')
115 args
= parser
.parse_args(argv
)
116 show_event_spy_list(args
.elf
, args
.endian
)
118 if __name__
== "__main__":