Add --call-graph option to properly setup callchain
code. Adding default settings to display callchains
whenever they are stored in the perf.data.

Link: http://lkml.kernel.org/n/tip-inykbom2f19difvsu1e18...@git.kernel.org
Signed-off-by: Jiri Olsa <jo...@kernel.org>
---
 tools/perf/builtin-c2c.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
index f4bdef5004c9..913a6b9b4d45 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;
@@ -181,6 +182,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;
@@ -2102,6 +2108,58 @@ static void ui_quirks(bool stdio)
        }
 }
 
+#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;
@@ -2109,6 +2167,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"),
@@ -2122,6 +2181,10 @@ static int perf_c2c__report(int argc, const char **argv)
                    "Use the stdio interface"),
        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;
@@ -2166,6 +2229,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;
 
-- 
2.7.4

Reply via email to