From: "Alex Bennée" <alex.bennee@linaro.org>
To: qemu-devel@nongnu.org
Cc: "Palmer Dabbelt" <palmer@dabbelt.com>,
"Alexandre Iooss" <erdnaxe@crans.org>,
"Mahmoud Mandour" <ma.mandourr@gmail.com>,
qemu-riscv@nongnu.org,
"Daniel Henrique Barboza" <dbarboza@ventanamicro.com>,
"Thomas Huth" <thuth@redhat.com>,
"Peter Maydell" <peter.maydell@linaro.org>,
"Alex Bennée" <alex.bennee@linaro.org>,
"Alistair Francis" <alistair.francis@wdc.com>,
qemu-arm@nongnu.org, "Philippe Mathieu-Daudé" <philmd@linaro.org>,
"Weiwei Li" <liwei1518@gmail.com>,
"Pierrick Bouvier" <pierrick.bouvier@linaro.org>,
"Liu Zhiwei" <zhiwei_liu@linux.alibaba.com>
Subject: [PATCH 24/25] contrib/plugins/uftrace_symbols.py
Date: Mon, 22 Sep 2025 10:37:09 +0100 [thread overview]
Message-ID: <20250922093711.2768983-25-alex.bennee@linaro.org> (raw)
In-Reply-To: <20250922093711.2768983-1-alex.bennee@linaro.org>
From: Pierrick Bouvier <pierrick.bouvier@linaro.org>
usage: contrib/plugins/uftrace_symbols.py \
--prefix-symbols \
arm-trusted-firmware/build/qemu/debug/bl1/bl1.elf \
arm-trusted-firmware/build/qemu/debug/bl2/bl2.elf \
arm-trusted-firmware/build/qemu/debug/bl31/bl31.elf \
u-boot/u-boot:0x60000000 \
u-boot/u-boot.relocated:0x000000023f6b6000 \
linux/vmlinux
Will generate symbols and memory mapping files for uftrace, allowing to
have an enhanced trace, instead of raw addresses.
It takes a collection of elf files, and automatically find all their
symbols, and generate an ordered memory map based on that.
This script uses the python (native) pyelftools module.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Acked-by: Alex Bennée <alex.bennee@linaro.org>
Message-ID: <20250902075042.223990-9-pierrick.bouvier@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
contrib/plugins/uftrace_symbols.py | 152 +++++++++++++++++++++++++++++
1 file changed, 152 insertions(+)
create mode 100755 contrib/plugins/uftrace_symbols.py
diff --git a/contrib/plugins/uftrace_symbols.py b/contrib/plugins/uftrace_symbols.py
new file mode 100755
index 00000000000..b49e03203c8
--- /dev/null
+++ b/contrib/plugins/uftrace_symbols.py
@@ -0,0 +1,152 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Create symbols and mapping files for uftrace.
+#
+# Copyright 2025 Linaro Ltd
+# Author: Pierrick Bouvier <pierrick.bouvier@linaro.org>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import argparse
+import elftools # pip install pyelftools
+import os
+
+from elftools.elf.elffile import ELFFile
+from elftools.elf.sections import SymbolTableSection
+
+def elf_func_symbols(elf):
+ symbol_tables = [(idx, s) for idx, s in enumerate(elf.iter_sections())
+ if isinstance(s, SymbolTableSection)]
+ symbols = []
+ for _, section in symbol_tables:
+ for _, symbol in enumerate(section.iter_symbols()):
+ if symbol_size(symbol) == 0:
+ continue
+ type = symbol['st_info']['type']
+ if type == 'STT_FUNC' or type == 'STT_NOTYPE':
+ symbols.append(symbol)
+ symbols.sort(key = lambda x: symbol_addr(x))
+ return symbols
+
+def symbol_size(symbol):
+ return symbol['st_size']
+
+def symbol_addr(symbol):
+ addr = symbol['st_value']
+ # clamp addr to 48 bits, like uftrace entries
+ return addr & 0xffffffffffff
+
+def symbol_name(symbol):
+ return symbol.name
+
+class BinaryFile:
+ def __init__(self, path, map_offset):
+ self.fullpath = os.path.realpath(path)
+ self.map_offset = map_offset
+ with open(path, 'rb') as f:
+ self.elf = ELFFile(f)
+ self.symbols = elf_func_symbols(self.elf)
+
+ def path(self):
+ return self.fullpath
+
+ def addr_start(self):
+ return self.map_offset
+
+ def addr_end(self):
+ last_sym = self.symbols[-1]
+ return symbol_addr(last_sym) + symbol_size(last_sym) + self.map_offset
+
+ def generate_symbol_file(self, prefix_symbols):
+ binary_name = os.path.basename(self.fullpath)
+ sym_file_path = f'./uftrace.data/{binary_name}.sym'
+ print(f'{sym_file_path} ({len(self.symbols)} symbols)')
+ with open(sym_file_path, 'w') as sym_file:
+ # print hexadecimal addresses on 48 bits
+ addrx = "0>12x"
+ for s in self.symbols:
+ addr = symbol_addr(s)
+ addr = f'{addr:{addrx}}'
+ size = f'{symbol_size(s):{addrx}}'
+ name = symbol_name(s)
+ if prefix_symbols:
+ name = f'{binary_name}:{name}'
+ print(addr, size, 'T', name, file=sym_file)
+
+def parse_parameter(p):
+ s = p.split(":")
+ path = s[0]
+ if len(s) == 1:
+ return path, 0
+ if len(s) > 2:
+ raise ValueError('only one offset can be set')
+ offset = s[1]
+ if not offset.startswith('0x'):
+ err = f'offset "{offset}" is not an hexadecimal constant. '
+ err += 'It should starts with "0x".'
+ raise ValueError(err)
+ offset = int(offset, 16)
+ return path, offset
+
+def is_from_user_mode(map_file_path):
+ if os.path.exists(map_file_path):
+ with open(map_file_path, 'r') as map_file:
+ if not map_file.readline().startswith('# map stack on'):
+ return True
+ return False
+
+def generate_map(binaries):
+ map_file_path = './uftrace.data/sid-0.map'
+
+ if is_from_user_mode(map_file_path):
+ print(f'do not overwrite {map_file_path} generated from qemu-user')
+ return
+
+ mappings = []
+
+ # print hexadecimal addresses on 48 bits
+ addrx = "0>12x"
+
+ mappings += ['# map stack on highest address possible, to prevent uftrace']
+ mappings += ['# from considering any kernel address']
+ mappings += ['ffffffffffff-ffffffffffff rw-p 00000000 00:00 0 [stack]']
+
+ for b in binaries:
+ m = f'{b.addr_start():{addrx}}-{b.addr_end():{addrx}}'
+ m += f' r--p 00000000 00:00 0 {b.path()}'
+ mappings.append(m)
+
+ with open(map_file_path, 'w') as map_file:
+ print('\n'.join(mappings), file=map_file)
+ print(f'{map_file_path}')
+ print('\n'.join(mappings))
+
+def main():
+ parser = argparse.ArgumentParser(description=
+ 'generate symbol files for uftrace')
+ parser.add_argument('elf_file', nargs='+',
+ help='path to an ELF file. '
+ 'Use /path/to/file:0xdeadbeef to add a mapping offset.')
+ parser.add_argument('--prefix-symbols',
+ help='prepend binary name to symbols',
+ action=argparse.BooleanOptionalAction)
+ args = parser.parse_args()
+
+ if not os.path.exists('./uftrace.data'):
+ os.mkdir('./uftrace.data')
+
+ binaries = []
+ for file in args.elf_file:
+ path, offset = parse_parameter(file)
+ b = BinaryFile(path, offset)
+ binaries.append(b)
+ binaries.sort(key = lambda b: b.addr_end());
+
+ for b in binaries:
+ b.generate_symbol_file(args.prefix_symbols)
+
+ generate_map(binaries)
+
+if __name__ == '__main__':
+ main()
--
2.47.3
next prev parent reply other threads:[~2025-09-22 9:44 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-22 9:36 [PATCH 00/25] September maintainer updates (docs, plugins, semihosting) pre-PR Alex Bennée
2025-09-22 9:36 ` [PATCH 01/25] docs/devel: fix typo in code-provenance.rst Alex Bennée
2025-09-22 11:32 ` Thomas Huth
2025-09-22 19:37 ` Richard Henderson
2025-09-22 9:36 ` [PATCH 02/25] scripts/ci: add gitlab-failure-analysis script Alex Bennée
2025-09-22 9:36 ` [PATCH 03/25] checkpatch: Ignore removed lines in license check Alex Bennée
2025-09-22 9:36 ` [PATCH 04/25] semihosting/syscalls: compile once in system and per target for user mode Alex Bennée
2025-09-22 9:36 ` [PATCH 05/25] semihosting/syscalls: replace uint64_t with vaddr where appropriate Alex Bennée
2025-09-22 9:36 ` [PATCH 06/25] semihosting/guestfd: compile once for system/user Alex Bennée
2025-09-22 9:36 ` [PATCH 07/25] semihosting/arm-compat-semi: change common_semi_sys_exit_extended Alex Bennée
2025-09-22 9:36 ` [PATCH 08/25] target/riscv/common-semi-target: remove sizeof(target_ulong) Alex Bennée
2025-09-22 9:36 ` [PATCH 09/25] target/{arm, riscv}/common-semi-target: eradicate target_ulong Alex Bennée
2025-09-22 9:36 ` [PATCH 10/25] include/semihosting/common-semi: extract common_semi API Alex Bennée
2025-09-22 9:36 ` [PATCH 11/25] semihosting/arm-compat-semi: eradicate sizeof(target_ulong) Alex Bennée
2025-09-22 11:52 ` Philippe Mathieu-Daudé
2025-09-22 9:36 ` [PATCH 12/25] semihosting/arm-compat-semi: replace target_ulong with vaddr Alex Bennée
2025-09-22 11:53 ` Philippe Mathieu-Daudé
2025-09-22 12:43 ` Alex Bennée
2025-09-25 21:13 ` Pierrick Bouvier
2025-09-22 9:36 ` [PATCH 13/25] semihosting/arm-compat-semi: eradicate target_long Alex Bennée
2025-09-22 9:36 ` [PATCH 14/25] semihosting/arm-compat-semi: remove dependency on cpu.h Alex Bennée
2025-09-22 9:37 ` [PATCH 15/25] semihosting/arm-compat-semi: compile once in system and per target for user mode Alex Bennée
2025-09-22 9:37 ` [PATCH 16/25] contrib/plugins/execlog: Explicitly check for qemu_plugin_read_register() failure Alex Bennée
2025-09-22 9:37 ` [PATCH 17/25] contrib/plugins/uftrace: skeleton file Alex Bennée
2025-09-22 9:37 ` [PATCH 18/25] contrib/plugins/uftrace: define cpu operations and implement aarch64 Alex Bennée
2025-09-22 9:37 ` [PATCH 19/25] contrib/plugins/uftrace: track callstack Alex Bennée
2025-09-22 9:37 ` [PATCH 20/25] contrib/plugins/uftrace: implement tracing Alex Bennée
2025-09-22 9:37 ` [PATCH 21/25] contrib/plugins/uftrace: implement privilege level tracing Alex Bennée
2025-09-22 9:37 ` [PATCH 22/25] contrib/plugins/uftrace: generate additional files for uftrace Alex Bennée
2025-09-22 9:37 ` [PATCH 23/25] contrib/plugins/uftrace: implement x64 support Alex Bennée
2025-09-22 9:37 ` Alex Bennée [this message]
2025-09-22 9:37 ` [PATCH 25/25] contrib/plugins/uftrace: add documentation Alex Bennée
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250922093711.2768983-25-alex.bennee@linaro.org \
--to=alex.bennee@linaro.org \
--cc=alistair.francis@wdc.com \
--cc=dbarboza@ventanamicro.com \
--cc=erdnaxe@crans.org \
--cc=liwei1518@gmail.com \
--cc=ma.mandourr@gmail.com \
--cc=palmer@dabbelt.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=pierrick.bouvier@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=qemu-riscv@nongnu.org \
--cc=thuth@redhat.com \
--cc=zhiwei_liu@linux.alibaba.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).