1 /* 2 * builtin-report.c 3 * 4 * Builtin report command: Analyze the perf.data input file, 5 * look up and read DSOs and symbol information and display 6 * a histogram of results, along various sorting keys. 7 */ 8 #include "builtin.h" 9 10 #include "util/util.h" 11 #include "util/cache.h" 12 13 #include "util/annotate.h" 14 #include "util/color.h" 15 #include <linux/list.h> 16 #include <linux/rbtree.h> 17 #include "util/symbol.h" 18 #include "util/callchain.h" 19 #include "util/strlist.h" 20 #include "util/values.h" 21 22 #include "perf.h" 23 #include "util/debug.h" 24 #include "util/evlist.h" 25 #include "util/evsel.h" 26 #include "util/header.h" 27 #include "util/session.h" 28 #include "util/tool.h" 29 30 #include "util/parse-options.h" 31 #include "util/parse-events.h" 32 33 #include "util/thread.h" 34 #include "util/sort.h" 35 #include "util/hist.h" 36 #include "util/data.h" 37 #include "arch/common.h" 38 39 #include "util/auxtrace.h" 40 41 #include <dlfcn.h> 42 #include <linux/bitmap.h> 43 44 struct report { 45 struct perf_tool tool; 46 struct perf_session *session; 47 bool force, use_tui, use_gtk, use_stdio; 48 bool hide_unresolved; 49 bool dont_use_callchains; 50 bool show_full_info; 51 bool show_threads; 52 bool inverted_callchain; 53 bool mem_mode; 54 bool header; 55 bool header_only; 56 bool nonany_branch_mode; 57 int max_stack; 58 struct perf_read_values show_threads_values; 59 const char *pretty_printing_style; 60 const char *cpu_list; 61 const char *symbol_filter_str; 62 float min_percent; 63 u64 nr_entries; 64 u64 queue_size; 65 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 66 }; 67 68 static int report__config(const char *var, const char *value, void *cb) 69 { 70 struct report *rep = cb; 71 72 if (!strcmp(var, "report.group")) { 73 symbol_conf.event_group = perf_config_bool(var, value); 74 return 0; 75 } 76 if (!strcmp(var, "report.percent-limit")) { 77 rep->min_percent = strtof(value, NULL); 78 return 0; 79 } 80 if (!strcmp(var, "report.children")) { 81 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 82 return 0; 83 } 84 if (!strcmp(var, "report.queue-size")) { 85 rep->queue_size = perf_config_u64(var, value); 86 return 0; 87 } 88 89 return perf_default_config(var, value, cb); 90 } 91 92 static int hist_iter__report_callback(struct hist_entry_iter *iter, 93 struct addr_location *al, bool single, 94 void *arg) 95 { 96 int err = 0; 97 struct report *rep = arg; 98 struct hist_entry *he = iter->he; 99 struct perf_evsel *evsel = iter->evsel; 100 struct mem_info *mi; 101 struct branch_info *bi; 102 103 if (!ui__has_annotation()) 104 return 0; 105 106 hist__account_cycles(iter->sample->branch_stack, al, iter->sample, 107 rep->nonany_branch_mode); 108 109 if (sort__mode == SORT_MODE__BRANCH) { 110 bi = he->branch_info; 111 err = addr_map_symbol__inc_samples(&bi->from, evsel->idx); 112 if (err) 113 goto out; 114 115 err = addr_map_symbol__inc_samples(&bi->to, evsel->idx); 116 117 } else if (rep->mem_mode) { 118 mi = he->mem_info; 119 err = addr_map_symbol__inc_samples(&mi->daddr, evsel->idx); 120 if (err) 121 goto out; 122 123 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 124 125 } else if (symbol_conf.cumulate_callchain) { 126 if (single) 127 err = hist_entry__inc_addr_samples(he, evsel->idx, 128 al->addr); 129 } else { 130 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 131 } 132 133 out: 134 return err; 135 } 136 137 static int process_sample_event(struct perf_tool *tool, 138 union perf_event *event, 139 struct perf_sample *sample, 140 struct perf_evsel *evsel, 141 struct machine *machine) 142 { 143 struct report *rep = container_of(tool, struct report, tool); 144 struct addr_location al; 145 struct hist_entry_iter iter = { 146 .evsel = evsel, 147 .sample = sample, 148 .hide_unresolved = rep->hide_unresolved, 149 .add_entry_cb = hist_iter__report_callback, 150 }; 151 int ret = 0; 152 153 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { 154 pr_debug("problem processing %d event, skipping it.\n", 155 event->header.type); 156 return -1; 157 } 158 159 if (rep->hide_unresolved && al.sym == NULL) 160 goto out_put; 161 162 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap)) 163 goto out_put; 164 165 if (sort__mode == SORT_MODE__BRANCH) 166 iter.ops = &hist_iter_branch; 167 else if (rep->mem_mode) 168 iter.ops = &hist_iter_mem; 169 else if (symbol_conf.cumulate_callchain) 170 iter.ops = &hist_iter_cumulative; 171 else 172 iter.ops = &hist_iter_normal; 173 174 if (al.map != NULL) 175 al.map->dso->hit = 1; 176 177 ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep); 178 if (ret < 0) 179 pr_debug("problem adding hist entry, skipping event\n"); 180 out_put: 181 addr_location__put(&al); 182 return ret; 183 } 184 185 static int process_read_event(struct perf_tool *tool, 186 union perf_event *event, 187 struct perf_sample *sample __maybe_unused, 188 struct perf_evsel *evsel, 189 struct machine *machine __maybe_unused) 190 { 191 struct report *rep = container_of(tool, struct report, tool); 192 193 if (rep->show_threads) { 194 const char *name = evsel ? perf_evsel__name(evsel) : "unknown"; 195 perf_read_values_add_value(&rep->show_threads_values, 196 event->read.pid, event->read.tid, 197 event->read.id, 198 name, 199 event->read.value); 200 } 201 202 dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid, 203 evsel ? perf_evsel__name(evsel) : "FAIL", 204 event->read.value); 205 206 return 0; 207 } 208 209 /* For pipe mode, sample_type is not currently set */ 210 static int report__setup_sample_type(struct report *rep) 211 { 212 struct perf_session *session = rep->session; 213 u64 sample_type = perf_evlist__combined_sample_type(session->evlist); 214 bool is_pipe = perf_data_file__is_pipe(session->file); 215 216 if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { 217 if (sort__has_parent) { 218 ui__error("Selected --sort parent, but no " 219 "callchain data. Did you call " 220 "'perf record' without -g?\n"); 221 return -EINVAL; 222 } 223 if (symbol_conf.use_callchain) { 224 ui__error("Selected -g or --branch-history but no " 225 "callchain data. Did\n" 226 "you call 'perf record' without -g?\n"); 227 return -1; 228 } 229 } else if (!rep->dont_use_callchains && 230 callchain_param.mode != CHAIN_NONE && 231 !symbol_conf.use_callchain) { 232 symbol_conf.use_callchain = true; 233 if (callchain_register_param(&callchain_param) < 0) { 234 ui__error("Can't register callchain params.\n"); 235 return -EINVAL; 236 } 237 } 238 239 if (symbol_conf.cumulate_callchain) { 240 /* Silently ignore if callchain is missing */ 241 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) { 242 symbol_conf.cumulate_callchain = false; 243 perf_hpp__cancel_cumulate(); 244 } 245 } 246 247 if (sort__mode == SORT_MODE__BRANCH) { 248 if (!is_pipe && 249 !(sample_type & PERF_SAMPLE_BRANCH_STACK)) { 250 ui__error("Selected -b but no branch data. " 251 "Did you call perf record without -b?\n"); 252 return -1; 253 } 254 } 255 256 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) { 257 if ((sample_type & PERF_SAMPLE_REGS_USER) && 258 (sample_type & PERF_SAMPLE_STACK_USER)) 259 callchain_param.record_mode = CALLCHAIN_DWARF; 260 else if (sample_type & PERF_SAMPLE_BRANCH_STACK) 261 callchain_param.record_mode = CALLCHAIN_LBR; 262 else 263 callchain_param.record_mode = CALLCHAIN_FP; 264 } 265 266 /* ??? handle more cases than just ANY? */ 267 if (!(perf_evlist__combined_branch_type(session->evlist) & 268 PERF_SAMPLE_BRANCH_ANY)) 269 rep->nonany_branch_mode = true; 270 271 return 0; 272 } 273 274 static void sig_handler(int sig __maybe_unused) 275 { 276 session_done = 1; 277 } 278 279 static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep, 280 const char *evname, FILE *fp) 281 { 282 size_t ret; 283 char unit; 284 unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 285 u64 nr_events = hists->stats.total_period; 286 struct perf_evsel *evsel = hists_to_evsel(hists); 287 char buf[512]; 288 size_t size = sizeof(buf); 289 290 if (symbol_conf.filter_relative) { 291 nr_samples = hists->stats.nr_non_filtered_samples; 292 nr_events = hists->stats.total_non_filtered_period; 293 } 294 295 if (perf_evsel__is_group_event(evsel)) { 296 struct perf_evsel *pos; 297 298 perf_evsel__group_desc(evsel, buf, size); 299 evname = buf; 300 301 for_each_group_member(pos, evsel) { 302 const struct hists *pos_hists = evsel__hists(pos); 303 304 if (symbol_conf.filter_relative) { 305 nr_samples += pos_hists->stats.nr_non_filtered_samples; 306 nr_events += pos_hists->stats.total_non_filtered_period; 307 } else { 308 nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE]; 309 nr_events += pos_hists->stats.total_period; 310 } 311 } 312 } 313 314 nr_samples = convert_unit(nr_samples, &unit); 315 ret = fprintf(fp, "# Samples: %lu%c", nr_samples, unit); 316 if (evname != NULL) 317 ret += fprintf(fp, " of event '%s'", evname); 318 319 if (symbol_conf.show_ref_callgraph && 320 strstr(evname, "call-graph=no")) { 321 ret += fprintf(fp, ", show reference callgraph"); 322 } 323 324 if (rep->mem_mode) { 325 ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events); 326 ret += fprintf(fp, "\n# Sort order : %s", sort_order ? : default_mem_sort_order); 327 } else 328 ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events); 329 return ret + fprintf(fp, "\n#\n"); 330 } 331 332 static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, 333 struct report *rep, 334 const char *help) 335 { 336 struct perf_evsel *pos; 337 338 fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples); 339 evlist__for_each(evlist, pos) { 340 struct hists *hists = evsel__hists(pos); 341 const char *evname = perf_evsel__name(pos); 342 343 if (symbol_conf.event_group && 344 !perf_evsel__is_group_leader(pos)) 345 continue; 346 347 hists__fprintf_nr_sample_events(hists, rep, evname, stdout); 348 hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout); 349 fprintf(stdout, "\n\n"); 350 } 351 352 if (sort_order == NULL && 353 parent_pattern == default_parent_pattern) 354 fprintf(stdout, "#\n# (%s)\n#\n", help); 355 356 if (rep->show_threads) { 357 bool style = !strcmp(rep->pretty_printing_style, "raw"); 358 perf_read_values_display(stdout, &rep->show_threads_values, 359 style); 360 perf_read_values_destroy(&rep->show_threads_values); 361 } 362 363 return 0; 364 } 365 366 static void report__warn_kptr_restrict(const struct report *rep) 367 { 368 struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION]; 369 struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL; 370 371 if (kernel_map == NULL || 372 (kernel_map->dso->hit && 373 (kernel_kmap->ref_reloc_sym == NULL || 374 kernel_kmap->ref_reloc_sym->addr == 0))) { 375 const char *desc = 376 "As no suitable kallsyms nor vmlinux was found, kernel samples\n" 377 "can't be resolved."; 378 379 if (kernel_map) { 380 const struct dso *kdso = kernel_map->dso; 381 if (!RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION])) { 382 desc = "If some relocation was applied (e.g. " 383 "kexec) symbols may be misresolved."; 384 } 385 } 386 387 ui__warning( 388 "Kernel address maps (/proc/{kallsyms,modules}) were restricted.\n\n" 389 "Check /proc/sys/kernel/kptr_restrict before running 'perf record'.\n\n%s\n\n" 390 "Samples in kernel modules can't be resolved as well.\n\n", 391 desc); 392 } 393 } 394 395 static int report__gtk_browse_hists(struct report *rep, const char *help) 396 { 397 int (*hist_browser)(struct perf_evlist *evlist, const char *help, 398 struct hist_browser_timer *timer, float min_pcnt); 399 400 hist_browser = dlsym(perf_gtk_handle, "perf_evlist__gtk_browse_hists"); 401 402 if (hist_browser == NULL) { 403 ui__error("GTK browser not found!\n"); 404 return -1; 405 } 406 407 return hist_browser(rep->session->evlist, help, NULL, rep->min_percent); 408 } 409 410 static int report__browse_hists(struct report *rep) 411 { 412 int ret; 413 struct perf_session *session = rep->session; 414 struct perf_evlist *evlist = session->evlist; 415 const char *help = "For a higher level overview, try: perf report --sort comm,dso"; 416 417 switch (use_browser) { 418 case 1: 419 ret = perf_evlist__tui_browse_hists(evlist, help, NULL, 420 rep->min_percent, 421 &session->header.env); 422 /* 423 * Usually "ret" is the last pressed key, and we only 424 * care if the key notifies us to switch data file. 425 */ 426 if (ret != K_SWITCH_INPUT_DATA) 427 ret = 0; 428 break; 429 case 2: 430 ret = report__gtk_browse_hists(rep, help); 431 break; 432 default: 433 ret = perf_evlist__tty_browse_hists(evlist, rep, help); 434 break; 435 } 436 437 return ret; 438 } 439 440 static void report__collapse_hists(struct report *rep) 441 { 442 struct ui_progress prog; 443 struct perf_evsel *pos; 444 445 ui_progress__init(&prog, rep->nr_entries, "Merging related events..."); 446 447 evlist__for_each(rep->session->evlist, pos) { 448 struct hists *hists = evsel__hists(pos); 449 450 if (pos->idx == 0) 451 hists->symbol_filter_str = rep->symbol_filter_str; 452 453 hists__collapse_resort(hists, &prog); 454 455 /* Non-group events are considered as leader */ 456 if (symbol_conf.event_group && 457 !perf_evsel__is_group_leader(pos)) { 458 struct hists *leader_hists = evsel__hists(pos->leader); 459 460 hists__match(leader_hists, hists); 461 hists__link(leader_hists, hists); 462 } 463 } 464 465 ui_progress__finish(); 466 } 467 468 static void report__output_resort(struct report *rep) 469 { 470 struct ui_progress prog; 471 struct perf_evsel *pos; 472 473 ui_progress__init(&prog, rep->nr_entries, "Sorting events for output..."); 474 475 evlist__for_each(rep->session->evlist, pos) 476 hists__output_resort(evsel__hists(pos), &prog); 477 478 ui_progress__finish(); 479 } 480 481 static int __cmd_report(struct report *rep) 482 { 483 int ret; 484 struct perf_session *session = rep->session; 485 struct perf_evsel *pos; 486 struct perf_data_file *file = session->file; 487 488 signal(SIGINT, sig_handler); 489 490 if (rep->cpu_list) { 491 ret = perf_session__cpu_bitmap(session, rep->cpu_list, 492 rep->cpu_bitmap); 493 if (ret) 494 return ret; 495 } 496 497 if (rep->show_threads) 498 perf_read_values_init(&rep->show_threads_values); 499 500 ret = report__setup_sample_type(rep); 501 if (ret) 502 return ret; 503 504 ret = perf_session__process_events(session); 505 if (ret) 506 return ret; 507 508 report__warn_kptr_restrict(rep); 509 510 evlist__for_each(session->evlist, pos) 511 rep->nr_entries += evsel__hists(pos)->nr_entries; 512 513 if (use_browser == 0) { 514 if (verbose > 3) 515 perf_session__fprintf(session, stdout); 516 517 if (verbose > 2) 518 perf_session__fprintf_dsos(session, stdout); 519 520 if (dump_trace) { 521 perf_session__fprintf_nr_events(session, stdout); 522 perf_evlist__fprintf_nr_events(session->evlist, stdout); 523 return 0; 524 } 525 } 526 527 report__collapse_hists(rep); 528 529 if (session_done()) 530 return 0; 531 532 /* 533 * recalculate number of entries after collapsing since it 534 * might be changed during the collapse phase. 535 */ 536 rep->nr_entries = 0; 537 evlist__for_each(session->evlist, pos) 538 rep->nr_entries += evsel__hists(pos)->nr_entries; 539 540 if (rep->nr_entries == 0) { 541 ui__error("The %s file has no samples!\n", file->path); 542 return 0; 543 } 544 545 report__output_resort(rep); 546 547 return report__browse_hists(rep); 548 } 549 550 static int 551 report_parse_callchain_opt(const struct option *opt, const char *arg, int unset) 552 { 553 struct report *rep = (struct report *)opt->value; 554 555 /* 556 * --no-call-graph 557 */ 558 if (unset) { 559 rep->dont_use_callchains = true; 560 return 0; 561 } 562 563 return parse_callchain_report_opt(arg); 564 } 565 566 int 567 report_parse_ignore_callees_opt(const struct option *opt __maybe_unused, 568 const char *arg, int unset __maybe_unused) 569 { 570 if (arg) { 571 int err = regcomp(&ignore_callees_regex, arg, REG_EXTENDED); 572 if (err) { 573 char buf[BUFSIZ]; 574 regerror(err, &ignore_callees_regex, buf, sizeof(buf)); 575 pr_err("Invalid --ignore-callees regex: %s\n%s", arg, buf); 576 return -1; 577 } 578 have_ignore_callees = 1; 579 } 580 581 return 0; 582 } 583 584 static int 585 parse_branch_mode(const struct option *opt __maybe_unused, 586 const char *str __maybe_unused, int unset) 587 { 588 int *branch_mode = opt->value; 589 590 *branch_mode = !unset; 591 return 0; 592 } 593 594 static int 595 parse_percent_limit(const struct option *opt, const char *str, 596 int unset __maybe_unused) 597 { 598 struct report *rep = opt->value; 599 600 rep->min_percent = strtof(str, NULL); 601 return 0; 602 } 603 604 int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) 605 { 606 struct perf_session *session; 607 struct itrace_synth_opts itrace_synth_opts = { .set = 0, }; 608 struct stat st; 609 bool has_br_stack = false; 610 int branch_mode = -1; 611 bool branch_call_mode = false; 612 char callchain_default_opt[] = "fractal,0.5,callee"; 613 const char * const report_usage[] = { 614 "perf report [<options>]", 615 NULL 616 }; 617 struct report report = { 618 .tool = { 619 .sample = process_sample_event, 620 .mmap = perf_event__process_mmap, 621 .mmap2 = perf_event__process_mmap2, 622 .comm = perf_event__process_comm, 623 .exit = perf_event__process_exit, 624 .fork = perf_event__process_fork, 625 .lost = perf_event__process_lost, 626 .read = process_read_event, 627 .attr = perf_event__process_attr, 628 .tracing_data = perf_event__process_tracing_data, 629 .build_id = perf_event__process_build_id, 630 .id_index = perf_event__process_id_index, 631 .auxtrace_info = perf_event__process_auxtrace_info, 632 .auxtrace = perf_event__process_auxtrace, 633 .ordered_events = true, 634 .ordering_requires_timestamps = true, 635 }, 636 .max_stack = PERF_MAX_STACK_DEPTH, 637 .pretty_printing_style = "normal", 638 }; 639 const struct option options[] = { 640 OPT_STRING('i', "input", &input_name, "file", 641 "input file name"), 642 OPT_INCR('v', "verbose", &verbose, 643 "be more verbose (show symbol address, etc)"), 644 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 645 "dump raw trace in ASCII"), 646 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 647 "file", "vmlinux pathname"), 648 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, 649 "file", "kallsyms pathname"), 650 OPT_BOOLEAN('f', "force", &report.force, "don't complain, do it"), 651 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 652 "load module symbols - WARNING: use only with -k and LIVE kernel"), 653 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 654 "Show a column with the number of samples"), 655 OPT_BOOLEAN('T', "threads", &report.show_threads, 656 "Show per-thread event counters"), 657 OPT_STRING(0, "pretty", &report.pretty_printing_style, "key", 658 "pretty printing style key: normal raw"), 659 OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"), 660 OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"), 661 OPT_BOOLEAN(0, "stdio", &report.use_stdio, 662 "Use the stdio interface"), 663 OPT_BOOLEAN(0, "header", &report.header, "Show data header."), 664 OPT_BOOLEAN(0, "header-only", &report.header_only, 665 "Show only data header."), 666 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 667 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..." 668 " Please refer the man page for the complete list."), 669 OPT_STRING('F', "fields", &field_order, "key[,keys...]", 670 "output field(s): overhead, period, sample plus all of sort keys"), 671 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, 672 "Show sample percentage for different cpu modes"), 673 OPT_STRING('p', "parent", &parent_pattern, "regex", 674 "regex filter to identify parent, see: '--sort parent'"), 675 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 676 "Only display entries with parent-match"), 677 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order[,branch]", 678 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address), add branches. " 679 "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt), 680 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, 681 "Accumulate callchains of children and show total overhead as well"), 682 OPT_INTEGER(0, "max-stack", &report.max_stack, 683 "Set the maximum stack depth when parsing the callchain, " 684 "anything beyond the specified depth will be ignored. " 685 "Default: " __stringify(PERF_MAX_STACK_DEPTH)), 686 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain, 687 "alias for inverted call graph"), 688 OPT_CALLBACK(0, "ignore-callees", NULL, "regex", 689 "ignore callees of these functions in call graphs", 690 report_parse_ignore_callees_opt), 691 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 692 "only consider symbols in these dsos"), 693 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 694 "only consider symbols in these comms"), 695 OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]", 696 "only consider symbols in these pids"), 697 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]", 698 "only consider symbols in these tids"), 699 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 700 "only consider these symbols"), 701 OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter", 702 "only show symbols that (partially) match with this filter"), 703 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str, 704 "width[,width...]", 705 "don't try to adjust column width, use these fixed values"), 706 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator", 707 "separator for columns, no spaces will be added between " 708 "columns '.' is reserved."), 709 OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved, 710 "Only display entries resolved to a symbol"), 711 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 712 "Look for files with symbols relative to this directory"), 713 OPT_STRING('C', "cpu", &report.cpu_list, "cpu", 714 "list of cpus to profile"), 715 OPT_BOOLEAN('I', "show-info", &report.show_full_info, 716 "Display extended information about perf.data file"), 717 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 718 "Interleave source code with assembly code (default)"), 719 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 720 "Display raw encoding of assembly instructions (default)"), 721 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 722 "Specify disassembler style (e.g. -M intel for intel syntax)"), 723 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 724 "Show a column with the sum of periods"), 725 OPT_BOOLEAN(0, "group", &symbol_conf.event_group, 726 "Show event group information together"), 727 OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "", 728 "use branch records for per branch histogram filling", 729 parse_branch_mode), 730 OPT_BOOLEAN(0, "branch-history", &branch_call_mode, 731 "add last branch records to call history"), 732 OPT_STRING(0, "objdump", &objdump_path, "path", 733 "objdump binary to use for disassembly and annotations"), 734 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 735 "Disable symbol demangling"), 736 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, 737 "Enable kernel symbol demangling"), 738 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), 739 OPT_CALLBACK(0, "percent-limit", &report, "percent", 740 "Don't show entries under that percent", parse_percent_limit), 741 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 742 "how to display percentage of filtered entries", parse_filter_percentage), 743 OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", 744 "Instruction Tracing options", 745 itrace_parse_synth_opts), 746 OPT_BOOLEAN(0, "full-source-path", &srcline_full_filename, 747 "Show full source file name path for source lines"), 748 OPT_BOOLEAN(0, "show-ref-call-graph", &symbol_conf.show_ref_callgraph, 749 "Show callgraph from reference event"), 750 OPT_END() 751 }; 752 struct perf_data_file file = { 753 .mode = PERF_DATA_MODE_READ, 754 }; 755 int ret = hists__init(); 756 757 if (ret < 0) 758 return ret; 759 760 perf_config(report__config, &report); 761 762 argc = parse_options(argc, argv, options, report_usage, 0); 763 764 if (symbol_conf.vmlinux_name && 765 access(symbol_conf.vmlinux_name, R_OK)) { 766 pr_err("Invalid file: %s\n", symbol_conf.vmlinux_name); 767 return -EINVAL; 768 } 769 if (symbol_conf.kallsyms_name && 770 access(symbol_conf.kallsyms_name, R_OK)) { 771 pr_err("Invalid file: %s\n", symbol_conf.kallsyms_name); 772 return -EINVAL; 773 } 774 775 if (report.use_stdio) 776 use_browser = 0; 777 else if (report.use_tui) 778 use_browser = 1; 779 else if (report.use_gtk) 780 use_browser = 2; 781 782 if (report.inverted_callchain) 783 callchain_param.order = ORDER_CALLER; 784 785 if (!input_name || !strlen(input_name)) { 786 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) 787 input_name = "-"; 788 else 789 input_name = "perf.data"; 790 } 791 792 file.path = input_name; 793 file.force = report.force; 794 795 repeat: 796 session = perf_session__new(&file, false, &report.tool); 797 if (session == NULL) 798 return -1; 799 800 if (report.queue_size) { 801 ordered_events__set_alloc_size(&session->ordered_events, 802 report.queue_size); 803 } 804 805 session->itrace_synth_opts = &itrace_synth_opts; 806 807 report.session = session; 808 809 has_br_stack = perf_header__has_feat(&session->header, 810 HEADER_BRANCH_STACK); 811 812 /* 813 * Branch mode is a tristate: 814 * -1 means default, so decide based on the file having branch data. 815 * 0/1 means the user chose a mode. 816 */ 817 if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) && 818 !branch_call_mode) { 819 sort__mode = SORT_MODE__BRANCH; 820 symbol_conf.cumulate_callchain = false; 821 } 822 if (branch_call_mode) { 823 callchain_param.key = CCKEY_ADDRESS; 824 callchain_param.branch_callstack = 1; 825 symbol_conf.use_callchain = true; 826 callchain_register_param(&callchain_param); 827 if (sort_order == NULL) 828 sort_order = "srcline,symbol,dso"; 829 } 830 831 if (report.mem_mode) { 832 if (sort__mode == SORT_MODE__BRANCH) { 833 pr_err("branch and mem mode incompatible\n"); 834 goto error; 835 } 836 sort__mode = SORT_MODE__MEMORY; 837 symbol_conf.cumulate_callchain = false; 838 } 839 840 if (setup_sorting() < 0) { 841 if (sort_order) 842 parse_options_usage(report_usage, options, "s", 1); 843 if (field_order) 844 parse_options_usage(sort_order ? NULL : report_usage, 845 options, "F", 1); 846 goto error; 847 } 848 849 /* Force tty output for header output and per-thread stat. */ 850 if (report.header || report.header_only || report.show_threads) 851 use_browser = 0; 852 853 if (strcmp(input_name, "-") != 0) 854 setup_browser(true); 855 else 856 use_browser = 0; 857 858 if (report.header || report.header_only) { 859 perf_session__fprintf_info(session, stdout, 860 report.show_full_info); 861 if (report.header_only) { 862 ret = 0; 863 goto error; 864 } 865 } else if (use_browser == 0) { 866 fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n", 867 stdout); 868 } 869 870 /* 871 * Only in the TUI browser we are doing integrated annotation, 872 * so don't allocate extra space that won't be used in the stdio 873 * implementation. 874 */ 875 if (ui__has_annotation()) { 876 symbol_conf.priv_size = sizeof(struct annotation); 877 machines__set_symbol_filter(&session->machines, 878 symbol__annotate_init); 879 /* 880 * For searching by name on the "Browse map details". 881 * providing it only in verbose mode not to bloat too 882 * much struct symbol. 883 */ 884 if (verbose) { 885 /* 886 * XXX: Need to provide a less kludgy way to ask for 887 * more space per symbol, the u32 is for the index on 888 * the ui browser. 889 * See symbol__browser_index. 890 */ 891 symbol_conf.priv_size += sizeof(u32); 892 symbol_conf.sort_by_name = true; 893 } 894 } 895 896 if (symbol__init(&session->header.env) < 0) 897 goto error; 898 899 if (argc) { 900 /* 901 * Special case: if there's an argument left then assume that 902 * it's a symbol filter: 903 */ 904 if (argc > 1) 905 usage_with_options(report_usage, options); 906 907 report.symbol_filter_str = argv[0]; 908 } 909 910 sort__setup_elide(stdout); 911 912 ret = __cmd_report(&report); 913 if (ret == K_SWITCH_INPUT_DATA) { 914 perf_session__delete(session); 915 goto repeat; 916 } else 917 ret = 0; 918 919 error: 920 perf_session__delete(session); 921 return ret; 922 } 923