0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "builtin.h"
0010
0011 #include "util/color.h"
0012 #include <linux/list.h>
0013 #include "util/cache.h"
0014 #include <linux/rbtree.h>
0015 #include <linux/zalloc.h>
0016 #include "util/symbol.h"
0017
0018 #include "perf.h"
0019 #include "util/debug.h"
0020
0021 #include "util/evlist.h"
0022 #include "util/evsel.h"
0023 #include "util/annotate.h"
0024 #include "util/event.h"
0025 #include <subcmd/parse-options.h>
0026 #include "util/parse-events.h"
0027 #include "util/sort.h"
0028 #include "util/hist.h"
0029 #include "util/dso.h"
0030 #include "util/machine.h"
0031 #include "util/map.h"
0032 #include "util/session.h"
0033 #include "util/tool.h"
0034 #include "util/data.h"
0035 #include "arch/common.h"
0036 #include "util/block-range.h"
0037 #include "util/map_symbol.h"
0038 #include "util/branch.h"
0039
0040 #include <dlfcn.h>
0041 #include <errno.h>
0042 #include <linux/bitmap.h>
0043 #include <linux/err.h>
0044
0045 struct perf_annotate {
0046 struct perf_tool tool;
0047 struct perf_session *session;
0048 struct annotation_options opts;
0049 #ifdef HAVE_SLANG_SUPPORT
0050 bool use_tui;
0051 #endif
0052 bool use_stdio, use_stdio2;
0053 #ifdef HAVE_GTK2_SUPPORT
0054 bool use_gtk;
0055 #endif
0056 bool skip_missing;
0057 bool has_br_stack;
0058 bool group_set;
0059 float min_percent;
0060 const char *sym_hist_filter;
0061 const char *cpu_list;
0062 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
0063 };
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 static void process_basic_block(struct addr_map_symbol *start,
0090 struct addr_map_symbol *end,
0091 struct branch_flags *flags)
0092 {
0093 struct symbol *sym = start->ms.sym;
0094 struct annotation *notes = sym ? symbol__annotation(sym) : NULL;
0095 struct block_range_iter iter;
0096 struct block_range *entry;
0097
0098
0099
0100
0101 if (!start->addr || start->addr > end->addr)
0102 return;
0103
0104 iter = block_range__create(start->addr, end->addr);
0105 if (!block_range_iter__valid(&iter))
0106 return;
0107
0108
0109
0110
0111 entry = block_range_iter(&iter);
0112 assert(entry->is_target);
0113 entry->entry++;
0114
0115 do {
0116 entry = block_range_iter(&iter);
0117
0118 entry->coverage++;
0119 entry->sym = sym;
0120
0121 if (notes)
0122 notes->max_coverage = max(notes->max_coverage, entry->coverage);
0123
0124 } while (block_range_iter__next(&iter));
0125
0126
0127
0128
0129 entry = block_range_iter(&iter);
0130 assert(entry->is_branch);
0131 entry->taken++;
0132 if (flags->predicted)
0133 entry->pred++;
0134 }
0135
0136 static void process_branch_stack(struct branch_stack *bs, struct addr_location *al,
0137 struct perf_sample *sample)
0138 {
0139 struct addr_map_symbol *prev = NULL;
0140 struct branch_info *bi;
0141 int i;
0142
0143 if (!bs || !bs->nr)
0144 return;
0145
0146 bi = sample__resolve_bstack(sample, al);
0147 if (!bi)
0148 return;
0149
0150 for (i = bs->nr - 1; i >= 0; i--) {
0151
0152
0153
0154 if (prev)
0155 process_basic_block(prev, &bi[i].from, &bi[i].flags);
0156 prev = &bi[i].to;
0157 }
0158
0159 free(bi);
0160 }
0161
0162 static int hist_iter__branch_callback(struct hist_entry_iter *iter,
0163 struct addr_location *al __maybe_unused,
0164 bool single __maybe_unused,
0165 void *arg __maybe_unused)
0166 {
0167 struct hist_entry *he = iter->he;
0168 struct branch_info *bi;
0169 struct perf_sample *sample = iter->sample;
0170 struct evsel *evsel = iter->evsel;
0171 int err;
0172
0173 bi = he->branch_info;
0174 err = addr_map_symbol__inc_samples(&bi->from, sample, evsel);
0175
0176 if (err)
0177 goto out;
0178
0179 err = addr_map_symbol__inc_samples(&bi->to, sample, evsel);
0180
0181 out:
0182 return err;
0183 }
0184
0185 static int process_branch_callback(struct evsel *evsel,
0186 struct perf_sample *sample,
0187 struct addr_location *al __maybe_unused,
0188 struct perf_annotate *ann,
0189 struct machine *machine)
0190 {
0191 struct hist_entry_iter iter = {
0192 .evsel = evsel,
0193 .sample = sample,
0194 .add_entry_cb = hist_iter__branch_callback,
0195 .hide_unresolved = symbol_conf.hide_unresolved,
0196 .ops = &hist_iter_branch,
0197 };
0198
0199 struct addr_location a;
0200
0201 if (machine__resolve(machine, &a, sample) < 0)
0202 return -1;
0203
0204 if (a.sym == NULL)
0205 return 0;
0206
0207 if (a.map != NULL)
0208 a.map->dso->hit = 1;
0209
0210 hist__account_cycles(sample->branch_stack, al, sample, false, NULL);
0211
0212 return hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann);
0213 }
0214
0215 static bool has_annotation(struct perf_annotate *ann)
0216 {
0217 return ui__has_annotation() || ann->use_stdio2;
0218 }
0219
0220 static int evsel__add_sample(struct evsel *evsel, struct perf_sample *sample,
0221 struct addr_location *al, struct perf_annotate *ann,
0222 struct machine *machine)
0223 {
0224 struct hists *hists = evsel__hists(evsel);
0225 struct hist_entry *he;
0226 int ret;
0227
0228 if ((!ann->has_br_stack || !has_annotation(ann)) &&
0229 ann->sym_hist_filter != NULL &&
0230 (al->sym == NULL ||
0231 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) {
0232
0233
0234
0235
0236
0237 if (al->sym != NULL) {
0238 rb_erase_cached(&al->sym->rb_node,
0239 &al->map->dso->symbols);
0240 symbol__delete(al->sym);
0241 dso__reset_find_symbol_cache(al->map->dso);
0242 }
0243 return 0;
0244 }
0245
0246
0247
0248
0249
0250 process_branch_stack(sample->branch_stack, al, sample);
0251
0252 if (ann->has_br_stack && has_annotation(ann))
0253 return process_branch_callback(evsel, sample, al, ann, machine);
0254
0255 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
0256 if (he == NULL)
0257 return -ENOMEM;
0258
0259 ret = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
0260 hists__inc_nr_samples(hists, true);
0261 return ret;
0262 }
0263
0264 static int process_sample_event(struct perf_tool *tool,
0265 union perf_event *event,
0266 struct perf_sample *sample,
0267 struct evsel *evsel,
0268 struct machine *machine)
0269 {
0270 struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool);
0271 struct addr_location al;
0272 int ret = 0;
0273
0274 if (machine__resolve(machine, &al, sample) < 0) {
0275 pr_warning("problem processing %d event, skipping it.\n",
0276 event->header.type);
0277 return -1;
0278 }
0279
0280 if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
0281 goto out_put;
0282
0283 if (!al.filtered &&
0284 evsel__add_sample(evsel, sample, &al, ann, machine)) {
0285 pr_warning("problem incrementing symbol count, "
0286 "skipping event\n");
0287 ret = -1;
0288 }
0289 out_put:
0290 addr_location__put(&al);
0291 return ret;
0292 }
0293
0294 static int process_feature_event(struct perf_session *session,
0295 union perf_event *event)
0296 {
0297 if (event->feat.feat_id < HEADER_LAST_FEATURE)
0298 return perf_event__process_feature(session, event);
0299 return 0;
0300 }
0301
0302 static int hist_entry__tty_annotate(struct hist_entry *he,
0303 struct evsel *evsel,
0304 struct perf_annotate *ann)
0305 {
0306 if (!ann->use_stdio2)
0307 return symbol__tty_annotate(&he->ms, evsel, &ann->opts);
0308
0309 return symbol__tty_annotate2(&he->ms, evsel, &ann->opts);
0310 }
0311
0312 static void hists__find_annotations(struct hists *hists,
0313 struct evsel *evsel,
0314 struct perf_annotate *ann)
0315 {
0316 struct rb_node *nd = rb_first_cached(&hists->entries), *next;
0317 int key = K_RIGHT;
0318
0319 while (nd) {
0320 struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
0321 struct annotation *notes;
0322
0323 if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned)
0324 goto find_next;
0325
0326 if (ann->sym_hist_filter &&
0327 (strcmp(he->ms.sym->name, ann->sym_hist_filter) != 0))
0328 goto find_next;
0329
0330 if (ann->min_percent) {
0331 float percent = 0;
0332 u64 total = hists__total_period(hists);
0333
0334 if (total)
0335 percent = 100.0 * he->stat.period / total;
0336
0337 if (percent < ann->min_percent)
0338 goto find_next;
0339 }
0340
0341 notes = symbol__annotation(he->ms.sym);
0342 if (notes->src == NULL) {
0343 find_next:
0344 if (key == K_LEFT)
0345 nd = rb_prev(nd);
0346 else
0347 nd = rb_next(nd);
0348 continue;
0349 }
0350
0351 if (use_browser == 2) {
0352 int ret;
0353 int (*annotate)(struct hist_entry *he,
0354 struct evsel *evsel,
0355 struct hist_browser_timer *hbt);
0356
0357 annotate = dlsym(perf_gtk_handle,
0358 "hist_entry__gtk_annotate");
0359 if (annotate == NULL) {
0360 ui__error("GTK browser not found!\n");
0361 return;
0362 }
0363
0364 ret = annotate(he, evsel, NULL);
0365 if (!ret || !ann->skip_missing)
0366 return;
0367
0368
0369 nd = rb_next(nd);
0370 } else if (use_browser == 1) {
0371 key = hist_entry__tui_annotate(he, evsel, NULL, &ann->opts);
0372
0373 switch (key) {
0374 case -1:
0375 if (!ann->skip_missing)
0376 return;
0377
0378 case K_RIGHT:
0379 next = rb_next(nd);
0380 break;
0381 case K_LEFT:
0382 next = rb_prev(nd);
0383 break;
0384 default:
0385 return;
0386 }
0387
0388 if (next != NULL)
0389 nd = next;
0390 } else {
0391 hist_entry__tty_annotate(he, evsel, ann);
0392 nd = rb_next(nd);
0393 }
0394 }
0395 }
0396
0397 static int __cmd_annotate(struct perf_annotate *ann)
0398 {
0399 int ret;
0400 struct perf_session *session = ann->session;
0401 struct evsel *pos;
0402 u64 total_nr_samples;
0403
0404 if (ann->cpu_list) {
0405 ret = perf_session__cpu_bitmap(session, ann->cpu_list,
0406 ann->cpu_bitmap);
0407 if (ret)
0408 goto out;
0409 }
0410
0411 if (!ann->opts.objdump_path) {
0412 ret = perf_env__lookup_objdump(&session->header.env,
0413 &ann->opts.objdump_path);
0414 if (ret)
0415 goto out;
0416 }
0417
0418 ret = perf_session__process_events(session);
0419 if (ret)
0420 goto out;
0421
0422 if (dump_trace) {
0423 perf_session__fprintf_nr_events(session, stdout, false);
0424 evlist__fprintf_nr_events(session->evlist, stdout, false);
0425 goto out;
0426 }
0427
0428 if (verbose > 3)
0429 perf_session__fprintf(session, stdout);
0430
0431 if (verbose > 2)
0432 perf_session__fprintf_dsos(session, stdout);
0433
0434 total_nr_samples = 0;
0435 evlist__for_each_entry(session->evlist, pos) {
0436 struct hists *hists = evsel__hists(pos);
0437 u32 nr_samples = hists->stats.nr_samples;
0438
0439 if (nr_samples > 0) {
0440 total_nr_samples += nr_samples;
0441 hists__collapse_resort(hists, NULL);
0442
0443 evsel__reset_sample_bit(pos, CALLCHAIN);
0444 evsel__output_resort(pos, NULL);
0445
0446 if (symbol_conf.event_group && !evsel__is_group_leader(pos))
0447 continue;
0448
0449 hists__find_annotations(hists, pos, ann);
0450 }
0451 }
0452
0453 if (total_nr_samples == 0) {
0454 ui__error("The %s data has no samples!\n", session->data->path);
0455 goto out;
0456 }
0457
0458 if (use_browser == 2) {
0459 void (*show_annotations)(void);
0460
0461 show_annotations = dlsym(perf_gtk_handle,
0462 "perf_gtk__show_annotations");
0463 if (show_annotations == NULL) {
0464 ui__error("GTK browser not found!\n");
0465 goto out;
0466 }
0467 show_annotations();
0468 }
0469
0470 out:
0471 return ret;
0472 }
0473
0474 static int parse_percent_limit(const struct option *opt, const char *str,
0475 int unset __maybe_unused)
0476 {
0477 struct perf_annotate *ann = opt->value;
0478 double pcnt = strtof(str, NULL);
0479
0480 ann->min_percent = pcnt;
0481 return 0;
0482 }
0483
0484 static const char * const annotate_usage[] = {
0485 "perf annotate [<options>]",
0486 NULL
0487 };
0488
0489 int cmd_annotate(int argc, const char **argv)
0490 {
0491 struct perf_annotate annotate = {
0492 .tool = {
0493 .sample = process_sample_event,
0494 .mmap = perf_event__process_mmap,
0495 .mmap2 = perf_event__process_mmap2,
0496 .comm = perf_event__process_comm,
0497 .exit = perf_event__process_exit,
0498 .fork = perf_event__process_fork,
0499 .namespaces = perf_event__process_namespaces,
0500 .attr = perf_event__process_attr,
0501 .build_id = perf_event__process_build_id,
0502 .tracing_data = perf_event__process_tracing_data,
0503 .id_index = perf_event__process_id_index,
0504 .auxtrace_info = perf_event__process_auxtrace_info,
0505 .auxtrace = perf_event__process_auxtrace,
0506 .feature = process_feature_event,
0507 .ordered_events = true,
0508 .ordering_requires_timestamps = true,
0509 },
0510 .opts = annotation__default_options,
0511 };
0512 struct perf_data data = {
0513 .mode = PERF_DATA_MODE_READ,
0514 };
0515 struct itrace_synth_opts itrace_synth_opts = {
0516 .set = 0,
0517 };
0518 struct option options[] = {
0519 OPT_STRING('i', "input", &input_name, "file",
0520 "input file name"),
0521 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
0522 "only consider symbols in these dsos"),
0523 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol",
0524 "symbol to annotate"),
0525 OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"),
0526 OPT_INCR('v', "verbose", &verbose,
0527 "be more verbose (show symbol address, etc)"),
0528 OPT_BOOLEAN('q', "quiet", &quiet, "do now show any message"),
0529 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
0530 "dump raw trace in ASCII"),
0531 #ifdef HAVE_GTK2_SUPPORT
0532 OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"),
0533 #endif
0534 #ifdef HAVE_SLANG_SUPPORT
0535 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
0536 #endif
0537 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
0538 OPT_BOOLEAN(0, "stdio2", &annotate.use_stdio2, "Use the stdio interface"),
0539 OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
0540 "don't load vmlinux even if found"),
0541 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
0542 "file", "vmlinux pathname"),
0543 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
0544 "load module symbols - WARNING: use only with -k and LIVE kernel"),
0545 OPT_BOOLEAN('l', "print-line", &annotate.opts.print_lines,
0546 "print matching source lines (may be slow)"),
0547 OPT_BOOLEAN('P', "full-paths", &annotate.opts.full_path,
0548 "Don't shorten the displayed pathnames"),
0549 OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing,
0550 "Skip symbols that cannot be annotated"),
0551 OPT_BOOLEAN_SET(0, "group", &symbol_conf.event_group,
0552 &annotate.group_set,
0553 "Show event group information together"),
0554 OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"),
0555 OPT_CALLBACK(0, "symfs", NULL, "directory",
0556 "Look for files with symbols relative to this directory",
0557 symbol__config_symfs),
0558 OPT_BOOLEAN(0, "source", &annotate.opts.annotate_src,
0559 "Interleave source code with assembly code (default)"),
0560 OPT_BOOLEAN(0, "asm-raw", &annotate.opts.show_asm_raw,
0561 "Display raw encoding of assembly instructions (default)"),
0562 OPT_STRING('M', "disassembler-style", &annotate.opts.disassembler_style, "disassembler style",
0563 "Specify disassembler style (e.g. -M intel for intel syntax)"),
0564 OPT_STRING(0, "prefix", &annotate.opts.prefix, "prefix",
0565 "Add prefix to source file path names in programs (with --prefix-strip)"),
0566 OPT_STRING(0, "prefix-strip", &annotate.opts.prefix_strip, "N",
0567 "Strip first N entries of source file path name in programs (with --prefix)"),
0568 OPT_STRING(0, "objdump", &annotate.opts.objdump_path, "path",
0569 "objdump binary to use for disassembly and annotations"),
0570 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
0571 "Enable symbol demangling"),
0572 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
0573 "Enable kernel symbol demangling"),
0574 OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
0575 "Show event group information together"),
0576 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
0577 "Show a column with the sum of periods"),
0578 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
0579 "Show a column with the number of samples"),
0580 OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
0581 "'always' (default), 'never' or 'auto' only applicable to --stdio mode",
0582 stdio__config_color, "always"),
0583 OPT_CALLBACK(0, "percent-type", &annotate.opts, "local-period",
0584 "Set percent type local/global-period/hits",
0585 annotate_parse_percent_type),
0586 OPT_CALLBACK(0, "percent-limit", &annotate, "percent",
0587 "Don't show entries under that percent", parse_percent_limit),
0588 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
0589 "Instruction Tracing options\n" ITRACE_HELP,
0590 itrace_parse_synth_opts),
0591
0592 OPT_END()
0593 };
0594 int ret;
0595
0596 set_option_flag(options, 0, "show-total-period", PARSE_OPT_EXCLUSIVE);
0597 set_option_flag(options, 0, "show-nr-samples", PARSE_OPT_EXCLUSIVE);
0598
0599
0600 ret = hists__init();
0601 if (ret < 0)
0602 return ret;
0603
0604 annotation_config__init(&annotate.opts);
0605
0606 argc = parse_options(argc, argv, options, annotate_usage, 0);
0607 if (argc) {
0608
0609
0610
0611
0612 if (argc > 1)
0613 usage_with_options(annotate_usage, options);
0614
0615 annotate.sym_hist_filter = argv[0];
0616 }
0617
0618 if (annotate_check_args(&annotate.opts) < 0)
0619 return -EINVAL;
0620
0621 #ifdef HAVE_GTK2_SUPPORT
0622 if (symbol_conf.show_nr_samples && annotate.use_gtk) {
0623 pr_err("--show-nr-samples is not available in --gtk mode at this time\n");
0624 return ret;
0625 }
0626 #endif
0627
0628 ret = symbol__validate_sym_arguments();
0629 if (ret)
0630 return ret;
0631
0632 if (quiet)
0633 perf_quiet_option();
0634
0635 data.path = input_name;
0636
0637 annotate.session = perf_session__new(&data, &annotate.tool);
0638 if (IS_ERR(annotate.session))
0639 return PTR_ERR(annotate.session);
0640
0641 annotate.session->itrace_synth_opts = &itrace_synth_opts;
0642
0643 annotate.has_br_stack = perf_header__has_feat(&annotate.session->header,
0644 HEADER_BRANCH_STACK);
0645
0646 if (annotate.group_set)
0647 evlist__force_leader(annotate.session->evlist);
0648
0649 ret = symbol__annotation_init();
0650 if (ret < 0)
0651 goto out_delete;
0652
0653 symbol_conf.try_vmlinux_path = true;
0654
0655 ret = symbol__init(&annotate.session->header.env);
0656 if (ret < 0)
0657 goto out_delete;
0658
0659 if (annotate.use_stdio || annotate.use_stdio2)
0660 use_browser = 0;
0661 #ifdef HAVE_SLANG_SUPPORT
0662 else if (annotate.use_tui)
0663 use_browser = 1;
0664 #endif
0665 #ifdef HAVE_GTK2_SUPPORT
0666 else if (annotate.use_gtk)
0667 use_browser = 2;
0668 #endif
0669
0670 setup_browser(true);
0671
0672
0673
0674
0675
0676
0677 sort_order = "dso,symbol";
0678
0679
0680
0681
0682
0683 if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack)
0684 sort__mode = SORT_MODE__BRANCH;
0685
0686 if (setup_sorting(NULL) < 0)
0687 usage_with_options(annotate_usage, options);
0688
0689 ret = __cmd_annotate(&annotate);
0690
0691 out_delete:
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704 return ret;
0705 }