aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-report.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-report.c')
-rw-r--r--tools/perf/builtin-report.c94
1 files changed, 52 insertions, 42 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 3662047cc6b1..72eae7498c09 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -49,7 +49,6 @@ struct perf_report {
49 bool mem_mode; 49 bool mem_mode;
50 struct perf_read_values show_threads_values; 50 struct perf_read_values show_threads_values;
51 const char *pretty_printing_style; 51 const char *pretty_printing_style;
52 symbol_filter_t annotate_init;
53 const char *cpu_list; 52 const char *cpu_list;
54 const char *symbol_filter_str; 53 const char *symbol_filter_str;
55 float min_percent; 54 float min_percent;
@@ -89,7 +88,7 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool,
89 if ((sort__has_parent || symbol_conf.use_callchain) && 88 if ((sort__has_parent || symbol_conf.use_callchain) &&
90 sample->callchain) { 89 sample->callchain) {
91 err = machine__resolve_callchain(machine, evsel, al->thread, 90 err = machine__resolve_callchain(machine, evsel, al->thread,
92 sample, &parent); 91 sample, &parent, al);
93 if (err) 92 if (err)
94 return err; 93 return err;
95 } 94 }
@@ -180,7 +179,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
180 if ((sort__has_parent || symbol_conf.use_callchain) 179 if ((sort__has_parent || symbol_conf.use_callchain)
181 && sample->callchain) { 180 && sample->callchain) {
182 err = machine__resolve_callchain(machine, evsel, al->thread, 181 err = machine__resolve_callchain(machine, evsel, al->thread,
183 sample, &parent); 182 sample, &parent, al);
184 if (err) 183 if (err)
185 return err; 184 return err;
186 } 185 }
@@ -254,7 +253,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
254 253
255 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { 254 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
256 err = machine__resolve_callchain(machine, evsel, al->thread, 255 err = machine__resolve_callchain(machine, evsel, al->thread,
257 sample, &parent); 256 sample, &parent, al);
258 if (err) 257 if (err)
259 return err; 258 return err;
260 } 259 }
@@ -305,8 +304,7 @@ static int process_sample_event(struct perf_tool *tool,
305 struct addr_location al; 304 struct addr_location al;
306 int ret; 305 int ret;
307 306
308 if (perf_event__preprocess_sample(event, machine, &al, sample, 307 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
309 rep->annotate_init) < 0) {
310 fprintf(stderr, "problem processing %d event, skipping it.\n", 308 fprintf(stderr, "problem processing %d event, skipping it.\n",
311 event->header.type); 309 event->header.type);
312 return -1; 310 return -1;
@@ -367,7 +365,7 @@ static int process_read_event(struct perf_tool *tool,
367static int perf_report__setup_sample_type(struct perf_report *rep) 365static int perf_report__setup_sample_type(struct perf_report *rep)
368{ 366{
369 struct perf_session *self = rep->session; 367 struct perf_session *self = rep->session;
370 u64 sample_type = perf_evlist__sample_type(self->evlist); 368 u64 sample_type = perf_evlist__combined_sample_type(self->evlist);
371 369
372 if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { 370 if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
373 if (sort__has_parent) { 371 if (sort__has_parent) {
@@ -403,8 +401,6 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
403 return 0; 401 return 0;
404} 402}
405 403
406extern volatile int session_done;
407
408static void sig_handler(int sig __maybe_unused) 404static void sig_handler(int sig __maybe_unused)
409{ 405{
410 session_done = 1; 406 session_done = 1;
@@ -497,7 +493,7 @@ static int __cmd_report(struct perf_report *rep)
497 ret = perf_session__cpu_bitmap(session, rep->cpu_list, 493 ret = perf_session__cpu_bitmap(session, rep->cpu_list,
498 rep->cpu_bitmap); 494 rep->cpu_bitmap);
499 if (ret) 495 if (ret)
500 goto out_delete; 496 return ret;
501 } 497 }
502 498
503 if (use_browser <= 0) 499 if (use_browser <= 0)
@@ -508,11 +504,11 @@ static int __cmd_report(struct perf_report *rep)
508 504
509 ret = perf_report__setup_sample_type(rep); 505 ret = perf_report__setup_sample_type(rep);
510 if (ret) 506 if (ret)
511 goto out_delete; 507 return ret;
512 508
513 ret = perf_session__process_events(session, &rep->tool); 509 ret = perf_session__process_events(session, &rep->tool);
514 if (ret) 510 if (ret)
515 goto out_delete; 511 return ret;
516 512
517 kernel_map = session->machines.host.vmlinux_maps[MAP__FUNCTION]; 513 kernel_map = session->machines.host.vmlinux_maps[MAP__FUNCTION];
518 kernel_kmap = map__kmap(kernel_map); 514 kernel_kmap = map__kmap(kernel_map);
@@ -547,7 +543,7 @@ static int __cmd_report(struct perf_report *rep)
547 543
548 if (dump_trace) { 544 if (dump_trace) {
549 perf_session__fprintf_nr_events(session, stdout); 545 perf_session__fprintf_nr_events(session, stdout);
550 goto out_delete; 546 return 0;
551 } 547 }
552 548
553 nr_samples = 0; 549 nr_samples = 0;
@@ -570,9 +566,12 @@ static int __cmd_report(struct perf_report *rep)
570 } 566 }
571 } 567 }
572 568
569 if (session_done())
570 return 0;
571
573 if (nr_samples == 0) { 572 if (nr_samples == 0) {
574 ui__error("The %s file has no samples!\n", session->filename); 573 ui__error("The %s file has no samples!\n", session->filename);
575 goto out_delete; 574 return 0;
576 } 575 }
577 576
578 list_for_each_entry(pos, &session->evlist->entries, node) 577 list_for_each_entry(pos, &session->evlist->entries, node)
@@ -598,19 +597,6 @@ static int __cmd_report(struct perf_report *rep)
598 } else 597 } else
599 perf_evlist__tty_browse_hists(session->evlist, rep, help); 598 perf_evlist__tty_browse_hists(session->evlist, rep, help);
600 599
601out_delete:
602 /*
603 * Speed up the exit process, for large files this can
604 * take quite a while.
605 *
606 * XXX Enable this when using valgrind or if we ever
607 * librarize this command.
608 *
609 * Also experiment with obstacks to see how much speed
610 * up we'll get here.
611 *
612 * perf_session__delete(session);
613 */
614 return ret; 600 return ret;
615} 601}
616 602
@@ -680,12 +666,23 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
680 } 666 }
681 667
682 /* get the call chain order */ 668 /* get the call chain order */
683 if (!strcmp(tok2, "caller")) 669 if (!strncmp(tok2, "caller", strlen("caller")))
684 callchain_param.order = ORDER_CALLER; 670 callchain_param.order = ORDER_CALLER;
685 else if (!strcmp(tok2, "callee")) 671 else if (!strncmp(tok2, "callee", strlen("callee")))
686 callchain_param.order = ORDER_CALLEE; 672 callchain_param.order = ORDER_CALLEE;
687 else 673 else
688 return -1; 674 return -1;
675
676 /* Get the sort key */
677 tok2 = strtok(NULL, ",");
678 if (!tok2)
679 goto setup;
680 if (!strncmp(tok2, "function", strlen("function")))
681 callchain_param.key = CCKEY_FUNCTION;
682 else if (!strncmp(tok2, "address", strlen("address")))
683 callchain_param.key = CCKEY_ADDRESS;
684 else
685 return -1;
689setup: 686setup:
690 if (callchain_register_param(&callchain_param) < 0) { 687 if (callchain_register_param(&callchain_param) < 0) {
691 fprintf(stderr, "Can't register callchain params\n"); 688 fprintf(stderr, "Can't register callchain params\n");
@@ -694,6 +691,24 @@ setup:
694 return 0; 691 return 0;
695} 692}
696 693
694int
695report_parse_ignore_callees_opt(const struct option *opt __maybe_unused,
696 const char *arg, int unset __maybe_unused)
697{
698 if (arg) {
699 int err = regcomp(&ignore_callees_regex, arg, REG_EXTENDED);
700 if (err) {
701 char buf[BUFSIZ];
702 regerror(err, &ignore_callees_regex, buf, sizeof(buf));
703 pr_err("Invalid --ignore-callees regex: %s\n%s", arg, buf);
704 return -1;
705 }
706 have_ignore_callees = 1;
707 }
708
709 return 0;
710}
711
697static int 712static int
698parse_branch_mode(const struct option *opt __maybe_unused, 713parse_branch_mode(const struct option *opt __maybe_unused,
699 const char *str __maybe_unused, int unset) 714 const char *str __maybe_unused, int unset)
@@ -730,13 +745,13 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
730 .tool = { 745 .tool = {
731 .sample = process_sample_event, 746 .sample = process_sample_event,
732 .mmap = perf_event__process_mmap, 747 .mmap = perf_event__process_mmap,
748 .mmap2 = perf_event__process_mmap2,
733 .comm = perf_event__process_comm, 749 .comm = perf_event__process_comm,
734 .exit = perf_event__process_exit, 750 .exit = perf_event__process_exit,
735 .fork = perf_event__process_fork, 751 .fork = perf_event__process_fork,
736 .lost = perf_event__process_lost, 752 .lost = perf_event__process_lost,
737 .read = process_read_event, 753 .read = process_read_event,
738 .attr = perf_event__process_attr, 754 .attr = perf_event__process_attr,
739 .event_type = perf_event__process_event_type,
740 .tracing_data = perf_event__process_tracing_data, 755 .tracing_data = perf_event__process_tracing_data,
741 .build_id = perf_event__process_build_id, 756 .build_id = perf_event__process_build_id,
742 .ordered_samples = true, 757 .ordered_samples = true,
@@ -780,10 +795,13 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
780 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 795 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
781 "Only display entries with parent-match"), 796 "Only display entries with parent-match"),
782 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order", 797 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
783 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit and callchain order. " 798 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). "
784 "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt), 799 "Default: fractal,0.5,callee,function", &parse_callchain_opt, callchain_default_opt),
785 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain, 800 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
786 "alias for inverted call graph"), 801 "alias for inverted call graph"),
802 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
803 "ignore callees of these functions in call graphs",
804 report_parse_ignore_callees_opt),
787 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 805 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
788 "only consider symbols in these dsos"), 806 "only consider symbols in these dsos"),
789 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 807 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
@@ -853,7 +871,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
853 setup_browser(true); 871 setup_browser(true);
854 else { 872 else {
855 use_browser = 0; 873 use_browser = 0;
856 perf_hpp__column_enable(PERF_HPP__OVERHEAD);
857 perf_hpp__init(); 874 perf_hpp__init();
858 } 875 }
859 876
@@ -907,7 +924,8 @@ repeat:
907 */ 924 */
908 if (use_browser == 1 && sort__has_sym) { 925 if (use_browser == 1 && sort__has_sym) {
909 symbol_conf.priv_size = sizeof(struct annotation); 926 symbol_conf.priv_size = sizeof(struct annotation);
910 report.annotate_init = symbol__annotate_init; 927 machines__set_symbol_filter(&session->machines,
928 symbol__annotate_init);
911 /* 929 /*
912 * For searching by name on the "Browse map details". 930 * For searching by name on the "Browse map details".
913 * providing it only in verbose mode not to bloat too 931 * providing it only in verbose mode not to bloat too
@@ -931,14 +949,6 @@ repeat:
931 if (parent_pattern != default_parent_pattern) { 949 if (parent_pattern != default_parent_pattern) {
932 if (sort_dimension__add("parent") < 0) 950 if (sort_dimension__add("parent") < 0)
933 goto error; 951 goto error;
934
935 /*
936 * Only show the parent fields if we explicitly
937 * sort that way. If we only use parent machinery
938 * for filtering, we don't want it.
939 */
940 if (!strstr(sort_order, "parent"))
941 sort_parent.elide = 1;
942 } 952 }
943 953
944 if (argc) { 954 if (argc) {