--- zzzz-none-000/linux-3.10.107/tools/perf/builtin-annotate.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/tools/perf/builtin-annotate.c 2021-02-04 17:41:59.000000000 +0000 @@ -28,13 +28,16 @@ #include "util/hist.h" #include "util/session.h" #include "util/tool.h" +#include "util/data.h" #include "arch/common.h" +#include #include struct perf_annotate { struct perf_tool tool; - bool force, use_tui, use_stdio, use_gtk; + struct perf_session *session; + bool use_tui, use_stdio, use_gtk; bool full_paths; bool print_line; bool skip_missing; @@ -44,10 +47,11 @@ }; static int perf_evsel__add_sample(struct perf_evsel *evsel, - struct perf_sample *sample, + struct perf_sample *sample __maybe_unused, struct addr_location *al, struct perf_annotate *ann) { + struct hists *hists = evsel__hists(evsel); struct hist_entry *he; int ret; @@ -55,29 +59,25 @@ (al->sym == NULL || strcmp(ann->sym_hist_filter, al->sym->name) != 0)) { /* We're only interested in a symbol named sym_hist_filter */ + /* + * FIXME: why isn't this done in the symbol_filter when loading + * the DSO? + */ if (al->sym != NULL) { rb_erase(&al->sym->rb_node, &al->map->dso->symbols[al->map->type]); symbol__delete(al->sym); + dso__reset_find_symbol_cache(al->map->dso); } return 0; } - he = __hists__add_entry(&evsel->hists, al, NULL, 1, 1); + he = __hists__add_entry(hists, al, NULL, NULL, NULL, 1, 1, 0, true); if (he == NULL) return -ENOMEM; - ret = 0; - if (he->ms.sym != NULL) { - struct annotation *notes = symbol__annotation(he->ms.sym); - if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0) - return -ENOMEM; - - ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); - } - - evsel->hists.stats.total_period += sample->period; - hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); + ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); + hists__inc_nr_samples(hists, true); return ret; } @@ -89,24 +89,25 @@ { struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool); struct addr_location al; + int ret = 0; - if (perf_event__preprocess_sample(event, machine, &al, sample, - symbol__annotate_init) < 0) { + if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { pr_warning("problem processing %d event, skipping it.\n", event->header.type); return -1; } if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap)) - return 0; + goto out_put; if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) { pr_warning("problem incrementing symbol count, " "skipping event\n"); - return -1; + ret = -1; } - - return 0; +out_put: + addr_location__put(&al); + return ret; } static int hist_entry__tty_annotate(struct hist_entry *he, @@ -117,11 +118,11 @@ ann->print_line, ann->full_paths, 0, 0); } -static void hists__find_annotations(struct hists *self, +static void hists__find_annotations(struct hists *hists, struct perf_evsel *evsel, struct perf_annotate *ann) { - struct rb_node *nd = rb_first(&self->entries), *next; + struct rb_node *nd = rb_first(&hists->entries), *next; int key = K_RIGHT; while (nd) { @@ -143,8 +144,18 @@ if (use_browser == 2) { int ret; + int (*annotate)(struct hist_entry *he, + struct perf_evsel *evsel, + struct hist_browser_timer *hbt); + + annotate = dlsym(perf_gtk_handle, + "hist_entry__gtk_annotate"); + if (annotate == NULL) { + ui__error("GTK browser not found!\n"); + return; + } - ret = hist_entry__gtk_annotate(he, evsel, NULL); + ret = annotate(he, evsel, NULL); if (!ret || !ann->skip_missing) return; @@ -177,8 +188,8 @@ * symbol, free he->ms.sym->src to signal we already * processed this symbol. */ - free(notes->src); - notes->src = NULL; + zfree(¬es->src->cycles_hist); + zfree(¬es->src); } } } @@ -186,35 +197,33 @@ static int __cmd_annotate(struct perf_annotate *ann) { int ret; - struct perf_session *session; + struct perf_session *session = ann->session; struct perf_evsel *pos; u64 total_nr_samples; - session = perf_session__new(input_name, O_RDONLY, - ann->force, false, &ann->tool); - if (session == NULL) - return -ENOMEM; + machines__set_symbol_filter(&session->machines, symbol__annotate_init); if (ann->cpu_list) { ret = perf_session__cpu_bitmap(session, ann->cpu_list, ann->cpu_bitmap); if (ret) - goto out_delete; + goto out; } if (!objdump_path) { - ret = perf_session_env__lookup_objdump(&session->header.env); + ret = perf_env__lookup_objdump(&session->header.env); if (ret) - goto out_delete; + goto out; } - ret = perf_session__process_events(session, &ann->tool); + ret = perf_session__process_events(session); if (ret) - goto out_delete; + goto out; if (dump_trace) { perf_session__fprintf_nr_events(session, stdout); - goto out_delete; + perf_evlist__fprintf_nr_events(session->evlist, stdout); + goto out; } if (verbose > 3) @@ -224,14 +233,16 @@ perf_session__fprintf_dsos(session, stdout); total_nr_samples = 0; - list_for_each_entry(pos, &session->evlist->entries, node) { - struct hists *hists = &pos->hists; + evlist__for_each(session->evlist, pos) { + struct hists *hists = evsel__hists(pos); u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; if (nr_samples > 0) { total_nr_samples += nr_samples; - hists__collapse_resort(hists); - hists__output_resort(hists); + hists__collapse_resort(hists, NULL); + /* Don't sort callchain */ + perf_evsel__reset_sample_bit(pos, CALLCHAIN); + hists__output_resort(hists, NULL); if (symbol_conf.event_group && !perf_evsel__is_group_leader(pos)) @@ -242,26 +253,23 @@ } if (total_nr_samples == 0) { - ui__error("The %s file has no samples!\n", session->filename); - goto out_delete; + ui__error("The %s file has no samples!\n", session->file->path); + goto out; } - if (use_browser == 2) - perf_gtk__show_annotations(); + if (use_browser == 2) { + void (*show_annotations)(void); -out_delete: - /* - * Speed up the exit process, for large files this can - * take quite a while. - * - * XXX Enable this when using valgrind or if we ever - * librarize this command. - * - * Also experiment with obstacks to see how much speed - * up we'll get here. - * - * perf_session__delete(session); - */ + show_annotations = dlsym(perf_gtk_handle, + "perf_gtk__show_annotations"); + if (show_annotations == NULL) { + ui__error("GTK browser not found!\n"); + goto out; + } + show_annotations(); + } + +out: return ret; } @@ -276,13 +284,17 @@ .tool = { .sample = process_sample_event, .mmap = perf_event__process_mmap, + .mmap2 = perf_event__process_mmap2, .comm = perf_event__process_comm, .exit = perf_event__process_exit, .fork = perf_event__process_fork, - .ordered_samples = true, + .ordered_events = true, .ordering_requires_timestamps = true, }, }; + struct perf_data_file file = { + .mode = PERF_DATA_MODE_READ, + }; const struct option options[] = { OPT_STRING('i', "input", &input_name, "file", "input file name"), @@ -290,7 +302,7 @@ "only consider symbols in these dsos"), OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol", "symbol to annotate"), - OPT_BOOLEAN('f', "force", &annotate.force, "don't complain, do it"), + OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, @@ -321,8 +333,14 @@ "objdump binary to use for disassembly and annotations"), OPT_BOOLEAN(0, "group", &symbol_conf.event_group, "Show event group information together"), + OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, + "Show a column with the sum of periods"), OPT_END() }; + int ret = hists__init(); + + if (ret < 0) + return ret; argc = parse_options(argc, argv, options, annotate_usage, 0); @@ -333,20 +351,27 @@ else if (annotate.use_gtk) use_browser = 2; + file.path = input_name; + setup_browser(true); + annotate.session = perf_session__new(&file, false, &annotate.tool); + if (annotate.session == NULL) + return -1; + symbol_conf.priv_size = sizeof(struct annotation); symbol_conf.try_vmlinux_path = true; - if (symbol__init() < 0) - return -1; + ret = symbol__init(&annotate.session->header.env); + if (ret < 0) + goto out_delete; if (setup_sorting() < 0) usage_with_options(annotate_usage, options); if (argc) { /* - * Special case: if there's an argument left then assume tha + * Special case: if there's an argument left then assume that * it's a symbol filter: */ if (argc > 1) @@ -355,5 +380,20 @@ annotate.sym_hist_filter = argv[0]; } - return __cmd_annotate(&annotate); + ret = __cmd_annotate(&annotate); + +out_delete: + /* + * Speed up the exit process, for large files this can + * take quite a while. + * + * XXX Enable this when using valgrind or if we ever + * librarize this command. + * + * Also experiment with obstacks to see how much speed + * up we'll get here. + * + * perf_session__delete(session); + */ + return ret; }