aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/probe-finder.c
diff options
context:
space:
mode:
authorNaveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>2015-04-30 17:12:31 +0530
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-05-14 10:05:09 -0300
commitd4c537e6bf860c12262cb936eef663180d7a3d45 (patch)
tree009003500b9bc61035bae03591362ac57592113f /tools/perf/util/probe-finder.c
parentperf tests: Fix map_groups refcount test (diff)
downloadlinux-dev-d4c537e6bf860c12262cb936eef663180d7a3d45.tar.xz
linux-dev-d4c537e6bf860c12262cb936eef663180d7a3d45.zip
perf probe: Ignore tail calls to probed functions
perf probe currently errors out if there are any tail calls to probed functions: [root@rhel71be]# perf probe do_fork Failed to find probe point in any functions. Error: Failed to add events. Fix this by teaching perf to ignore tail calls. Without patch: [root@rhel71be perf]# ./perf probe -v do_fork probe-definition(0): do_fork symbol:do_fork file:(null) line:0 offset:0 return:0 lazy:(null) 0 arguments Looking at the vmlinux_path (7 entries long) symsrc__init: build id mismatch for /boot/vmlinux. Using /usr/lib/debug/lib/modules/3.10.0-201.el7.ppc64/vmlinux for symbols Open Debuginfo file: /usr/lib/debug/lib/modules/3.10.0-201.el7.ppc64/vmlinux Try to find probe point from debuginfo. found inline addr: 0xc0000000000bb9b0 Probe point found: do_fork+0 found inline addr: 0xc0000000000bbe20 Probe point found: kernel_thread+48 found inline addr: 0xc0000000000bbe5c Probe point found: sys_fork+28 found inline addr: 0xc0000000000bbfac Probe point found: sys_vfork+44 found inline addr: 0xc0000000000bc27c Failed to find probe point in any functions. An error occurred in debuginfo analysis (-2). Error: Failed to add events. Reason: No such file or directory (Code: -2) With patch: [root@rhel71be perf]# ./perf probe -v do_fork probe-definition(0): do_fork symbol:do_fork file:(null) line:0 offset:0 return:0 lazy:(null) 0 arguments Looking at the vmlinux_path (7 entries long) symsrc__init: build id mismatch for /boot/vmlinux. Using /usr/lib/debug/lib/modules/3.10.0-201.el7.ppc64/vmlinux for symbols Open Debuginfo file: /usr/lib/debug/lib/modules/3.10.0-201.el7.ppc64/vmlinux Try to find probe point from debuginfo. found inline addr: 0xc0000000000bb9b0 Probe point found: do_fork+0 found inline addr: 0xc0000000000bbe20 Probe point found: kernel_thread+48 found inline addr: 0xc0000000000bbe5c Probe point found: sys_fork+28 found inline addr: 0xc0000000000bbfac Probe point found: sys_vfork+44 found inline addr: 0xc0000000000bc27c Ignoring tail call from SyS_clone Found 4 probe_trace_events. Opening /sys/kernel/debug/tracing/kprobe_events write=1 No kprobe blacklist support, ignored Added new events: Writing event: p:probe/do_fork _text+768432 Failed to write event: Invalid argument Error: Failed to add events. Reason: Invalid argument (Code: -22) [Ignore the error about failure to write event - this kernel is missing a patch to resolve _text properly] The reason to ignore tail calls is that the address does not belong to any function frame. In the example above, the address in SyS_clone is 0xc0000000000bc27c, but looking at the debug-info: <1><830081>: Abbrev Number: 133 (DW_TAG_subprogram) <830083> DW_AT_external : 1 <830083> DW_AT_name : (indirect string, offset: 0x3cea3): SyS_clone <830087> DW_AT_decl_file : 7 <830088> DW_AT_decl_line : 1689 <83008a> DW_AT_prototyped : 1 <83008a> DW_AT_type : <0x8110eb> <83008e> DW_AT_low_pc : 0xc0000000000bc270 <830096> DW_AT_high_pc : 0xc <83009e> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <8300a0> DW_AT_GNU_all_call_sites: 1 <8300a0> DW_AT_sibling : <0x830178> <snip> <3><830147>: Abbrev Number: 125 (DW_TAG_GNU_call_site) <830148> DW_AT_low_pc : 0xc0000000000bc27c <830150> DW_AT_GNU_tail_call: 1 <830150> DW_AT_abstract_origin: <0x82e7e1> The frame ends at 0xc0000000000bc27c. I suppose this is why this particular call is a "tail" call. FWIW, systemtap seems to ignore these as well and requires users to explicitly place probes at these call sites if necessary. I print out the caller so that users know. Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Link: http://lkml.kernel.org/r/1430394151-15928-1-git-send-email-naveen.n.rao@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to '')
-rw-r--r--tools/perf/util/probe-finder.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 590a24a7f555..c50da392e256 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -674,9 +674,15 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
/* If not a real subprogram, find a real one */
if (!die_is_func_def(sc_die)) {
if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
- pr_warning("Failed to find probe point in any "
- "functions.\n");
- return -ENOENT;
+ if (die_find_tailfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
+ pr_warning("Ignoring tail call from %s\n",
+ dwarf_diename(&pf->sp_die));
+ return 0;
+ } else {
+ pr_warning("Failed to find probe point in any "
+ "functions.\n");
+ return -ENOENT;
+ }
}
} else
memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));