aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-annotate.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r--tools/perf/builtin-annotate.c109
1 files changed, 99 insertions, 10 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index f15731a3d438..51709a961496 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -40,10 +40,11 @@
40struct perf_annotate { 40struct perf_annotate {
41 struct perf_tool tool; 41 struct perf_tool tool;
42 struct perf_session *session; 42 struct perf_session *session;
43 bool use_tui, use_stdio, use_gtk; 43 bool use_tui, use_stdio, use_stdio2, use_gtk;
44 bool full_paths; 44 bool full_paths;
45 bool print_line; 45 bool print_line;
46 bool skip_missing; 46 bool skip_missing;
47 bool has_br_stack;
47 const char *sym_hist_filter; 48 const char *sym_hist_filter;
48 const char *cpu_list; 49 const char *cpu_list;
49 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 50 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -146,16 +147,78 @@ static void process_branch_stack(struct branch_stack *bs, struct addr_location *
146 free(bi); 147 free(bi);
147} 148}
148 149
150static int hist_iter__branch_callback(struct hist_entry_iter *iter,
151 struct addr_location *al __maybe_unused,
152 bool single __maybe_unused,
153 void *arg __maybe_unused)
154{
155 struct hist_entry *he = iter->he;
156 struct branch_info *bi;
157 struct perf_sample *sample = iter->sample;
158 struct perf_evsel *evsel = iter->evsel;
159 int err;
160
161 hist__account_cycles(sample->branch_stack, al, sample, false);
162
163 bi = he->branch_info;
164 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel->idx);
165
166 if (err)
167 goto out;
168
169 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel->idx);
170
171out:
172 return err;
173}
174
175static int process_branch_callback(struct perf_evsel *evsel,
176 struct perf_sample *sample,
177 struct addr_location *al __maybe_unused,
178 struct perf_annotate *ann,
179 struct machine *machine)
180{
181 struct hist_entry_iter iter = {
182 .evsel = evsel,
183 .sample = sample,
184 .add_entry_cb = hist_iter__branch_callback,
185 .hide_unresolved = symbol_conf.hide_unresolved,
186 .ops = &hist_iter_branch,
187 };
188
189 struct addr_location a;
190 int ret;
191
192 if (machine__resolve(machine, &a, sample) < 0)
193 return -1;
194
195 if (a.sym == NULL)
196 return 0;
197
198 if (a.map != NULL)
199 a.map->dso->hit = 1;
200
201 ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann);
202 return ret;
203}
204
205static bool has_annotation(struct perf_annotate *ann)
206{
207 return ui__has_annotation() || ann->use_stdio2;
208}
209
149static int perf_evsel__add_sample(struct perf_evsel *evsel, 210static int perf_evsel__add_sample(struct perf_evsel *evsel,
150 struct perf_sample *sample, 211 struct perf_sample *sample,
151 struct addr_location *al, 212 struct addr_location *al,
152 struct perf_annotate *ann) 213 struct perf_annotate *ann,
214 struct machine *machine)
153{ 215{
154 struct hists *hists = evsel__hists(evsel); 216 struct hists *hists = evsel__hists(evsel);
155 struct hist_entry *he; 217 struct hist_entry *he;
156 int ret; 218 int ret;
157 219
158 if (ann->sym_hist_filter != NULL && 220 if ((!ann->has_br_stack || !has_annotation(ann)) &&
221 ann->sym_hist_filter != NULL &&
159 (al->sym == NULL || 222 (al->sym == NULL ||
160 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) { 223 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) {
161 /* We're only interested in a symbol named sym_hist_filter */ 224 /* We're only interested in a symbol named sym_hist_filter */
@@ -178,6 +241,9 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
178 */ 241 */
179 process_branch_stack(sample->branch_stack, al, sample); 242 process_branch_stack(sample->branch_stack, al, sample);
180 243
244 if (ann->has_br_stack && has_annotation(ann))
245 return process_branch_callback(evsel, sample, al, ann, machine);
246
181 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); 247 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
182 if (he == NULL) 248 if (he == NULL)
183 return -ENOMEM; 249 return -ENOMEM;
@@ -206,7 +272,8 @@ static int process_sample_event(struct perf_tool *tool,
206 if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap)) 272 if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
207 goto out_put; 273 goto out_put;
208 274
209 if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) { 275 if (!al.filtered &&
276 perf_evsel__add_sample(evsel, sample, &al, ann, machine)) {
210 pr_warning("problem incrementing symbol count, " 277 pr_warning("problem incrementing symbol count, "
211 "skipping event\n"); 278 "skipping event\n");
212 ret = -1; 279 ret = -1;
@@ -220,8 +287,11 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
220 struct perf_evsel *evsel, 287 struct perf_evsel *evsel,
221 struct perf_annotate *ann) 288 struct perf_annotate *ann)
222{ 289{
223 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel, 290 if (!ann->use_stdio2)
224 ann->print_line, ann->full_paths, 0, 0); 291 return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel,
292 ann->print_line, ann->full_paths, 0, 0);
293 return symbol__tty_annotate2(he->ms.sym, he->ms.map, evsel,
294 ann->print_line, ann->full_paths);
225} 295}
226 296
227static void hists__find_annotations(struct hists *hists, 297static void hists__find_annotations(struct hists *hists,
@@ -238,6 +308,10 @@ static void hists__find_annotations(struct hists *hists,
238 if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned) 308 if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned)
239 goto find_next; 309 goto find_next;
240 310
311 if (ann->sym_hist_filter &&
312 (strcmp(he->ms.sym->name, ann->sym_hist_filter) != 0))
313 goto find_next;
314
241 notes = symbol__annotation(he->ms.sym); 315 notes = symbol__annotation(he->ms.sym);
242 if (notes->src == NULL) { 316 if (notes->src == NULL) {
243find_next: 317find_next:
@@ -269,6 +343,7 @@ find_next:
269 nd = rb_next(nd); 343 nd = rb_next(nd);
270 } else if (use_browser == 1) { 344 } else if (use_browser == 1) {
271 key = hist_entry__tui_annotate(he, evsel, NULL); 345 key = hist_entry__tui_annotate(he, evsel, NULL);
346
272 switch (key) { 347 switch (key) {
273 case -1: 348 case -1:
274 if (!ann->skip_missing) 349 if (!ann->skip_missing)
@@ -420,6 +495,9 @@ int cmd_annotate(int argc, const char **argv)
420 OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"), 495 OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"),
421 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"), 496 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
422 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"), 497 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
498 OPT_BOOLEAN(0, "stdio2", &annotate.use_stdio2, "Use the stdio interface"),
499 OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
500 "don't load vmlinux even if found"),
423 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 501 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
424 "file", "vmlinux pathname"), 502 "file", "vmlinux pathname"),
425 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 503 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
@@ -489,20 +567,22 @@ int cmd_annotate(int argc, const char **argv)
489 if (annotate.session == NULL) 567 if (annotate.session == NULL)
490 return -1; 568 return -1;
491 569
570 annotate.has_br_stack = perf_header__has_feat(&annotate.session->header,
571 HEADER_BRANCH_STACK);
572
492 ret = symbol__annotation_init(); 573 ret = symbol__annotation_init();
493 if (ret < 0) 574 if (ret < 0)
494 goto out_delete; 575 goto out_delete;
495 576
577 annotation_config__init();
578
496 symbol_conf.try_vmlinux_path = true; 579 symbol_conf.try_vmlinux_path = true;
497 580
498 ret = symbol__init(&annotate.session->header.env); 581 ret = symbol__init(&annotate.session->header.env);
499 if (ret < 0) 582 if (ret < 0)
500 goto out_delete; 583 goto out_delete;
501 584
502 if (setup_sorting(NULL) < 0) 585 if (annotate.use_stdio || annotate.use_stdio2)
503 usage_with_options(annotate_usage, options);
504
505 if (annotate.use_stdio)
506 use_browser = 0; 586 use_browser = 0;
507 else if (annotate.use_tui) 587 else if (annotate.use_tui)
508 use_browser = 1; 588 use_browser = 1;
@@ -511,6 +591,15 @@ int cmd_annotate(int argc, const char **argv)
511 591
512 setup_browser(true); 592 setup_browser(true);
513 593
594 if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack) {
595 sort__mode = SORT_MODE__BRANCH;
596 if (setup_sorting(annotate.session->evlist) < 0)
597 usage_with_options(annotate_usage, options);
598 } else {
599 if (setup_sorting(NULL) < 0)
600 usage_with_options(annotate_usage, options);
601 }
602
514 ret = __cmd_annotate(&annotate); 603 ret = __cmd_annotate(&annotate);
515 604
516out_delete: 605out_delete: