diff options
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r-- | tools/perf/builtin-annotate.c | 123 |
1 files changed, 89 insertions, 34 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 6c0a0412502e..f839e69492e8 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -46,10 +46,17 @@ struct perf_annotate { struct perf_tool tool; struct perf_session *session; struct annotation_options opts; - bool use_tui, use_stdio, use_stdio2, use_gtk; +#ifdef HAVE_SLANG_SUPPORT + bool use_tui; +#endif + bool use_stdio, use_stdio2; +#ifdef HAVE_GTK2_SUPPORT + bool use_gtk; +#endif bool skip_missing; bool has_br_stack; bool group_set; + float min_percent; const char *sym_hist_filter; const char *cpu_list; DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); @@ -190,7 +197,6 @@ static int process_branch_callback(struct evsel *evsel, }; struct addr_location a; - int ret; if (machine__resolve(machine, &a, sample) < 0) return -1; @@ -203,8 +209,7 @@ static int process_branch_callback(struct evsel *evsel, hist__account_cycles(sample->branch_stack, al, sample, false, NULL); - ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann); - return ret; + return hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann); } static bool has_annotation(struct perf_annotate *ann) @@ -212,11 +217,9 @@ static bool has_annotation(struct perf_annotate *ann) return ui__has_annotation() || ann->use_stdio2; } -static int perf_evsel__add_sample(struct evsel *evsel, - struct perf_sample *sample, - struct addr_location *al, - struct perf_annotate *ann, - struct machine *machine) +static int evsel__add_sample(struct evsel *evsel, struct perf_sample *sample, + struct addr_location *al, struct perf_annotate *ann, + struct machine *machine) { struct hists *hists = evsel__hists(evsel); struct hist_entry *he; @@ -241,7 +244,7 @@ static int perf_evsel__add_sample(struct evsel *evsel, } /* - * XXX filtered samples can still have branch entires pointing into our + * XXX filtered samples can still have branch entries pointing into our * symbol and are missed. */ process_branch_stack(sample->branch_stack, al, sample); @@ -278,7 +281,7 @@ static int process_sample_event(struct perf_tool *tool, goto out_put; if (!al.filtered && - perf_evsel__add_sample(evsel, sample, &al, ann, machine)) { + evsel__add_sample(evsel, sample, &al, ann, machine)) { pr_warning("problem incrementing symbol count, " "skipping event\n"); ret = -1; @@ -324,6 +327,17 @@ static void hists__find_annotations(struct hists *hists, (strcmp(he->ms.sym->name, ann->sym_hist_filter) != 0)) goto find_next; + if (ann->min_percent) { + float percent = 0; + u64 total = hists__total_period(hists); + + if (total) + percent = 100.0 * he->stat.period / total; + + if (percent < ann->min_percent) + goto find_next; + } + notes = symbol__annotation(he->ms.sym); if (notes->src == NULL) { find_next: @@ -376,13 +390,6 @@ find_next: } else { hist_entry__tty_annotate(he, evsel, ann); nd = rb_next(nd); - /* - * Since we have a hist_entry per IP for the same - * symbol, free he->ms.sym->src to signal we already - * processed this symbol. - */ - zfree(¬es->src->cycles_hist); - zfree(¬es->src); } } } @@ -413,8 +420,8 @@ static int __cmd_annotate(struct perf_annotate *ann) goto out; if (dump_trace) { - perf_session__fprintf_nr_events(session, stdout); - perf_evlist__fprintf_nr_events(session->evlist, stdout); + perf_session__fprintf_nr_events(session, stdout, false); + evlist__fprintf_nr_events(session->evlist, stdout, false); goto out; } @@ -427,17 +434,16 @@ static int __cmd_annotate(struct perf_annotate *ann) total_nr_samples = 0; evlist__for_each_entry(session->evlist, pos) { struct hists *hists = evsel__hists(pos); - u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; + u32 nr_samples = hists->stats.nr_samples; if (nr_samples > 0) { total_nr_samples += nr_samples; hists__collapse_resort(hists, NULL); /* Don't sort callchain */ - perf_evsel__reset_sample_bit(pos, CALLCHAIN); - perf_evsel__output_resort(pos, NULL); + evsel__reset_sample_bit(pos, CALLCHAIN); + evsel__output_resort(pos, NULL); - if (symbol_conf.event_group && - !perf_evsel__is_group_leader(pos)) + if (symbol_conf.event_group && !evsel__is_group_leader(pos)) continue; hists__find_annotations(hists, pos, ann); @@ -465,6 +471,16 @@ out: return ret; } +static int parse_percent_limit(const struct option *opt, const char *str, + int unset __maybe_unused) +{ + struct perf_annotate *ann = opt->value; + double pcnt = strtof(str, NULL); + + ann->min_percent = pcnt; + return 0; +} + static const char * const annotate_usage[] = { "perf annotate [<options>]", NULL @@ -484,6 +500,9 @@ int cmd_annotate(int argc, const char **argv) .attr = perf_event__process_attr, .build_id = perf_event__process_build_id, .tracing_data = perf_event__process_tracing_data, + .id_index = perf_event__process_id_index, + .auxtrace_info = perf_event__process_auxtrace_info, + .auxtrace = perf_event__process_auxtrace, .feature = process_feature_event, .ordered_events = true, .ordering_requires_timestamps = true, @@ -493,6 +512,9 @@ int cmd_annotate(int argc, const char **argv) struct perf_data data = { .mode = PERF_DATA_MODE_READ, }; + struct itrace_synth_opts itrace_synth_opts = { + .set = 0, + }; struct option options[] = { OPT_STRING('i', "input", &input_name, "file", "input file name"), @@ -506,8 +528,12 @@ int cmd_annotate(int argc, const char **argv) OPT_BOOLEAN('q', "quiet", &quiet, "do now show any message"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), +#ifdef HAVE_GTK2_SUPPORT OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"), +#endif +#ifdef HAVE_SLANG_SUPPORT OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"), +#endif OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"), OPT_BOOLEAN(0, "stdio2", &annotate.use_stdio2, "Use the stdio interface"), OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux, @@ -541,6 +567,10 @@ int cmd_annotate(int argc, const char **argv) "Strip first N entries of source file path name in programs (with --prefix)"), OPT_STRING(0, "objdump", &annotate.opts.objdump_path, "path", "objdump binary to use for disassembly and annotations"), + OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, + "Enable symbol demangling"), + OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, + "Enable kernel symbol demangling"), OPT_BOOLEAN(0, "group", &symbol_conf.event_group, "Show event group information together"), OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, @@ -553,6 +583,11 @@ int cmd_annotate(int argc, const char **argv) OPT_CALLBACK(0, "percent-type", &annotate.opts, "local-period", "Set percent type local/global-period/hits", annotate_parse_percent_type), + OPT_CALLBACK(0, "percent-limit", &annotate, "percent", + "Don't show entries under that percent", parse_percent_limit), + OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", + "Instruction Tracing options\n" ITRACE_HELP, + itrace_parse_synth_opts), OPT_END() }; @@ -583,25 +618,33 @@ int cmd_annotate(int argc, const char **argv) if (annotate_check_args(&annotate.opts) < 0) return -EINVAL; +#ifdef HAVE_GTK2_SUPPORT if (symbol_conf.show_nr_samples && annotate.use_gtk) { pr_err("--show-nr-samples is not available in --gtk mode at this time\n"); return ret; } +#endif + + ret = symbol__validate_sym_arguments(); + if (ret) + return ret; if (quiet) perf_quiet_option(); data.path = input_name; - annotate.session = perf_session__new(&data, false, &annotate.tool); + annotate.session = perf_session__new(&data, &annotate.tool); if (IS_ERR(annotate.session)) return PTR_ERR(annotate.session); + annotate.session->itrace_synth_opts = &itrace_synth_opts; + annotate.has_br_stack = perf_header__has_feat(&annotate.session->header, HEADER_BRANCH_STACK); if (annotate.group_set) - perf_evlist__force_leader(annotate.session->evlist); + evlist__force_leader(annotate.session->evlist); ret = symbol__annotation_init(); if (ret < 0) @@ -615,21 +658,33 @@ int cmd_annotate(int argc, const char **argv) if (annotate.use_stdio || annotate.use_stdio2) use_browser = 0; +#ifdef HAVE_SLANG_SUPPORT else if (annotate.use_tui) use_browser = 1; +#endif +#ifdef HAVE_GTK2_SUPPORT else if (annotate.use_gtk) use_browser = 2; +#endif setup_browser(true); - if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack) { + /* + * Events of different processes may correspond to the same + * symbol, we do not care about the processes in annotate, + * set sort order to avoid repeated output. + */ + sort_order = "dso,symbol"; + + /* + * Set SORT_MODE__BRANCH so that annotate display IPC/Cycle + * if branch info is in perf data in TUI mode. + */ + if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack) sort__mode = SORT_MODE__BRANCH; - if (setup_sorting(annotate.session->evlist) < 0) - usage_with_options(annotate_usage, options); - } else { - if (setup_sorting(NULL) < 0) - usage_with_options(annotate_usage, options); - } + + if (setup_sorting(NULL) < 0) + usage_with_options(annotate_usage, options); ret = __cmd_annotate(&annotate); |