[PATCH 11/12] event: Add a script to decode the event-spy list

Simon Glass sjg at chromium.org
Tue Dec 28 09:28:53 CET 2021


For debugging and dicoverability it is useful to be able to see a list of
each event spy in a U-Boot ELF file. Add a script which shows this, along
with the event type and the source location. This makes events a little
easier to use than weak functions, for example.

Add a basic sandbox test as well. We could provide a test for other
boards, but for now, few use events.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 MAINTAINERS                      |   2 +
 scripts/event_dump.py            | 117 +++++++++++++++++++++++++++++++
 test/py/tests/test_event_dump.py |  19 +++++
 3 files changed, 138 insertions(+)
 create mode 100755 scripts/event_dump.py
 create mode 100644 test/py/tests/test_event_dump.py

diff --git a/MAINTAINERS b/MAINTAINERS
index 117a7d6c985..c040fb83162 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -792,7 +792,9 @@ S:	Maintained
 F:	cmd/event.c
 F:	common/event.c
 F:	include/event.h
+F:	scripts/event_dump.py
 F:	test/common/event.c
+F:	test/py/tests/test_event_dump.py
 
 FASTBOOT
 S:	Orphaned
diff --git a/scripts/event_dump.py b/scripts/event_dump.py
new file mode 100755
index 00000000000..ce006ae31d1
--- /dev/null
+++ b/scripts/event_dump.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2020 Google LLC
+# Written by Simon Glass <sjg at chromium.org>
+
+"""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 patman import tools
+
+PREFIX = '_u_boot_list_2_evspy_info_2_'
+RE_EVTYPE = re.compile('%s(.*)' % 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.ReadFile(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')
+    parser.add_argument('-t', '--test', action='store_true',
+                        help='Big-endian image')
+    args = parser.parse_args(argv)
+    show_event_spy_list(args.elf, args.endian)
+
+if __name__ == "__main__":
+    main(sys.argv[1:])
diff --git a/test/py/tests/test_event_dump.py b/test/py/tests/test_event_dump.py
new file mode 100644
index 00000000000..6a5ea42a60a
--- /dev/null
+++ b/test/py/tests/test_event_dump.py
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2021 Google LLC
+# Written by Simon Glass <sjg at chromium.org>
+
+import pytest
+import u_boot_utils as util
+
+# This is only a partial test - coverting 64-bit sandbox. It does not test
+# big-endian images, nor 32-bit images
+ at pytest.mark.boardspec('sandbox')
+def test_event_dump(u_boot_console):
+    """Test that the "help" command can be executed."""
+    cons = u_boot_console
+    sandbox = cons.config.build_dir + '/u-boot'
+    out = util.run_and_log(cons, ['scripts/event_dump.py', sandbox])
+    expect = '''Event type            Id                              Source location
+--------------------  ------------------------------  ------------------------------
+EVT_MISC_INIT_F       sandbox_misc_init_f             arch/sandbox/cpu/start.c:'''
+    assert out[:len(expect)] == expect
-- 
2.34.1.448.ga2b2bfdf31-goog



More information about the U-Boot mailing list