diff options
author | Athira Rajeev <atrajeev@linux.ibm.com> | 2025-02-25 18:00:42 +0530 |
---|---|---|
committer | Namhyung Kim <namhyung@kernel.org> | 2025-02-26 14:25:14 -0800 |
commit | 556b58c19154a7060b72ab62c0cd0911ccdbf1ba (patch) | |
tree | 732862bea7557b4751a06478b30e3f509f74341e /tools/perf/util/trace-event-scripting.c | |
parent | 833d025239491767d9009c956de03c14f9bbd990 (diff) |
perf probe: Pick the correct dwarf die while adding probe points
Perf probe on vfs_fstatat fails as below on a powerpc system
$ ./perf probe -nf --max-probes=512 -a 'vfs_fstatat $params'
Segmentation fault (core dumped)
This is observed while running perftool-testsuite_probe testcase.
While running with verbose, its observed that segfault happens
at:
synthesize_probe_trace_arg ()
synthesize_probe_trace_command ()
probe_file.add_event ()
apply_perf_probe_events ()
__cmd_probe ()
cmd_probe ()
run_builtin ()
handle_internal_command ()
main ()
Code in synthesize_probe_trace_arg() access a null value and results in
segfault. Data structure which is null:
struct probe_trace_arg arg->value
We are hitting a case where arg->value is null in probe point:
"vfs_fstatat $params". This is happening since 'commit e896474fe485
("getname_maybe_null() - the third variant of pathname copy-in")'
Before the commit, probe point for vfs_fstatat was getting added only
for one location:
Writing event: p:probe/vfs_fstatat _text+6345404 dfd=%gpr3:s32 filename=%gpr4:x64 stat=%gpr5:x64 flags=%gpr6:s32
With this change, vfs_fstatat code is inlined for other locations in the
code:
Probe point found: __do_sys_lstat64+48
Probe point found: __do_sys_stat64+48
Probe point found: __do_sys_newlstat+48
Probe point found: __do_sys_newstat+48
Probe point found: vfs_fstatat+0
When trying to find matching dwarf information entry (DIE)
from the debuginfo, the code incorrectly picks DIE which is
not referring to vfs_fstatat. Snippet from dwarf entry in vmlinux
debuginfo file.
The main abstract die is:
<1><4214883>: Abbrev Number: 147 (DW_TAG_subprogram)
<4214885> DW_AT_external : 1
<4214885> DW_AT_name : (indirect string, offset: 0x17b9f3): vfs_fstatat
With formal parameters:
<2><4214896>: Abbrev Number: 51 (DW_TAG_formal_parameter)
<4214897> DW_AT_name : dfd
<2><42148a3>: Abbrev Number: 23 (DW_TAG_formal_parameter)
<42148a4> DW_AT_name : (indirect string, offset: 0x8fda9): filename
<2><42148b0>: Abbrev Number: 23 (DW_TAG_formal_parameter)
<42148b1> DW_AT_name : (indirect string, offset: 0x16bd9c): stat
<2><42148bd>: Abbrev Number: 23 (DW_TAG_formal_parameter)
<42148be> DW_AT_name : (indirect string, offset: 0x39832b): flags
While collecting variables/parameters for a probe point, the function
copy_variables_cb() also looks at dwarf debug entries based on the
instruction address. Snippet
if (dwarf_haspc(die_mem, vf->pf->addr))
return DIE_FIND_CB_CONTINUE;
else
return DIE_FIND_CB_SIBLING;
But incase of inlined function instance for vfs_fstatat, there are two
entries which has the instruction address entry point as same.
Instance 1: which is for vfs_fstatat and DW_AT_abstract_origin points to
0x4214883 (reference above for main abstract die)
<3><42131fa>: Abbrev Number: 59 (DW_TAG_inlined_subroutine)
<42131fb> DW_AT_abstract_origin: <0x4214883>
<42131ff> DW_AT_entry_pc : 0xc00000000062b1e0
Instance 2: which is not for vfs_fstatat but for getname
<5><4213270>: Abbrev Number: 39 (DW_TAG_inlined_subroutine)
<4213271> DW_AT_abstract_origin: <0x4215b6b>
<4213275> DW_AT_entry_pc : 0xc00000000062b1e0
But the copy_variables_cb() continues to add parameters from second
instance also based on the dwarf_haspc() check. This results in
formal parameters for getname also appended to params. But while
filling in the args->value for these parameters, since these args
are not part of dwarf with offset "42131fa". Hence value will be
null. This incorrect args results in segfault when value field is
accessed.
Save the dwarf dieoffset of the actual DW_TAG_subprogram as part of
"struct probe_finder". In copy_variables_cb(), include check to make
sure the DW_AT_abstract_origin points to the correct entry if the
dwarf_haspc() matches the instruction address.
Signed-off-by: Athira Rajeev <atrajeev@linux.ibm.com>
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Link: https://lore.kernel.org/r/20250225123042.37263-1-atrajeev@linux.ibm.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Diffstat (limited to 'tools/perf/util/trace-event-scripting.c')
0 files changed, 0 insertions, 0 deletions