aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2010-04-12 13:17:29 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-04-14 16:28:20 -0400
commita34a985499895a46a4dacff727d0fbc63cdc75e8 (patch)
tree84905a8248ab1b35403e676609dd120c85c1dd97 /tools
parent11a1ca3554b377d2a8a318a3cbf8ce10a7a2a8e4 (diff)
perf probe: Support DW_OP_call_frame_cfa in debuginfo
When building kernel without CONFIG_FRAME_POINTER, gcc uses CFA (canonical frame address) for frame base. With this patch, perf probe just gets CFI (call frame information) from debuginfo and search corresponding CFA from the CFI. IOW, this allows perf probe works correctly on the kernel without CONFIG_FRAME_POINTER. <Before> ./perf probe -fn sched_slice:12 lw.weight Fatal: DW_OP 156 is not supported. (^^^ DW_OP_call_frame_cfa) <After> ./perf probe -fn sched_slice:12 lw.weight Add new event: probe:sched_slice (on sched_slice:12 with weight=lw.weight) Cc: Ingo Molnar <mingo@elte.hu> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20100412171728.3790.98217.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/probe-finder.c14
-rw-r--r--tools/perf/util/probe-finder.h1
2 files changed, 12 insertions, 3 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index ab476736cbe7..1f4528555d42 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -398,7 +398,6 @@ static void convert_location(Dwarf_Op *op, struct probe_finder *pf)
398 const char *regs; 398 const char *regs;
399 struct kprobe_trace_arg *tvar = pf->tvar; 399 struct kprobe_trace_arg *tvar = pf->tvar;
400 400
401 /* TODO: support CFA */
402 /* If this is based on frame buffer, set the offset */ 401 /* If this is based on frame buffer, set the offset */
403 if (op->atom == DW_OP_fbreg) { 402 if (op->atom == DW_OP_fbreg) {
404 if (pf->fb_ops == NULL) 403 if (pf->fb_ops == NULL)
@@ -629,11 +628,17 @@ static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
629 /* Get the frame base attribute/ops */ 628 /* Get the frame base attribute/ops */
630 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr); 629 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
631 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); 630 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
632 if (ret <= 0 || nops == 0) 631 if (ret <= 0 || nops == 0) {
633 pf->fb_ops = NULL; 632 pf->fb_ops = NULL;
633 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
634 pf->cfi != NULL) {
635 Dwarf_Frame *frame;
636 ret = dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame);
637 DIE_IF(ret != 0);
638 dwarf_frame_cfa(frame, &pf->fb_ops, &nops);
639 }
634 640
635 /* Find each argument */ 641 /* Find each argument */
636 /* TODO: use dwarf_cfi_addrframe */
637 tev->nargs = pf->pev->nargs; 642 tev->nargs = pf->pev->nargs;
638 tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); 643 tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs);
639 for (i = 0; i < pf->pev->nargs; i++) { 644 for (i = 0; i < pf->pev->nargs; i++) {
@@ -842,6 +847,9 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
842 if (!dbg) 847 if (!dbg)
843 return -ENOENT; 848 return -ENOENT;
844 849
850 /* Get the call frame information from this dwarf */
851 pf.cfi = dwarf_getcfi(dbg);
852
845 off = 0; 853 off = 0;
846 line_list__init(&pf.lcache); 854 line_list__init(&pf.lcache);
847 /* Loop on CUs (Compilation Unit) */ 855 /* Loop on CUs (Compilation Unit) */
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 2a271321944f..310ce897229c 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -42,6 +42,7 @@ struct probe_finder {
42 struct list_head lcache; /* Line cache for lazy match */ 42 struct list_head lcache; /* Line cache for lazy match */
43 43
44 /* For variable searching */ 44 /* For variable searching */
45 Dwarf_CFI *cfi; /* Call Frame Information */
45 Dwarf_Op *fb_ops; /* Frame base attribute */ 46 Dwarf_Op *fb_ops; /* Frame base attribute */
46 struct perf_probe_arg *pvar; /* Current target variable */ 47 struct perf_probe_arg *pvar; /* Current target variable */
47 struct kprobe_trace_arg *tvar; /* Current result variable */ 48 struct kprobe_trace_arg *tvar; /* Current result variable */