aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-script.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2018-09-20 14:05:39 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2018-10-24 14:29:55 -0400
commit99f753f048b3f02f31a56951781672021af6cd0d (patch)
tree9c22f288e4be70e8c31d9c248657dcdd98231452 /tools/perf/builtin-script.c
parentd1b1552e15d41297abcaf3812378e3391d44fa6b (diff)
perf script: Implement --graph-function
Add a ftrace style --graph-function argument to 'perf script' that allows to print itrace function calls only below a given function. This makes it easier to find the code of interest in a large trace. % perf record -e intel_pt//k -a sleep 1 % perf script --graph-function group_sched_in --call-trace perf 900 [000] 194167.205652203: ([kernel.kallsyms]) group_sched_in perf 900 [000] 194167.205652203: ([kernel.kallsyms]) __x86_indirect_thunk_rax perf 900 [000] 194167.205652203: ([kernel.kallsyms]) event_sched_in.isra.107 perf 900 [000] 194167.205652203: ([kernel.kallsyms]) perf_event_set_state.part.71 perf 900 [000] 194167.205652203: ([kernel.kallsyms]) perf_event_update_time perf 900 [000] 194167.205652203: ([kernel.kallsyms]) perf_pmu_disable perf 900 [000] 194167.205652203: ([kernel.kallsyms]) perf_log_itrace_start perf 900 [000] 194167.205652203: ([kernel.kallsyms]) __x86_indirect_thunk_rax perf 900 [000] 194167.205652203: ([kernel.kallsyms]) perf_event_update_userpage perf 900 [000] 194167.205652203: ([kernel.kallsyms]) calc_timer_values perf 900 [000] 194167.205652203: ([kernel.kallsyms]) sched_clock_cpu perf 900 [000] 194167.205652203: ([kernel.kallsyms]) __x86_indirect_thunk_rax perf 900 [000] 194167.205652203: ([kernel.kallsyms]) arch_perf_update_userpage perf 900 [000] 194167.205652203: ([kernel.kallsyms]) __fentry__ perf 900 [000] 194167.205652203: ([kernel.kallsyms]) using_native_sched_clock perf 900 [000] 194167.205652203: ([kernel.kallsyms]) sched_clock_stable perf 900 [000] 194167.205652203: ([kernel.kallsyms]) perf_pmu_enable perf 900 [000] 194167.205652203: ([kernel.kallsyms]) __x86_indirect_thunk_rax swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) group_sched_in swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) __x86_indirect_thunk_rax swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) event_sched_in.isra.107 swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) perf_event_set_state.part.71 swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) perf_event_update_time swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) perf_pmu_disable swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) perf_log_itrace_start swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) __x86_indirect_thunk_rax swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) perf_event_update_userpage swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) calc_timer_values swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) sched_clock_cpu swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) __x86_indirect_thunk_rax swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) arch_perf_update_userpage swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) __fentry__ swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) using_native_sched_clock swapper 0 [001] 194167.205660693: ([kernel.kallsyms]) sched_clock_stable Signed-off-by: Andi Kleen <ak@linux.intel.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Tested-by: Leo Yan <leo.yan@linaro.org> Acked-by: Jiri Olsa <jolsa@kernel.org> Cc: Kim Phillips <kim.phillips@arm.com> Link: http://lkml.kernel.org/r/20180920180540.14039-5-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r--tools/perf/builtin-script.c96
1 files changed, 78 insertions, 18 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 566e1450898a..9d2249ea75e3 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1105,6 +1105,35 @@ out:
1105 return printed; 1105 return printed;
1106} 1106}
1107 1107
1108static const char *resolve_branch_sym(struct perf_sample *sample,
1109 struct perf_evsel *evsel,
1110 struct thread *thread,
1111 struct addr_location *al,
1112 u64 *ip)
1113{
1114 struct addr_location addr_al;
1115 struct perf_event_attr *attr = &evsel->attr;
1116 const char *name = NULL;
1117
1118 if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
1119 if (sample_addr_correlates_sym(attr)) {
1120 thread__resolve(thread, &addr_al, sample);
1121 if (addr_al.sym)
1122 name = addr_al.sym->name;
1123 else
1124 *ip = sample->addr;
1125 } else {
1126 *ip = sample->addr;
1127 }
1128 } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
1129 if (al->sym)
1130 name = al->sym->name;
1131 else
1132 *ip = sample->ip;
1133 }
1134 return name;
1135}
1136
1108static int perf_sample__fprintf_callindent(struct perf_sample *sample, 1137static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1109 struct perf_evsel *evsel, 1138 struct perf_evsel *evsel,
1110 struct thread *thread, 1139 struct thread *thread,
@@ -1112,7 +1141,6 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1112{ 1141{
1113 struct perf_event_attr *attr = &evsel->attr; 1142 struct perf_event_attr *attr = &evsel->attr;
1114 size_t depth = thread_stack__depth(thread); 1143 size_t depth = thread_stack__depth(thread);
1115 struct addr_location addr_al;
1116 const char *name = NULL; 1144 const char *name = NULL;
1117 static int spacing; 1145 static int spacing;
1118 int len = 0; 1146 int len = 0;
@@ -1126,22 +1154,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1126 if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN) 1154 if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN)
1127 depth += 1; 1155 depth += 1;
1128 1156
1129 if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) { 1157 name = resolve_branch_sym(sample, evsel, thread, al, &ip);
1130 if (sample_addr_correlates_sym(attr)) {
1131 thread__resolve(thread, &addr_al, sample);
1132 if (addr_al.sym)
1133 name = addr_al.sym->name;
1134 else
1135 ip = sample->addr;
1136 } else {
1137 ip = sample->addr;
1138 }
1139 } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
1140 if (al->sym)
1141 name = al->sym->name;
1142 else
1143 ip = sample->ip;
1144 }
1145 1158
1146 if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) { 1159 if (PRINT_FIELD(DSO) && !(PRINT_FIELD(IP) || PRINT_FIELD(ADDR))) {
1147 dlen += fprintf(fp, "("); 1160 dlen += fprintf(fp, "(");
@@ -1647,6 +1660,47 @@ static void perf_sample__fprint_metric(struct perf_script *script,
1647 } 1660 }
1648} 1661}
1649 1662
1663static bool show_event(struct perf_sample *sample,
1664 struct perf_evsel *evsel,
1665 struct thread *thread,
1666 struct addr_location *al)
1667{
1668 int depth = thread_stack__depth(thread);
1669
1670 if (!symbol_conf.graph_function)
1671 return true;
1672
1673 if (thread->filter) {
1674 if (depth <= thread->filter_entry_depth) {
1675 thread->filter = false;
1676 return false;
1677 }
1678 return true;
1679 } else {
1680 const char *s = symbol_conf.graph_function;
1681 u64 ip;
1682 const char *name = resolve_branch_sym(sample, evsel, thread, al,
1683 &ip);
1684 unsigned nlen;
1685
1686 if (!name)
1687 return false;
1688 nlen = strlen(name);
1689 while (*s) {
1690 unsigned len = strcspn(s, ",");
1691 if (nlen == len && !strncmp(name, s, len)) {
1692 thread->filter = true;
1693 thread->filter_entry_depth = depth;
1694 return true;
1695 }
1696 s += len;
1697 if (*s == ',')
1698 s++;
1699 }
1700 return false;
1701 }
1702}
1703
1650static void process_event(struct perf_script *script, 1704static void process_event(struct perf_script *script,
1651 struct perf_sample *sample, struct perf_evsel *evsel, 1705 struct perf_sample *sample, struct perf_evsel *evsel,
1652 struct addr_location *al, 1706 struct addr_location *al,
@@ -1661,6 +1715,9 @@ static void process_event(struct perf_script *script,
1661 if (output[type].fields == 0) 1715 if (output[type].fields == 0)
1662 return; 1716 return;
1663 1717
1718 if (!show_event(sample, evsel, thread, al))
1719 return;
1720
1664 ++es->samples; 1721 ++es->samples;
1665 1722
1666 perf_sample__fprintf_start(sample, thread, evsel, 1723 perf_sample__fprintf_start(sample, thread, evsel,
@@ -3237,6 +3294,8 @@ int cmd_script(int argc, const char **argv)
3237 "Decode calls from from itrace", parse_call_trace), 3294 "Decode calls from from itrace", parse_call_trace),
3238 OPT_CALLBACK_OPTARG(0, "call-ret-trace", &itrace_synth_opts, NULL, NULL, 3295 OPT_CALLBACK_OPTARG(0, "call-ret-trace", &itrace_synth_opts, NULL, NULL,
3239 "Decode calls and returns from itrace", parse_callret_trace), 3296 "Decode calls and returns from itrace", parse_callret_trace),
3297 OPT_STRING(0, "graph-function", &symbol_conf.graph_function, "symbol[,symbol...]",
3298 "Only print symbols and callees with --call-trace/--call-ret-trace"),
3240 OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]", 3299 OPT_STRING(0, "stop-bt", &symbol_conf.bt_stop_list_str, "symbol[,symbol...]",
3241 "Stop display of callgraph at these symbols"), 3300 "Stop display of callgraph at these symbols"),
3242 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 3301 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
@@ -3494,7 +3553,8 @@ int cmd_script(int argc, const char **argv)
3494 script.session = session; 3553 script.session = session;
3495 script__setup_sample_type(&script); 3554 script__setup_sample_type(&script);
3496 3555
3497 if (output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) 3556 if ((output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) ||
3557 symbol_conf.graph_function)
3498 itrace_synth_opts.thread_stack = true; 3558 itrace_synth_opts.thread_stack = true;
3499 3559
3500 session->itrace_synth_opts = &itrace_synth_opts; 3560 session->itrace_synth_opts = &itrace_synth_opts;