mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-14 17:07:38 +00:00
4583c00236
The patman directory has a number of modules which are used by other tools in U-Boot. This makes it hard to package the tools using pypi since the common files must be copied along with the tool that uses them. To address this, move these files into a new u_boot_pylib library. This can be packaged separately and listed as a dependency of each tool. Signed-off-by: Simon Glass <sjg@chromium.org>
115 lines
3.7 KiB
Python
Executable file
115 lines
3.7 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: GPL-2.0+
|
|
|
|
"""Decode the evspy_info linker list in a U-Boot ELF image"""
|
|
|
|
from argparse import ArgumentParser
|
|
import os
|
|
import re
|
|
import struct
|
|
import sys
|
|
|
|
our_path = os.path.dirname(os.path.realpath(__file__))
|
|
src_path = os.path.dirname(our_path)
|
|
|
|
sys.path.insert(1, os.path.join(our_path, '../tools'))
|
|
|
|
from binman import elf
|
|
from u_boot_pylib import tools
|
|
|
|
# A typical symbol looks like this:
|
|
# _u_boot_list_2_evspy_info_2_EVT_MISC_INIT_F_3_sandbox_misc_init_f
|
|
PREFIX = '_u_boot_list_2_evspy_info_2_'
|
|
RE_EVTYPE = re.compile('%s(.*)_3_.*' % PREFIX)
|
|
|
|
def show_sym(fname, data, endian, evtype, sym):
|
|
"""Show information about an evspy entry
|
|
|
|
Args:
|
|
fname (str): Filename of ELF file
|
|
data (bytes): Data for this symbol
|
|
endian (str): Endianness to use ('little', 'big', 'auto')
|
|
evtype (str): Event type, e.g. 'MISC_INIT_F'
|
|
sym (elf.Symbol): Symbol to show
|
|
"""
|
|
def _unpack_val(sym_data, offset):
|
|
start = offset * func_size
|
|
val_data = sym_data[start:start + func_size]
|
|
fmt = '%s%s' % ('>' if endian == 'big' else '<',
|
|
'L' if func_size == 4 else 'Q')
|
|
val = struct.unpack(fmt, val_data)[0]
|
|
return val
|
|
|
|
# Get the data, which is a struct evspy_info
|
|
sym_data = data[sym.offset:sym.offset + sym.size]
|
|
|
|
# Figure out the word size of the struct
|
|
func_size = 4 if sym.size < 16 else 8
|
|
|
|
# Read the function name for evspy_info->func
|
|
while True:
|
|
# Switch to big-endian if we see a failure
|
|
func_addr = _unpack_val(sym_data, 0)
|
|
func_name = elf.GetSymbolFromAddress(fname, func_addr)
|
|
if not func_name and endian == 'auto':
|
|
endian = 'big'
|
|
else:
|
|
break
|
|
has_id = sym.size in [12, 24]
|
|
if has_id:
|
|
# Find the address of evspy_info->id in the ELF
|
|
id_addr = _unpack_val(sym_data, 2)
|
|
|
|
# Get the file offset for that address
|
|
id_ofs = elf.GetFileOffset(fname, id_addr)
|
|
|
|
# Read out a nul-terminated string
|
|
id_data = data[id_ofs:id_ofs + 80]
|
|
pos = id_data.find(0)
|
|
if pos:
|
|
id_data = id_data[:pos]
|
|
id_str = id_data.decode('utf-8')
|
|
else:
|
|
id_str = None
|
|
|
|
# Find the file/line for the function
|
|
cmd = ['addr2line', '-e', fname, '%x' % func_addr]
|
|
out = tools.run(*cmd).strip()
|
|
|
|
# Drop the full path if it is the current directory
|
|
if out.startswith(src_path):
|
|
out = out[len(src_path) + 1:]
|
|
print('%-20s %-30s %s' % (evtype, id_str or f'f:{func_name}', out))
|
|
|
|
def show_event_spy_list(fname, endian):
|
|
"""Show a the event-spy- list from a U-Boot image
|
|
|
|
Args:
|
|
fname (str): Filename of ELF file
|
|
endian (str): Endianness to use ('little', 'big', 'auto')
|
|
"""
|
|
syms = elf.GetSymbolFileOffset(fname, [PREFIX])
|
|
data = tools.read_file(fname)
|
|
print('%-20s %-30s %s' % ('Event type', 'Id', 'Source location'))
|
|
print('%-20s %-30s %s' % ('-' * 20, '-' * 30, '-' * 30))
|
|
for name, sym in syms.items():
|
|
m_evtype = RE_EVTYPE.search(name)
|
|
evtype = m_evtype .group(1)
|
|
show_sym(fname, data, endian, evtype, sym)
|
|
|
|
def main(argv):
|
|
"""Main program
|
|
|
|
Args:
|
|
argv (list of str): List of program arguments, excluding arvg[0]
|
|
"""
|
|
epilog = 'Show a list of even spies in a U-Boot EFL file'
|
|
parser = ArgumentParser(epilog=epilog)
|
|
parser.add_argument('elf', type=str, help='ELF file to decode')
|
|
parser.add_argument('-e', '--endian', type=str, default='auto',
|
|
help='Big-endian image')
|
|
args = parser.parse_args(argv)
|
|
show_event_spy_list(args.elf, args.endian)
|
|
|
|
if __name__ == "__main__":
|
|
main(sys.argv[1:])
|