.. | .. |
---|
8 | 8 | */ |
---|
9 | 9 | #include "builtin.h" |
---|
10 | 10 | |
---|
11 | | -#include "util/util.h" |
---|
12 | 11 | #include "util/color.h" |
---|
13 | 12 | #include <linux/list.h> |
---|
14 | 13 | #include "util/cache.h" |
---|
15 | 14 | #include <linux/rbtree.h> |
---|
| 15 | +#include <linux/zalloc.h> |
---|
16 | 16 | #include "util/symbol.h" |
---|
17 | 17 | |
---|
18 | 18 | #include "perf.h" |
---|
.. | .. |
---|
24 | 24 | #include "util/event.h" |
---|
25 | 25 | #include <subcmd/parse-options.h> |
---|
26 | 26 | #include "util/parse-events.h" |
---|
27 | | -#include "util/thread.h" |
---|
28 | 27 | #include "util/sort.h" |
---|
29 | 28 | #include "util/hist.h" |
---|
| 29 | +#include "util/dso.h" |
---|
| 30 | +#include "util/machine.h" |
---|
| 31 | +#include "util/map.h" |
---|
30 | 32 | #include "util/session.h" |
---|
31 | 33 | #include "util/tool.h" |
---|
32 | 34 | #include "util/data.h" |
---|
33 | 35 | #include "arch/common.h" |
---|
34 | 36 | #include "util/block-range.h" |
---|
| 37 | +#include "util/map_symbol.h" |
---|
| 38 | +#include "util/branch.h" |
---|
35 | 39 | |
---|
36 | 40 | #include <dlfcn.h> |
---|
37 | 41 | #include <errno.h> |
---|
38 | 42 | #include <linux/bitmap.h> |
---|
| 43 | +#include <linux/err.h> |
---|
39 | 44 | |
---|
40 | 45 | struct perf_annotate { |
---|
41 | 46 | struct perf_tool tool; |
---|
.. | .. |
---|
78 | 83 | struct addr_map_symbol *end, |
---|
79 | 84 | struct branch_flags *flags) |
---|
80 | 85 | { |
---|
81 | | - struct symbol *sym = start->sym; |
---|
| 86 | + struct symbol *sym = start->ms.sym; |
---|
82 | 87 | struct annotation *notes = sym ? symbol__annotation(sym) : NULL; |
---|
83 | 88 | struct block_range_iter iter; |
---|
84 | 89 | struct block_range *entry; |
---|
.. | .. |
---|
155 | 160 | struct hist_entry *he = iter->he; |
---|
156 | 161 | struct branch_info *bi; |
---|
157 | 162 | struct perf_sample *sample = iter->sample; |
---|
158 | | - struct perf_evsel *evsel = iter->evsel; |
---|
| 163 | + struct evsel *evsel = iter->evsel; |
---|
159 | 164 | int err; |
---|
160 | | - |
---|
161 | | - hist__account_cycles(sample->branch_stack, al, sample, false); |
---|
162 | 165 | |
---|
163 | 166 | bi = he->branch_info; |
---|
164 | 167 | err = addr_map_symbol__inc_samples(&bi->from, sample, evsel); |
---|
.. | .. |
---|
172 | 175 | return err; |
---|
173 | 176 | } |
---|
174 | 177 | |
---|
175 | | -static int process_branch_callback(struct perf_evsel *evsel, |
---|
| 178 | +static int process_branch_callback(struct evsel *evsel, |
---|
176 | 179 | struct perf_sample *sample, |
---|
177 | 180 | struct addr_location *al __maybe_unused, |
---|
178 | 181 | struct perf_annotate *ann, |
---|
.. | .. |
---|
198 | 201 | if (a.map != NULL) |
---|
199 | 202 | a.map->dso->hit = 1; |
---|
200 | 203 | |
---|
| 204 | + hist__account_cycles(sample->branch_stack, al, sample, false, NULL); |
---|
| 205 | + |
---|
201 | 206 | ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann); |
---|
202 | 207 | return ret; |
---|
203 | 208 | } |
---|
.. | .. |
---|
207 | 212 | return ui__has_annotation() || ann->use_stdio2; |
---|
208 | 213 | } |
---|
209 | 214 | |
---|
210 | | -static int perf_evsel__add_sample(struct perf_evsel *evsel, |
---|
211 | | - struct perf_sample *sample, |
---|
212 | | - struct addr_location *al, |
---|
213 | | - struct perf_annotate *ann, |
---|
214 | | - struct machine *machine) |
---|
| 215 | +static int evsel__add_sample(struct evsel *evsel, struct perf_sample *sample, |
---|
| 216 | + struct addr_location *al, struct perf_annotate *ann, |
---|
| 217 | + struct machine *machine) |
---|
215 | 218 | { |
---|
216 | 219 | struct hists *hists = evsel__hists(evsel); |
---|
217 | 220 | struct hist_entry *he; |
---|
.. | .. |
---|
227 | 230 | * the DSO? |
---|
228 | 231 | */ |
---|
229 | 232 | if (al->sym != NULL) { |
---|
230 | | - rb_erase(&al->sym->rb_node, |
---|
| 233 | + rb_erase_cached(&al->sym->rb_node, |
---|
231 | 234 | &al->map->dso->symbols); |
---|
232 | 235 | symbol__delete(al->sym); |
---|
233 | 236 | dso__reset_find_symbol_cache(al->map->dso); |
---|
.. | .. |
---|
256 | 259 | static int process_sample_event(struct perf_tool *tool, |
---|
257 | 260 | union perf_event *event, |
---|
258 | 261 | struct perf_sample *sample, |
---|
259 | | - struct perf_evsel *evsel, |
---|
| 262 | + struct evsel *evsel, |
---|
260 | 263 | struct machine *machine) |
---|
261 | 264 | { |
---|
262 | 265 | struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool); |
---|
.. | .. |
---|
273 | 276 | goto out_put; |
---|
274 | 277 | |
---|
275 | 278 | if (!al.filtered && |
---|
276 | | - perf_evsel__add_sample(evsel, sample, &al, ann, machine)) { |
---|
| 279 | + evsel__add_sample(evsel, sample, &al, ann, machine)) { |
---|
277 | 280 | pr_warning("problem incrementing symbol count, " |
---|
278 | 281 | "skipping event\n"); |
---|
279 | 282 | ret = -1; |
---|
.. | .. |
---|
283 | 286 | return ret; |
---|
284 | 287 | } |
---|
285 | 288 | |
---|
286 | | -static int process_feature_event(struct perf_tool *tool, |
---|
287 | | - union perf_event *event, |
---|
288 | | - struct perf_session *session) |
---|
| 289 | +static int process_feature_event(struct perf_session *session, |
---|
| 290 | + union perf_event *event) |
---|
289 | 291 | { |
---|
290 | 292 | if (event->feat.feat_id < HEADER_LAST_FEATURE) |
---|
291 | | - return perf_event__process_feature(tool, event, session); |
---|
| 293 | + return perf_event__process_feature(session, event); |
---|
292 | 294 | return 0; |
---|
293 | 295 | } |
---|
294 | 296 | |
---|
295 | 297 | static int hist_entry__tty_annotate(struct hist_entry *he, |
---|
296 | | - struct perf_evsel *evsel, |
---|
| 298 | + struct evsel *evsel, |
---|
297 | 299 | struct perf_annotate *ann) |
---|
298 | 300 | { |
---|
299 | 301 | if (!ann->use_stdio2) |
---|
300 | | - return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel, &ann->opts); |
---|
| 302 | + return symbol__tty_annotate(&he->ms, evsel, &ann->opts); |
---|
301 | 303 | |
---|
302 | | - return symbol__tty_annotate2(he->ms.sym, he->ms.map, evsel, &ann->opts); |
---|
| 304 | + return symbol__tty_annotate2(&he->ms, evsel, &ann->opts); |
---|
303 | 305 | } |
---|
304 | 306 | |
---|
305 | 307 | static void hists__find_annotations(struct hists *hists, |
---|
306 | | - struct perf_evsel *evsel, |
---|
| 308 | + struct evsel *evsel, |
---|
307 | 309 | struct perf_annotate *ann) |
---|
308 | 310 | { |
---|
309 | | - struct rb_node *nd = rb_first(&hists->entries), *next; |
---|
| 311 | + struct rb_node *nd = rb_first_cached(&hists->entries), *next; |
---|
310 | 312 | int key = K_RIGHT; |
---|
311 | 313 | |
---|
312 | 314 | while (nd) { |
---|
.. | .. |
---|
333 | 335 | if (use_browser == 2) { |
---|
334 | 336 | int ret; |
---|
335 | 337 | int (*annotate)(struct hist_entry *he, |
---|
336 | | - struct perf_evsel *evsel, |
---|
| 338 | + struct evsel *evsel, |
---|
337 | 339 | struct hist_browser_timer *hbt); |
---|
338 | 340 | |
---|
339 | 341 | annotate = dlsym(perf_gtk_handle, |
---|
.. | .. |
---|
387 | 389 | { |
---|
388 | 390 | int ret; |
---|
389 | 391 | struct perf_session *session = ann->session; |
---|
390 | | - struct perf_evsel *pos; |
---|
| 392 | + struct evsel *pos; |
---|
391 | 393 | u64 total_nr_samples; |
---|
392 | 394 | |
---|
393 | 395 | if (ann->cpu_list) { |
---|
.. | .. |
---|
429 | 431 | total_nr_samples += nr_samples; |
---|
430 | 432 | hists__collapse_resort(hists, NULL); |
---|
431 | 433 | /* Don't sort callchain */ |
---|
432 | | - perf_evsel__reset_sample_bit(pos, CALLCHAIN); |
---|
433 | | - perf_evsel__output_resort(pos, NULL); |
---|
| 434 | + evsel__reset_sample_bit(pos, CALLCHAIN); |
---|
| 435 | + evsel__output_resort(pos, NULL); |
---|
434 | 436 | |
---|
435 | | - if (symbol_conf.event_group && |
---|
436 | | - !perf_evsel__is_group_leader(pos)) |
---|
| 437 | + if (symbol_conf.event_group && !evsel__is_group_leader(pos)) |
---|
437 | 438 | continue; |
---|
438 | 439 | |
---|
439 | 440 | hists__find_annotations(hists, pos, ann); |
---|
.. | .. |
---|
441 | 442 | } |
---|
442 | 443 | |
---|
443 | 444 | if (total_nr_samples == 0) { |
---|
444 | | - ui__error("The %s file has no samples!\n", session->data->file.path); |
---|
| 445 | + ui__error("The %s data has no samples!\n", session->data->path); |
---|
445 | 446 | goto out; |
---|
446 | 447 | } |
---|
447 | 448 | |
---|
.. | .. |
---|
531 | 532 | "Display raw encoding of assembly instructions (default)"), |
---|
532 | 533 | OPT_STRING('M', "disassembler-style", &annotate.opts.disassembler_style, "disassembler style", |
---|
533 | 534 | "Specify disassembler style (e.g. -M intel for intel syntax)"), |
---|
| 535 | + OPT_STRING(0, "prefix", &annotate.opts.prefix, "prefix", |
---|
| 536 | + "Add prefix to source file path names in programs (with --prefix-strip)"), |
---|
| 537 | + OPT_STRING(0, "prefix-strip", &annotate.opts.prefix_strip, "N", |
---|
| 538 | + "Strip first N entries of source file path name in programs (with --prefix)"), |
---|
534 | 539 | OPT_STRING(0, "objdump", &annotate.opts.objdump_path, "path", |
---|
535 | 540 | "objdump binary to use for disassembly and annotations"), |
---|
536 | 541 | OPT_BOOLEAN(0, "group", &symbol_conf.event_group, |
---|
.. | .. |
---|
558 | 563 | if (ret < 0) |
---|
559 | 564 | return ret; |
---|
560 | 565 | |
---|
| 566 | + annotation_config__init(&annotate.opts); |
---|
| 567 | + |
---|
561 | 568 | argc = parse_options(argc, argv, options, annotate_usage, 0); |
---|
562 | 569 | if (argc) { |
---|
563 | 570 | /* |
---|
.. | .. |
---|
570 | 577 | annotate.sym_hist_filter = argv[0]; |
---|
571 | 578 | } |
---|
572 | 579 | |
---|
| 580 | + if (annotate_check_args(&annotate.opts) < 0) |
---|
| 581 | + return -EINVAL; |
---|
| 582 | + |
---|
573 | 583 | if (symbol_conf.show_nr_samples && annotate.use_gtk) { |
---|
574 | 584 | pr_err("--show-nr-samples is not available in --gtk mode at this time\n"); |
---|
575 | 585 | return ret; |
---|
.. | .. |
---|
578 | 588 | if (quiet) |
---|
579 | 589 | perf_quiet_option(); |
---|
580 | 590 | |
---|
581 | | - data.file.path = input_name; |
---|
| 591 | + data.path = input_name; |
---|
582 | 592 | |
---|
583 | 593 | annotate.session = perf_session__new(&data, false, &annotate.tool); |
---|
584 | | - if (annotate.session == NULL) |
---|
585 | | - return -1; |
---|
| 594 | + if (IS_ERR(annotate.session)) |
---|
| 595 | + return PTR_ERR(annotate.session); |
---|
586 | 596 | |
---|
587 | 597 | annotate.has_br_stack = perf_header__has_feat(&annotate.session->header, |
---|
588 | 598 | HEADER_BRANCH_STACK); |
---|
.. | .. |
---|
593 | 603 | ret = symbol__annotation_init(); |
---|
594 | 604 | if (ret < 0) |
---|
595 | 605 | goto out_delete; |
---|
596 | | - |
---|
597 | | - annotation_config__init(); |
---|
598 | 606 | |
---|
599 | 607 | symbol_conf.try_vmlinux_path = true; |
---|
600 | 608 | |
---|