Re: [PATCH perf-tools-next v6 0/5] perf trace: Symbolise kernel virtual addresses and function pointers

From: Ian Rogers

Date: Mon Aug 24 2026 - 12:31:04 EST


On Mon, Aug 24, 2026 at 6:31 AM Aaron Tomlin <atomlin@xxxxxxxxxxx> wrote:
>
> When inspecting kernel execution flows using perf trace (e.g., when
> monitoring workqueues, delayed work items, timer callbacks, etc.),
> tracepoint payload arguments containing raw kernel virtual addresses are
> currently rendered as hexadecimal values (e.g., 0xffffffff81234567).
>
> This requires manual symbol lookups against /proc/kallsyms or vmlinux to
> identify the underlying kernel function being executed.
>
> This patch series enhances perf trace by introducing kernel virtual address
> and function pointer symbolisation using perf's native symbol engine
> (i.e., machine__find_kernel_symbol()).
>
> Before:
> workqueue:workqueue_execute_end(work: 0xffffffffab2f1420, function: 0xffffffffa8046b50)
>
> After:
> workqueue:workqueue_execute_end(work: 0xffff8ac2c420f270, function: wb_update_bandwidth_workfn)
>
> Patch 1 fixes a pre-existing error handling issue in btf_struct_scnprintf()
> where negative error return codes from btf_dump__dump_type_data() bypassed
> the error check and erroneously advanced the augmented arguments buffer.
>
> Patch 2 introduces the syscall_arg__scnprintf_ksym() (SCA_KSYM) beautifier,
> which resolves virtual addresses via machine__find_kernel_symbol(),
> formatting them as symbol_name+offset (or "NULL", with a graceful
> hexadecimal fallback upon lookup failure).
>
> Patch 3 updates event format initialisation in
> syscall_arg_fmt__init_array() to automatically assign SCA_KSYM to non-array
> tracepoint fields typed as function pointers (such as typedefs ending in
> "_func_t" or "_fn", or function prototypes matching "(*)"). It also
> registers common function pointer, callback, and callsite field names
> (e.g., "action", "call_site", "callback", "caller", "caller_ip",
> "callsite", "cb", "fn", "func", "function", "handler", "location") in
> syscall_arg_fmts__by_name[]. To prevent misclassifying enums or 32-bit
> integers on 32-bit architectures, helper guards (field_is_ptr_sized(),
> field_is_enum(), and field_is_plain_int()) ensure SCA_KSYM is strictly
> assigned to pointer-sized fields and 64-bit scalars while allowing enums to
> fall through to BTF pretty-printing. It also removes the legacy
> trace__field_is_ip() hex override in trace__fprintf_tp_fields().
>
> Patch 4 extends BTF pretty-printing in trace__btf_scnprintf() with
> btf_is_func_ptr() to automatically traverse BTF type hierarchies (including
> nested typedefs and qualifiers) and route kernel function pointer arguments
> to SCA_KSYM when BTF metadata is available. It strictly enforces a single
> pointer indirection limit and validates type signatures against extra
> pointer asterisks to prevent multi-level pointers from being
> mis-symbolised.
>
> Patch 5 adds an automated regression test script, trace_ksym_beautifier.sh,
> to verify kernel symbol beautification across both virtual address fields
> and function pointer fields.
>
> Changes since v5:
>
> - Introduced patch to correct error-checking in btf_struct_scnprintf() to
> prevent erroneously advancing arg->augmented.args on negative error
> returns
>
> - Added helper functions field_is_enum(), field_is_plain_int(), and
> field_is_ptr_sized() in Patch 3 to guard SCA_KSYM assignment from
> colliding with 4-byte enum or integer fields on 32-bit architectures
> while supporting 64-bit scalar addresses (e.g., u64 caller_ip)
>
> - Updated btf_is_func_ptr() in Patch 4 to enforce a strict single-pointer
> limit (nr_ptrs == 1) with early termination on multi-level pointers,
> and added a type-string pointer check in trace__btf_scnprintf() to reject
> function pointer typedefs with extra pointer indirections
>
> - Removed test_ksym_btf() from trace_ksym_beautifier.sh in Patch 5,
> refocusing the test on verifying SCA_KSYM symbolisation across both
> virtual address and function pointer fields
>
> - Link to v5: https://lore.kernel.org/lkml/20260822213558.704018-1-atomlin@xxxxxxxxxxx/
>
> Changes since v4:
>
> - Added a non-array guard (!(field->flags & TEP_FIELD_IS_ARRAY)) to the
> type-signature heuristic in syscall_arg_fmt__init_array(), preventing
> array fields matching "(*)", "_func_t", or "_fn" from erroneously
> receiving SCA_KSYM
>
> - Replaced host sizeof(void *) check with tep_get_long_size() to support
> cross-architecture analysis of 32-bit trace data on 64-bit hosts
>
> - Added deterministic workloads to trace_ksym_beautifier.sh to prevent
> indefinite hangs on quiescent systems
>
> - Replaced csd:csd_function_entry in test_ksym_btf() with
> timer:hrtimer_start to ensure test reliability on both SMP and
> uniprocessor (CONFIG_SMP=n) systems
>
> - Link to v4: https://lore.kernel.org/lkml/20260821204930.679027-1-atomlin@xxxxxxxxxxx/
>
> Changes since v3:
>
> - Added "caller_ip" to syscall_arg_fmts__by_name[] in alphabetical order
> to symbolise instruction pointer fields
>
> - Guarded SCA_KSYM auto-assignment in syscall_arg_fmt__init_array() to
> only match actual pointer fields or pointer-sized non-array scalars,
> allowing unmatched fields to fall through to subsequent type checks
>
> - Fixed btf_struct_scnprintf() to only dump struct data for augmented
> input parameters, preventing un-augmented output pointers from dumping
> empty "{}" instead of falling back to hexadecimal pointer addresses.
> Also ensured btf_dump is properly freed on error exits
>
> - Updated test_ksym_btf() to trace csd:csd_function_entry with --force-btf
> instead of call_site, directly verifying function pointer symbolisation
>
> - Link to v3: https://lore.kernel.org/lkml/20260820211100.649142-1-atomlin@xxxxxxxxxxx/
>
> Changes since v2:
>
> - Populated syscall_arg_fmts__by_name[] with common function pointer,
> callback, handler, and callsite field names ("action", "call_site",
> "callback", "caller", "callsite", "cb", "fn", "func", "function",
> "handler", "location")
>
> - Checked syscall_arg_fmt__find_by_name() prior to generic pointer
> fallbacks in syscall_arg_fmt__init_array(), and dropped the inline
> 64-bit size check to ensure 32-bit and cross-platform compatibility
>
> - Removed legacy trace__field_is_ip() in trace__fprintf_tp_fields() to
> allow "call_site" and "caller_ip" to be beautified with SCA_KSYM rather
> than being forced to raw hexadecimal
>
> - Simplified btf_is_func_ptr() to remove the internal pointer requirement,
> correctly identifying bare prototype typedefs as function pointers
>
> - Prevented pointer enums (e.g., "enum foo *") from being misclassified
> and formatted as scalar enum values in
> syscall_arg_fmt__cache_btf_type(), trace__btf_scnprintf(), and
> syscall_arg__strtoul_btf_type()
>
> - Added negative caching (btf_type_cached) to struct syscall_arg_fmt to
> avoid repeated BTF searches on every event for unresolvable or primitive
> types
>
> - Widened btf_enum_scnprintf() to accept unsigned long val, eliminating
> narrowing truncation of 64-bit values to 32-bit signed integers
>
> - Fixed trace_ksym_beautifier.sh:
> - Quoted "$0" to support directory paths containing spaces
> - Captured output in memory to eliminate temporary file leaks on early
> skip
> - Hardened regex validation to require valid C symbol identifiers and
> reject raw hexadecimal addresses
> - Used '%s' format specifiers in printf to prevent format string
> injection
>
> - Link to v2: https://lore.kernel.org/lkml/20260816205921.576365-1-atomlin@xxxxxxxxxxx/
>
> Changes since v1:
>
> - Fixed reference leak of struct map in syscall_arg__scnprintf_ksym() by
> calling map__put() prior to returning Removed unreachable and erroneous
> entries ("action", "callsite", "call_site", "fn", "function", "work")
> from syscall_arg_fmts__by_name[]
>
> - Restricted name-based SCA_KSYM auto-assignment in
> syscall_arg_fmt__init_array() to pointer or 64-bit address fields,
> preventing misclassification of non-pointer integer fields
>
> - Updated btf_is_func_ptr() to fully unwrap typedefs and type modifiers
> below pointer targets
>
> - Fixed BTF type name matching in syscall_arg_fmt__cache_btf_type() to
> handle leading modifiers and strip trailing pointer asterisks before
> lookup
>
> - Synchronised arg->val with val in trace__btf_scnprintf() and widened val
> to unsigned long, fixing erroneous "NULL" output
>
> - Added shell test script,
> tools/perf/tests/shell/trace_ksym_beautifier.sh, to verify kernel symbol
> beautification for both default kallsyms and BTF routing
>
> - Link to v1: https://lore.kernel.org/lkml/20260815233651.527936-1-atomlin@xxxxxxxxxxx/
>
> Aaron Tomlin (5):
> perf trace: Fix error checking in btf_struct_scnprintf()
> perf trace: Introduce kernel symbol beautifier for virtual addresses
> perf trace: Auto-assign kernel symbol beautifier to function pointer
> fields
> perf trace: Enhance BTF type formatting to symbolise kernel function
> pointers
> perf tests: Add shell test for kernel symbol beautifier

For the series:

Reviewed-by: Ian Rogers <irogers@xxxxxxxxxx>
Tested-by: Ian Rogers <irogers@xxxxxxxxxx>

Thanks,
Ian

> tools/perf/builtin-trace.c | 250 +++++++++++++-----
> .../perf/tests/shell/trace_ksym_beautifier.sh | 38 +++
> tools/perf/trace/beauty/beauty.h | 3 +
> 3 files changed, 232 insertions(+), 59 deletions(-)
> create mode 100755 tools/perf/tests/shell/trace_ksym_beautifier.sh
>
> --
> 2.55.0
>