diff options
Diffstat (limited to 'tools/perf/builtin-c2c.c')
-rw-r--r-- | tools/perf/builtin-c2c.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 88d88eac53aa..950a4123ea66 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -17,6 +17,7 @@ #include "evsel.h" #include <asm/bug.h> #include "ui/browsers/hists.h" +#include "evlist.h" struct c2c_hists { struct hists hists; @@ -183,6 +184,11 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, return -1; } + ret = sample__resolve_callchain(sample, &callchain_cursor, NULL, + evsel, &al, sysctl_perf_event_max_stack); + if (ret) + goto out; + mi = sample__resolve_mem(sample, &al); if (mi == NULL) return -ENOMEM; @@ -2117,6 +2123,58 @@ static void ui_quirks(void) } } +#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent" + +const char callchain_help[] = "Display call graph (stack chain/backtrace):\n\n" + CALLCHAIN_REPORT_HELP + "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT; + +static int +parse_callchain_opt(const struct option *opt, const char *arg, int unset) +{ + struct callchain_param *callchain = opt->value; + + callchain->enabled = !unset; + /* + * --no-call-graph + */ + if (unset) { + symbol_conf.use_callchain = false; + callchain->mode = CHAIN_NONE; + return 0; + } + + return parse_callchain_report_opt(arg); +} + +static int setup_callchain(struct perf_evlist *evlist) +{ + u64 sample_type = perf_evlist__combined_sample_type(evlist); + enum perf_call_graph_mode mode = CALLCHAIN_NONE; + + if ((sample_type & PERF_SAMPLE_REGS_USER) && + (sample_type & PERF_SAMPLE_STACK_USER)) + mode = CALLCHAIN_DWARF; + else if (sample_type & PERF_SAMPLE_BRANCH_STACK) + mode = CALLCHAIN_LBR; + else if (sample_type & PERF_SAMPLE_CALLCHAIN) + mode = CALLCHAIN_FP; + + if (!callchain_param.enabled && + callchain_param.mode != CHAIN_NONE && + mode != CALLCHAIN_NONE) { + symbol_conf.use_callchain = true; + if (callchain_register_param(&callchain_param) < 0) { + ui__error("Can't register callchain params.\n"); + return -EINVAL; + } + } + + callchain_param.record_mode = mode; + callchain_param.min_percent = 0; + return 0; +} + static int perf_c2c__report(int argc, const char **argv) { struct perf_session *session; @@ -2124,6 +2182,7 @@ static int perf_c2c__report(int argc, const char **argv) struct perf_data_file file = { .mode = PERF_DATA_MODE_READ, }; + char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT; const struct option c2c_options[] = { OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, "file", "vmlinux pathname"), @@ -2138,6 +2197,10 @@ static int perf_c2c__report(int argc, const char **argv) #endif OPT_BOOLEAN(0, "stats", &c2c.stats_only, "Use the stdio interface"), + OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param, + "print_type,threshold[,print_limit],order,sort_key[,branch],value", + callchain_help, &parse_callchain_opt, + callchain_default_opt), OPT_END() }; int err = 0; @@ -2179,6 +2242,10 @@ static int perf_c2c__report(int argc, const char **argv) goto out; } + err = setup_callchain(session->evlist); + if (err) + goto out_session; + if (symbol__init(&session->header.env) < 0) goto out_session; |