tools/perf/util/probe-finder.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
An issue can be observed when probe C++ demangled symbol with steps:
# nm test_cpp_mangle | grep print_data
0000000000000c94 t _GLOBAL__sub_I__Z10print_datai
0000000000000afc T _Z10print_datai
0000000000000b38 T _Z10print_dataR5Point
# perf probe -x /home/niayan01/test_cpp_mangle -F --demangle
...
print_data(Point&)
print_data(int)
...
# perf --debug verbose=3 probe -x test_cpp_mangle --add "test=print_data(int)"
probe-definition(0): test=print_data(int)
symbol:print_data(int) file:(null) line:0 offset:0 return:0 lazy:(null)
0 arguments
Open Debuginfo file: /home/niayan01/test_cpp_mangle
Try to find probe point from debuginfo.
Symbol print_data(int) address found : afc
Matched function: print_data [2ccf]
Probe point found: print_data+0
Found 1 probe_trace_events.
Opening /sys/kernel/tracing//uprobe_events write=1
Opening /sys/kernel/tracing//README write=0
Writing event: p:probe_test_cpp_mangle/test /home/niayan01/test_cpp_mangle:0xb38
...
When tried to probe symbol "print_data(int)", the log shows:
Symbol print_data(int) address found : afc
The found address is 0xafc - which is right with verifying the output
result from nm. Afterwards when write event, the command uses offset
0xb38 in the last log, which is a wrong address.
The dwarf_diename() gets a common function name, in above case, it
returns string "print_data". As a result, the tool parses the offset
based on the common name. This leads to probe at the wrong symbol
"print_data(Point&)".
To fix the issue, use the die_get_linkage_name() function to retrieve
the distinct linkage name - this is the mangled name for the C++ case.
Based on this unique name, the tool can get a correct offset for
probing. Based on DWARF doc, it is possible the linkage name is missed
in the DIE, it rolls back to use dwarf_diename().
After:
# perf --debug verbose=3 probe -x test_cpp_mangle --add "test=print_data(int)"
probe-definition(0): test=print_data(int)
symbol:print_data(int) file:(null) line:0 offset:0 return:0 lazy:(null)
0 arguments
Open Debuginfo file: /home/niayan01/test_cpp_mangle
Try to find probe point from debuginfo.
Symbol print_data(int) address found : afc
Matched function: print_data [2d06]
Probe point found: print_data+0
Found 1 probe_trace_events.
Opening /sys/kernel/tracing//uprobe_events write=1
Opening /sys/kernel/tracing//README write=0
Writing event: p:probe_test_cpp_mangle/test /home/niayan01/test_cpp_mangle:0xafc
Added new event:
probe_test_cpp_mangle:test (on print_data(int) in /home/niayan01/test_cpp_mangle)
You can now use it in all perf tools, such as:
perf record -e probe_test_cpp_mangle:test -aR sleep 1
# perf --debug verbose=3 probe -x test_cpp_mangle --add "test2=print_data(Point&)"
probe-definition(0): test2=print_data(Point&)
symbol:print_data(Point&) file:(null) line:0 offset:0 return:0 lazy:(null)
0 arguments
Open Debuginfo file: /home/niayan01/test_cpp_mangle
Try to find probe point from debuginfo.
Symbol print_data(Point&) address found : b38
Matched function: print_data [2ccf]
Probe point found: print_data+0
Found 1 probe_trace_events.
Opening /sys/kernel/tracing//uprobe_events write=1
Parsing probe_events: p:probe_test_cpp_mangle/test /home/niayan01/test_cpp_mangle:0x0000000000000afc
Group:probe_test_cpp_mangle Event:test probe:p
Opening /sys/kernel/tracing//README write=0
Writing event: p:probe_test_cpp_mangle/test2 /home/niayan01/test_cpp_mangle:0xb38
Added new event:
probe_test_cpp_mangle:test2 (on print_data(Point&) in /home/niayan01/test_cpp_mangle)
You can now use it in all perf tools, such as:
perf record -e probe_test_cpp_mangle:test2 -aR sleep 1
Fixes: fb1587d869a3 ("perf probe: List probes with line number and file name")
Signed-off-by: Leo Yan <leo.yan@arm.com>
---
tools/perf/util/probe-finder.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 630e16c54ed5..498ccfb0be6f 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1583,8 +1583,21 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr,
/* Find a corresponding function (name, baseline and baseaddr) */
if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
- /* Get function entry information */
- func = basefunc = dwarf_diename(&spdie);
+ /*
+ * Get function entry information.
+ *
+ * As described in the document DWARF Debugging Information
+ * Format Version 5, section 2.22 Linkage Names, "mangled names,
+ * are used in various ways, ... to distinguish multiple
+ * entities that have the same name".
+ *
+ * Firstly try to get distinct linkage name, if fail then
+ * rollback to get associated name in DIE.
+ */
+ func = basefunc = die_get_linkage_name(&spdie);
+ if (!func)
+ func = basefunc = dwarf_diename(&spdie);
+
if (!func ||
die_entrypc(&spdie, &baseaddr) != 0 ||
dwarf_decl_line(&spdie, &baseline) != 0) {
--
2.25.1
On Sat, 12 Oct 2024 15:14:32 +0100, Leo Yan wrote: > An issue can be observed when probe C++ demangled symbol with steps: > > # nm test_cpp_mangle | grep print_data > 0000000000000c94 t _GLOBAL__sub_I__Z10print_datai > 0000000000000afc T _Z10print_datai > 0000000000000b38 T _Z10print_dataR5Point > > [...] Applied to perf-tools-next, thanks! Best regards, Namhyung
On Sat, 12 Oct 2024 15:14:32 +0100 Leo Yan <leo.yan@arm.com> wrote: > An issue can be observed when probe C++ demangled symbol with steps: > > # nm test_cpp_mangle | grep print_data > 0000000000000c94 t _GLOBAL__sub_I__Z10print_datai > 0000000000000afc T _Z10print_datai > 0000000000000b38 T _Z10print_dataR5Point > > # perf probe -x /home/niayan01/test_cpp_mangle -F --demangle > ... > print_data(Point&) > print_data(int) > ... > > # perf --debug verbose=3 probe -x test_cpp_mangle --add "test=print_data(int)" > probe-definition(0): test=print_data(int) > symbol:print_data(int) file:(null) line:0 offset:0 return:0 lazy:(null) > 0 arguments > Open Debuginfo file: /home/niayan01/test_cpp_mangle > Try to find probe point from debuginfo. > Symbol print_data(int) address found : afc > Matched function: print_data [2ccf] > Probe point found: print_data+0 > Found 1 probe_trace_events. > Opening /sys/kernel/tracing//uprobe_events write=1 > Opening /sys/kernel/tracing//README write=0 > Writing event: p:probe_test_cpp_mangle/test /home/niayan01/test_cpp_mangle:0xb38 > ... > > When tried to probe symbol "print_data(int)", the log shows: > > Symbol print_data(int) address found : afc > > The found address is 0xafc - which is right with verifying the output > result from nm. Afterwards when write event, the command uses offset > 0xb38 in the last log, which is a wrong address. > > The dwarf_diename() gets a common function name, in above case, it > returns string "print_data". As a result, the tool parses the offset > based on the common name. This leads to probe at the wrong symbol > "print_data(Point&)". > > To fix the issue, use the die_get_linkage_name() function to retrieve > the distinct linkage name - this is the mangled name for the C++ case. > Based on this unique name, the tool can get a correct offset for > probing. Based on DWARF doc, it is possible the linkage name is missed > in the DIE, it rolls back to use dwarf_diename(). > > After: > > # perf --debug verbose=3 probe -x test_cpp_mangle --add "test=print_data(int)" > probe-definition(0): test=print_data(int) > symbol:print_data(int) file:(null) line:0 offset:0 return:0 lazy:(null) > 0 arguments > Open Debuginfo file: /home/niayan01/test_cpp_mangle > Try to find probe point from debuginfo. > Symbol print_data(int) address found : afc > Matched function: print_data [2d06] > Probe point found: print_data+0 > Found 1 probe_trace_events. > Opening /sys/kernel/tracing//uprobe_events write=1 > Opening /sys/kernel/tracing//README write=0 > Writing event: p:probe_test_cpp_mangle/test /home/niayan01/test_cpp_mangle:0xafc > Added new event: > probe_test_cpp_mangle:test (on print_data(int) in /home/niayan01/test_cpp_mangle) > > You can now use it in all perf tools, such as: > > perf record -e probe_test_cpp_mangle:test -aR sleep 1 > > # perf --debug verbose=3 probe -x test_cpp_mangle --add "test2=print_data(Point&)" > probe-definition(0): test2=print_data(Point&) > symbol:print_data(Point&) file:(null) line:0 offset:0 return:0 lazy:(null) > 0 arguments > Open Debuginfo file: /home/niayan01/test_cpp_mangle > Try to find probe point from debuginfo. > Symbol print_data(Point&) address found : b38 > Matched function: print_data [2ccf] > Probe point found: print_data+0 > Found 1 probe_trace_events. > Opening /sys/kernel/tracing//uprobe_events write=1 > Parsing probe_events: p:probe_test_cpp_mangle/test /home/niayan01/test_cpp_mangle:0x0000000000000afc > Group:probe_test_cpp_mangle Event:test probe:p > Opening /sys/kernel/tracing//README write=0 > Writing event: p:probe_test_cpp_mangle/test2 /home/niayan01/test_cpp_mangle:0xb38 > Added new event: > probe_test_cpp_mangle:test2 (on print_data(Point&) in /home/niayan01/test_cpp_mangle) > > You can now use it in all perf tools, such as: > > perf record -e probe_test_cpp_mangle:test2 -aR sleep 1 > This looks good to me. Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Thank you! > Fixes: fb1587d869a3 ("perf probe: List probes with line number and file name") > Signed-off-by: Leo Yan <leo.yan@arm.com> > --- > tools/perf/util/probe-finder.c | 17 +++++++++++++++-- > 1 file changed, 15 insertions(+), 2 deletions(-) > > diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c > index 630e16c54ed5..498ccfb0be6f 100644 > --- a/tools/perf/util/probe-finder.c > +++ b/tools/perf/util/probe-finder.c > @@ -1583,8 +1583,21 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr, > > /* Find a corresponding function (name, baseline and baseaddr) */ > if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) { > - /* Get function entry information */ > - func = basefunc = dwarf_diename(&spdie); > + /* > + * Get function entry information. > + * > + * As described in the document DWARF Debugging Information > + * Format Version 5, section 2.22 Linkage Names, "mangled names, > + * are used in various ways, ... to distinguish multiple > + * entities that have the same name". > + * > + * Firstly try to get distinct linkage name, if fail then > + * rollback to get associated name in DIE. > + */ > + func = basefunc = die_get_linkage_name(&spdie); > + if (!func) > + func = basefunc = dwarf_diename(&spdie); > + > if (!func || > die_entrypc(&spdie, &baseaddr) != 0 || > dwarf_decl_line(&spdie, &baseline) != 0) { > -- > 2.25.1 > > -- Masami Hiramatsu (Google) <mhiramat@kernel.org>
© 2016 - 2024 Red Hat, Inc.