aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/session.c
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@redhat.com>2012-08-07 09:20:46 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-08-11 14:06:56 -0400
commit71ad0f5e4e361c8bca864c7d09d14b64af6bc2fc (patch)
tree57d87f004c3d939d2c7be315b9e1011a9214a6a1 /tools/perf/util/session.c
parent0f6a30150ca2e0cf4f893e7173d61434a3c02e0e (diff)
perf tools: Support for DWARF CFI unwinding on post processing
This brings the support for DWARF cfi unwinding on perf post processing. Call frame informations are retrieved and then passed to libunwind that requests memory and register content from the applications. Adding unwind object to handle the user stack backtrace based on the user register values and user stack dump. The unwind object access the libunwind via remote interface and provides to it all the necessary data to unwind the stack. The unwind interface provides following function: unwind__get_entries And callback (specified in above function) to retrieve the backtrace entries: typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); Signed-off-by: Jiri Olsa <jolsa@redhat.com> Original-patch-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: "Frank Ch. Eigler" <fche@redhat.com> Cc: Arun Sharma <asharma@fb.com> Cc: Benjamin Redelings <benjamin.redelings@nescent.org> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com> Cc: Cyrill Gorcunov <gorcunov@openvz.org> Cc: Frank Ch. Eigler <fche@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Robert Richter <robert.richter@amd.com> Cc: Stephane Eranian <eranian@google.com> Cc: Tom Zanussi <tzanussi@gmail.com> Cc: Ulrich Drepper <drepper@gmail.com> Link: http://lkml.kernel.org/r/1344345647-11536-12-git-send-email-jolsa@redhat.com [ Replaced use of perf_session by usage of perf_evsel ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r--tools/perf/util/session.c66
1 files changed, 53 insertions, 13 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index c9ed7e3cf231..f7bb7ae328da 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -16,6 +16,7 @@
16#include "cpumap.h" 16#include "cpumap.h"
17#include "event-parse.h" 17#include "event-parse.h"
18#include "perf_regs.h" 18#include "perf_regs.h"
19#include "unwind.h"
19 20
20static int perf_session__open(struct perf_session *self, bool force) 21static int perf_session__open(struct perf_session *self, bool force)
21{ 22{
@@ -289,10 +290,11 @@ struct branch_info *machine__resolve_bstack(struct machine *self,
289 return bi; 290 return bi;
290} 291}
291 292
292int machine__resolve_callchain(struct machine *self, 293static int machine__resolve_callchain_sample(struct machine *machine,
293 struct thread *thread, 294 struct thread *thread,
294 struct ip_callchain *chain, 295 struct ip_callchain *chain,
295 struct symbol **parent) 296 struct symbol **parent)
297
296{ 298{
297 u8 cpumode = PERF_RECORD_MISC_USER; 299 u8 cpumode = PERF_RECORD_MISC_USER;
298 unsigned int i; 300 unsigned int i;
@@ -317,11 +319,14 @@ int machine__resolve_callchain(struct machine *self,
317 if (ip >= PERF_CONTEXT_MAX) { 319 if (ip >= PERF_CONTEXT_MAX) {
318 switch (ip) { 320 switch (ip) {
319 case PERF_CONTEXT_HV: 321 case PERF_CONTEXT_HV:
320 cpumode = PERF_RECORD_MISC_HYPERVISOR; break; 322 cpumode = PERF_RECORD_MISC_HYPERVISOR;
323 break;
321 case PERF_CONTEXT_KERNEL: 324 case PERF_CONTEXT_KERNEL:
322 cpumode = PERF_RECORD_MISC_KERNEL; break; 325 cpumode = PERF_RECORD_MISC_KERNEL;
326 break;
323 case PERF_CONTEXT_USER: 327 case PERF_CONTEXT_USER:
324 cpumode = PERF_RECORD_MISC_USER; break; 328 cpumode = PERF_RECORD_MISC_USER;
329 break;
325 default: 330 default:
326 pr_debug("invalid callchain context: " 331 pr_debug("invalid callchain context: "
327 "%"PRId64"\n", (s64) ip); 332 "%"PRId64"\n", (s64) ip);
@@ -336,7 +341,7 @@ int machine__resolve_callchain(struct machine *self,
336 } 341 }
337 342
338 al.filtered = false; 343 al.filtered = false;
339 thread__find_addr_location(thread, self, cpumode, 344 thread__find_addr_location(thread, machine, cpumode,
340 MAP__FUNCTION, ip, &al, NULL); 345 MAP__FUNCTION, ip, &al, NULL);
341 if (al.sym != NULL) { 346 if (al.sym != NULL) {
342 if (sort__has_parent && !*parent && 347 if (sort__has_parent && !*parent &&
@@ -355,6 +360,40 @@ int machine__resolve_callchain(struct machine *self,
355 return 0; 360 return 0;
356} 361}
357 362
363static int unwind_entry(struct unwind_entry *entry, void *arg)
364{
365 struct callchain_cursor *cursor = arg;
366 return callchain_cursor_append(cursor, entry->ip,
367 entry->map, entry->sym);
368}
369
370int machine__resolve_callchain(struct machine *machine,
371 struct perf_evsel *evsel,
372 struct thread *thread,
373 struct perf_sample *sample,
374 struct symbol **parent)
375
376{
377 int ret;
378
379 callchain_cursor_reset(&callchain_cursor);
380
381 ret = machine__resolve_callchain_sample(machine, thread,
382 sample->callchain, parent);
383 if (ret)
384 return ret;
385
386 /* Can we do dwarf post unwind? */
387 if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
388 (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
389 return 0;
390
391 return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
392 thread, evsel->attr.sample_regs_user,
393 sample);
394
395}
396
358static int process_event_synth_tracing_data_stub(union perf_event *event __used, 397static int process_event_synth_tracing_data_stub(union perf_event *event __used,
359 struct perf_session *session __used) 398 struct perf_session *session __used)
360{ 399{
@@ -1533,9 +1572,9 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1533 return NULL; 1572 return NULL;
1534} 1573}
1535 1574
1536void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, 1575void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1537 struct machine *machine, int print_sym, 1576 struct perf_sample *sample, struct machine *machine,
1538 int print_dso, int print_symoffset) 1577 int print_sym, int print_dso, int print_symoffset)
1539{ 1578{
1540 struct addr_location al; 1579 struct addr_location al;
1541 struct callchain_cursor_node *node; 1580 struct callchain_cursor_node *node;
@@ -1549,8 +1588,9 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1549 1588
1550 if (symbol_conf.use_callchain && sample->callchain) { 1589 if (symbol_conf.use_callchain && sample->callchain) {
1551 1590
1552 if (machine__resolve_callchain(machine, al.thread, 1591
1553 sample->callchain, NULL) != 0) { 1592 if (machine__resolve_callchain(machine, evsel, al.thread,
1593 sample, NULL) != 0) {
1554 if (verbose) 1594 if (verbose)
1555 error("Failed to resolve callchain. Skipping\n"); 1595 error("Failed to resolve callchain. Skipping\n");
1556 return; 1596 return;