diff options
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r-- | tools/perf/builtin-annotate.c | 57 |
1 files changed, 34 insertions, 23 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 6ad7148451c5..f924b4332be6 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include "util/cache.h" | 14 | #include "util/cache.h" |
15 | #include <linux/rbtree.h> | 15 | #include <linux/rbtree.h> |
16 | #include "util/symbol.h" | 16 | #include "util/symbol.h" |
17 | #include "util/string.h" | ||
18 | 17 | ||
19 | #include "perf.h" | 18 | #include "perf.h" |
20 | #include "util/debug.h" | 19 | #include "util/debug.h" |
@@ -29,11 +28,11 @@ | |||
29 | 28 | ||
30 | static char const *input_name = "perf.data"; | 29 | static char const *input_name = "perf.data"; |
31 | 30 | ||
32 | static int force; | 31 | static bool force; |
33 | 32 | ||
34 | static int full_paths; | 33 | static bool full_paths; |
35 | 34 | ||
36 | static int print_line; | 35 | static bool print_line; |
37 | 36 | ||
38 | struct sym_hist { | 37 | struct sym_hist { |
39 | u64 sum; | 38 | u64 sum; |
@@ -69,13 +68,13 @@ static int sym__alloc_hist(struct symbol *self) | |||
69 | static int annotate__hist_hit(struct hist_entry *he, u64 ip) | 68 | static int annotate__hist_hit(struct hist_entry *he, u64 ip) |
70 | { | 69 | { |
71 | unsigned int sym_size, offset; | 70 | unsigned int sym_size, offset; |
72 | struct symbol *sym = he->sym; | 71 | struct symbol *sym = he->ms.sym; |
73 | struct sym_priv *priv; | 72 | struct sym_priv *priv; |
74 | struct sym_hist *h; | 73 | struct sym_hist *h; |
75 | 74 | ||
76 | he->count++; | 75 | he->count++; |
77 | 76 | ||
78 | if (!sym || !he->map) | 77 | if (!sym || !he->ms.map) |
79 | return 0; | 78 | return 0; |
80 | 79 | ||
81 | priv = symbol__priv(sym); | 80 | priv = symbol__priv(sym); |
@@ -85,7 +84,7 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip) | |||
85 | sym_size = sym->end - sym->start; | 84 | sym_size = sym->end - sym->start; |
86 | offset = ip - sym->start; | 85 | offset = ip - sym->start; |
87 | 86 | ||
88 | pr_debug3("%s: ip=%#Lx\n", __func__, he->map->unmap_ip(he->map, ip)); | 87 | pr_debug3("%s: ip=%#Lx\n", __func__, he->ms.map->unmap_ip(he->ms.map, ip)); |
89 | 88 | ||
90 | if (offset >= sym_size) | 89 | if (offset >= sym_size) |
91 | return 0; | 90 | return 0; |
@@ -94,8 +93,8 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip) | |||
94 | h->sum++; | 93 | h->sum++; |
95 | h->ip[offset]++; | 94 | h->ip[offset]++; |
96 | 95 | ||
97 | pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", he->sym->start, | 96 | pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", he->ms.sym->start, |
98 | he->sym->name, ip, ip - he->sym->start, h->ip[offset]); | 97 | he->ms.sym->name, ip, ip - he->ms.sym->start, h->ip[offset]); |
99 | return 0; | 98 | return 0; |
100 | } | 99 | } |
101 | 100 | ||
@@ -187,7 +186,7 @@ static struct objdump_line *objdump__get_next_ip_line(struct list_head *head, | |||
187 | static int parse_line(FILE *file, struct hist_entry *he, | 186 | static int parse_line(FILE *file, struct hist_entry *he, |
188 | struct list_head *head) | 187 | struct list_head *head) |
189 | { | 188 | { |
190 | struct symbol *sym = he->sym; | 189 | struct symbol *sym = he->ms.sym; |
191 | struct objdump_line *objdump_line; | 190 | struct objdump_line *objdump_line; |
192 | char *line = NULL, *tmp, *tmp2; | 191 | char *line = NULL, *tmp, *tmp2; |
193 | size_t line_len; | 192 | size_t line_len; |
@@ -226,7 +225,7 @@ static int parse_line(FILE *file, struct hist_entry *he, | |||
226 | } | 225 | } |
227 | 226 | ||
228 | if (line_ip != -1) { | 227 | if (line_ip != -1) { |
229 | u64 start = map__rip_2objdump(he->map, sym->start); | 228 | u64 start = map__rip_2objdump(he->ms.map, sym->start); |
230 | offset = line_ip - start; | 229 | offset = line_ip - start; |
231 | } | 230 | } |
232 | 231 | ||
@@ -244,7 +243,7 @@ static int objdump_line__print(struct objdump_line *self, | |||
244 | struct list_head *head, | 243 | struct list_head *head, |
245 | struct hist_entry *he, u64 len) | 244 | struct hist_entry *he, u64 len) |
246 | { | 245 | { |
247 | struct symbol *sym = he->sym; | 246 | struct symbol *sym = he->ms.sym; |
248 | static const char *prev_line; | 247 | static const char *prev_line; |
249 | static const char *prev_color; | 248 | static const char *prev_color; |
250 | 249 | ||
@@ -327,7 +326,7 @@ static void insert_source_line(struct sym_ext *sym_ext) | |||
327 | 326 | ||
328 | static void free_source_line(struct hist_entry *he, int len) | 327 | static void free_source_line(struct hist_entry *he, int len) |
329 | { | 328 | { |
330 | struct sym_priv *priv = symbol__priv(he->sym); | 329 | struct sym_priv *priv = symbol__priv(he->ms.sym); |
331 | struct sym_ext *sym_ext = priv->ext; | 330 | struct sym_ext *sym_ext = priv->ext; |
332 | int i; | 331 | int i; |
333 | 332 | ||
@@ -346,7 +345,7 @@ static void free_source_line(struct hist_entry *he, int len) | |||
346 | static void | 345 | static void |
347 | get_source_line(struct hist_entry *he, int len, const char *filename) | 346 | get_source_line(struct hist_entry *he, int len, const char *filename) |
348 | { | 347 | { |
349 | struct symbol *sym = he->sym; | 348 | struct symbol *sym = he->ms.sym; |
350 | u64 start; | 349 | u64 start; |
351 | int i; | 350 | int i; |
352 | char cmd[PATH_MAX * 2]; | 351 | char cmd[PATH_MAX * 2]; |
@@ -361,7 +360,7 @@ get_source_line(struct hist_entry *he, int len, const char *filename) | |||
361 | if (!priv->ext) | 360 | if (!priv->ext) |
362 | return; | 361 | return; |
363 | 362 | ||
364 | start = he->map->unmap_ip(he->map, sym->start); | 363 | start = he->ms.map->unmap_ip(he->ms.map, sym->start); |
365 | 364 | ||
366 | for (i = 0; i < len; i++) { | 365 | for (i = 0; i < len; i++) { |
367 | char *path = NULL; | 366 | char *path = NULL; |
@@ -425,7 +424,7 @@ static void print_summary(const char *filename) | |||
425 | 424 | ||
426 | static void hist_entry__print_hits(struct hist_entry *self) | 425 | static void hist_entry__print_hits(struct hist_entry *self) |
427 | { | 426 | { |
428 | struct symbol *sym = self->sym; | 427 | struct symbol *sym = self->ms.sym; |
429 | struct sym_priv *priv = symbol__priv(sym); | 428 | struct sym_priv *priv = symbol__priv(sym); |
430 | struct sym_hist *h = priv->hist; | 429 | struct sym_hist *h = priv->hist; |
431 | u64 len = sym->end - sym->start, offset; | 430 | u64 len = sym->end - sym->start, offset; |
@@ -439,9 +438,9 @@ static void hist_entry__print_hits(struct hist_entry *self) | |||
439 | 438 | ||
440 | static void annotate_sym(struct hist_entry *he) | 439 | static void annotate_sym(struct hist_entry *he) |
441 | { | 440 | { |
442 | struct map *map = he->map; | 441 | struct map *map = he->ms.map; |
443 | struct dso *dso = map->dso; | 442 | struct dso *dso = map->dso; |
444 | struct symbol *sym = he->sym; | 443 | struct symbol *sym = he->ms.sym; |
445 | const char *filename = dso->long_name, *d_filename; | 444 | const char *filename = dso->long_name, *d_filename; |
446 | u64 len; | 445 | u64 len; |
447 | char command[PATH_MAX*2]; | 446 | char command[PATH_MAX*2]; |
@@ -452,6 +451,16 @@ static void annotate_sym(struct hist_entry *he) | |||
452 | if (!filename) | 451 | if (!filename) |
453 | return; | 452 | return; |
454 | 453 | ||
454 | if (dso->origin == DSO__ORIG_KERNEL) { | ||
455 | if (dso->annotate_warned) | ||
456 | return; | ||
457 | dso->annotate_warned = 1; | ||
458 | pr_err("Can't annotate %s: No vmlinux file was found in the " | ||
459 | "path:\n", sym->name); | ||
460 | vmlinux_path__fprintf(stderr); | ||
461 | return; | ||
462 | } | ||
463 | |||
455 | pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__, | 464 | pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__, |
456 | filename, sym->name, map->unmap_ip(map, sym->start), | 465 | filename, sym->name, map->unmap_ip(map, sym->start), |
457 | map->unmap_ip(map, sym->end)); | 466 | map->unmap_ip(map, sym->end)); |
@@ -516,17 +525,17 @@ static void perf_session__find_annotations(struct perf_session *self) | |||
516 | struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); | 525 | struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); |
517 | struct sym_priv *priv; | 526 | struct sym_priv *priv; |
518 | 527 | ||
519 | if (he->sym == NULL) | 528 | if (he->ms.sym == NULL) |
520 | continue; | 529 | continue; |
521 | 530 | ||
522 | priv = symbol__priv(he->sym); | 531 | priv = symbol__priv(he->ms.sym); |
523 | if (priv->hist == NULL) | 532 | if (priv->hist == NULL) |
524 | continue; | 533 | continue; |
525 | 534 | ||
526 | annotate_sym(he); | 535 | annotate_sym(he); |
527 | /* | 536 | /* |
528 | * Since we have a hist_entry per IP for the same symbol, free | 537 | * Since we have a hist_entry per IP for the same symbol, free |
529 | * he->sym->hist to signal we already processed this symbol. | 538 | * he->ms.sym->hist to signal we already processed this symbol. |
530 | */ | 539 | */ |
531 | free(priv->hist); | 540 | free(priv->hist); |
532 | priv->hist = NULL; | 541 | priv->hist = NULL; |
@@ -562,7 +571,7 @@ static int __cmd_annotate(void) | |||
562 | perf_session__fprintf(session, stdout); | 571 | perf_session__fprintf(session, stdout); |
563 | 572 | ||
564 | if (verbose > 2) | 573 | if (verbose > 2) |
565 | dsos__fprintf(stdout); | 574 | dsos__fprintf(&session->kerninfo_root, stdout); |
566 | 575 | ||
567 | perf_session__collapse_resort(&session->hists); | 576 | perf_session__collapse_resort(&session->hists); |
568 | perf_session__output_resort(&session->hists, session->event_total[0]); | 577 | perf_session__output_resort(&session->hists, session->event_total[0]); |
@@ -581,10 +590,12 @@ static const char * const annotate_usage[] = { | |||
581 | static const struct option options[] = { | 590 | static const struct option options[] = { |
582 | OPT_STRING('i', "input", &input_name, "file", | 591 | OPT_STRING('i', "input", &input_name, "file", |
583 | "input file name"), | 592 | "input file name"), |
593 | OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", | ||
594 | "only consider symbols in these dsos"), | ||
584 | OPT_STRING('s', "symbol", &sym_hist_filter, "symbol", | 595 | OPT_STRING('s', "symbol", &sym_hist_filter, "symbol", |
585 | "symbol to annotate"), | 596 | "symbol to annotate"), |
586 | OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), | 597 | OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), |
587 | OPT_BOOLEAN('v', "verbose", &verbose, | 598 | OPT_INCR('v', "verbose", &verbose, |
588 | "be more verbose (show symbol address, etc)"), | 599 | "be more verbose (show symbol address, etc)"), |
589 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, | 600 | OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, |
590 | "dump raw trace in ASCII"), | 601 | "dump raw trace in ASCII"), |