diff options
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/builtin-annotate.c | 62 | ||||
-rw-r--r-- | tools/perf/util/event.h | 8 | ||||
-rw-r--r-- | tools/perf/util/map.c | 6 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 8 |
4 files changed, 58 insertions, 26 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 56ba71658d70..06f10278b28e 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -58,9 +58,12 @@ static void hist_hit(struct hist_entry *he, u64 ip) | |||
58 | return; | 58 | return; |
59 | 59 | ||
60 | sym_size = sym->end - sym->start; | 60 | sym_size = sym->end - sym->start; |
61 | ip = he->map->map_ip(he->map, ip); | ||
62 | offset = ip - sym->start; | 61 | offset = ip - sym->start; |
63 | 62 | ||
63 | if (verbose) | ||
64 | fprintf(stderr, "%s: ip=%Lx\n", __func__, | ||
65 | he->map->unmap_ip(he->map, ip)); | ||
66 | |||
64 | if (offset >= sym_size) | 67 | if (offset >= sym_size) |
65 | return; | 68 | return; |
66 | 69 | ||
@@ -83,8 +86,7 @@ static int hist_entry__add(struct thread *thread, struct map *map, | |||
83 | count, level, &hit); | 86 | count, level, &hit); |
84 | if (he == NULL) | 87 | if (he == NULL) |
85 | return -ENOMEM; | 88 | return -ENOMEM; |
86 | if (hit) | 89 | hist_hit(he, ip); |
87 | hist_hit(he, ip); | ||
88 | return 0; | 90 | return 0; |
89 | } | 91 | } |
90 | 92 | ||
@@ -260,14 +262,15 @@ process_event(event_t *event, unsigned long offset, unsigned long head) | |||
260 | return 0; | 262 | return 0; |
261 | } | 263 | } |
262 | 264 | ||
263 | static int | 265 | static int parse_line(FILE *file, struct hist_entry *he, u64 len) |
264 | parse_line(FILE *file, struct symbol *sym, u64 len) | ||
265 | { | 266 | { |
267 | struct symbol *sym = he->sym; | ||
266 | char *line = NULL, *tmp, *tmp2; | 268 | char *line = NULL, *tmp, *tmp2; |
267 | static const char *prev_line; | 269 | static const char *prev_line; |
268 | static const char *prev_color; | 270 | static const char *prev_color; |
269 | unsigned int offset; | 271 | unsigned int offset; |
270 | size_t line_len; | 272 | size_t line_len; |
273 | u64 start; | ||
271 | s64 line_ip; | 274 | s64 line_ip; |
272 | int ret; | 275 | int ret; |
273 | char *c; | 276 | char *c; |
@@ -304,6 +307,8 @@ parse_line(FILE *file, struct symbol *sym, u64 len) | |||
304 | line_ip = -1; | 307 | line_ip = -1; |
305 | } | 308 | } |
306 | 309 | ||
310 | start = he->map->unmap_ip(he->map, sym->start); | ||
311 | |||
307 | if (line_ip != -1) { | 312 | if (line_ip != -1) { |
308 | const char *path = NULL; | 313 | const char *path = NULL; |
309 | unsigned int hits = 0; | 314 | unsigned int hits = 0; |
@@ -311,7 +316,7 @@ parse_line(FILE *file, struct symbol *sym, u64 len) | |||
311 | const char *color; | 316 | const char *color; |
312 | struct sym_ext *sym_ext = sym->priv; | 317 | struct sym_ext *sym_ext = sym->priv; |
313 | 318 | ||
314 | offset = line_ip - sym->start; | 319 | offset = line_ip - start; |
315 | if (offset < len) | 320 | if (offset < len) |
316 | hits = sym->hist[offset]; | 321 | hits = sym->hist[offset]; |
317 | 322 | ||
@@ -390,8 +395,10 @@ static void free_source_line(struct symbol *sym, int len) | |||
390 | 395 | ||
391 | /* Get the filename:line for the colored entries */ | 396 | /* Get the filename:line for the colored entries */ |
392 | static void | 397 | static void |
393 | get_source_line(struct symbol *sym, int len, const char *filename) | 398 | get_source_line(struct hist_entry *he, int len, const char *filename) |
394 | { | 399 | { |
400 | struct symbol *sym = he->sym; | ||
401 | u64 start; | ||
395 | int i; | 402 | int i; |
396 | char cmd[PATH_MAX * 2]; | 403 | char cmd[PATH_MAX * 2]; |
397 | struct sym_ext *sym_ext; | 404 | struct sym_ext *sym_ext; |
@@ -404,6 +411,7 @@ get_source_line(struct symbol *sym, int len, const char *filename) | |||
404 | return; | 411 | return; |
405 | 412 | ||
406 | sym_ext = sym->priv; | 413 | sym_ext = sym->priv; |
414 | start = he->map->unmap_ip(he->map, sym->start); | ||
407 | 415 | ||
408 | for (i = 0; i < len; i++) { | 416 | for (i = 0; i < len; i++) { |
409 | char *path = NULL; | 417 | char *path = NULL; |
@@ -415,7 +423,7 @@ get_source_line(struct symbol *sym, int len, const char *filename) | |||
415 | if (sym_ext[i].percent <= 0.5) | 423 | if (sym_ext[i].percent <= 0.5) |
416 | continue; | 424 | continue; |
417 | 425 | ||
418 | offset = sym->start + i; | 426 | offset = start + i; |
419 | sprintf(cmd, "addr2line -e %s %016llx", filename, offset); | 427 | sprintf(cmd, "addr2line -e %s %016llx", filename, offset); |
420 | fp = popen(cmd, "r"); | 428 | fp = popen(cmd, "r"); |
421 | if (!fp) | 429 | if (!fp) |
@@ -465,8 +473,11 @@ static void print_summary(const char *filename) | |||
465 | } | 473 | } |
466 | } | 474 | } |
467 | 475 | ||
468 | static void annotate_sym(struct dso *dso, struct symbol *sym) | 476 | static void annotate_sym(struct hist_entry *he) |
469 | { | 477 | { |
478 | struct map *map = he->map; | ||
479 | struct dso *dso = map->dso; | ||
480 | struct symbol *sym = he->sym; | ||
470 | const char *filename = dso->long_name, *d_filename; | 481 | const char *filename = dso->long_name, *d_filename; |
471 | u64 len; | 482 | u64 len; |
472 | char command[PATH_MAX*2]; | 483 | char command[PATH_MAX*2]; |
@@ -475,6 +486,12 @@ static void annotate_sym(struct dso *dso, struct symbol *sym) | |||
475 | if (!filename) | 486 | if (!filename) |
476 | return; | 487 | return; |
477 | 488 | ||
489 | if (verbose) | ||
490 | fprintf(stderr, "%s: filename=%s, sym=%s, start=%Lx, end=%Lx\n", | ||
491 | __func__, filename, sym->name, | ||
492 | map->unmap_ip(map, sym->start), | ||
493 | map->unmap_ip(map, sym->end)); | ||
494 | |||
478 | if (full_paths) | 495 | if (full_paths) |
479 | d_filename = filename; | 496 | d_filename = filename; |
480 | else | 497 | else |
@@ -483,7 +500,7 @@ static void annotate_sym(struct dso *dso, struct symbol *sym) | |||
483 | len = sym->end - sym->start; | 500 | len = sym->end - sym->start; |
484 | 501 | ||
485 | if (print_line) { | 502 | if (print_line) { |
486 | get_source_line(sym, len, filename); | 503 | get_source_line(he, len, filename); |
487 | print_summary(filename); | 504 | print_summary(filename); |
488 | } | 505 | } |
489 | 506 | ||
@@ -496,7 +513,8 @@ static void annotate_sym(struct dso *dso, struct symbol *sym) | |||
496 | dso, dso->long_name, sym, sym->name); | 513 | dso, dso->long_name, sym, sym->name); |
497 | 514 | ||
498 | sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", | 515 | sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", |
499 | sym->start, sym->end, filename, filename); | 516 | map->unmap_ip(map, sym->start), map->unmap_ip(map, sym->end), |
517 | filename, filename); | ||
500 | 518 | ||
501 | if (verbose >= 3) | 519 | if (verbose >= 3) |
502 | printf("doing: %s\n", command); | 520 | printf("doing: %s\n", command); |
@@ -506,7 +524,7 @@ static void annotate_sym(struct dso *dso, struct symbol *sym) | |||
506 | return; | 524 | return; |
507 | 525 | ||
508 | while (!feof(file)) { | 526 | while (!feof(file)) { |
509 | if (parse_line(file, sym, len) < 0) | 527 | if (parse_line(file, he, len) < 0) |
510 | break; | 528 | break; |
511 | } | 529 | } |
512 | 530 | ||
@@ -518,18 +536,22 @@ static void annotate_sym(struct dso *dso, struct symbol *sym) | |||
518 | static void find_annotations(void) | 536 | static void find_annotations(void) |
519 | { | 537 | { |
520 | struct rb_node *nd; | 538 | struct rb_node *nd; |
521 | struct dso *dso; | ||
522 | int count = 0; | 539 | int count = 0; |
523 | 540 | ||
524 | list_for_each_entry(dso, &dsos, node) { | 541 | for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) { |
542 | struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); | ||
525 | 543 | ||
526 | for (nd = rb_first(&dso->syms); nd; nd = rb_next(nd)) { | 544 | if (he->sym && he->sym->hist) { |
527 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); | 545 | annotate_sym(he); |
546 | count++; | ||
547 | /* | ||
548 | * Since we have a hist_entry per IP for the same | ||
549 | * symbol, free he->sym->hist to signal we already | ||
550 | * processed this symbol. | ||
551 | */ | ||
552 | free(he->sym->hist); | ||
553 | he->sym->hist = NULL; | ||
528 | 554 | ||
529 | if (sym->hist) { | ||
530 | annotate_sym(dso, sym); | ||
531 | count++; | ||
532 | } | ||
533 | } | 555 | } |
534 | } | 556 | } |
535 | 557 | ||
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index c2e62be62798..6b5be56a8271 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -82,6 +82,7 @@ struct map { | |||
82 | u64 end; | 82 | u64 end; |
83 | u64 pgoff; | 83 | u64 pgoff; |
84 | u64 (*map_ip)(struct map *, u64); | 84 | u64 (*map_ip)(struct map *, u64); |
85 | u64 (*unmap_ip)(struct map *, u64); | ||
85 | struct dso *dso; | 86 | struct dso *dso; |
86 | }; | 87 | }; |
87 | 88 | ||
@@ -90,7 +91,12 @@ static inline u64 map__map_ip(struct map *map, u64 ip) | |||
90 | return ip - map->start + map->pgoff; | 91 | return ip - map->start + map->pgoff; |
91 | } | 92 | } |
92 | 93 | ||
93 | static inline u64 vdso__map_ip(struct map *map __used, u64 ip) | 94 | static inline u64 map__unmap_ip(struct map *map, u64 ip) |
95 | { | ||
96 | return ip + map->start - map->pgoff; | ||
97 | } | ||
98 | |||
99 | static inline u64 identity__map_ip(struct map *map __used, u64 ip) | ||
94 | { | 100 | { |
95 | return ip; | 101 | return ip; |
96 | } | 102 | } |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 804e02382739..4e203d144f9e 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -54,9 +54,11 @@ static int strcommon(const char *pathname, char *cwd, int cwdlen) | |||
54 | goto out_delete; | 54 | goto out_delete; |
55 | 55 | ||
56 | if (self->dso == vdso || anon) | 56 | if (self->dso == vdso || anon) |
57 | self->map_ip = vdso__map_ip; | 57 | self->map_ip = self->unmap_ip = identity__map_ip; |
58 | else | 58 | else { |
59 | self->map_ip = map__map_ip; | 59 | self->map_ip = map__map_ip; |
60 | self->unmap_ip = map__unmap_ip; | ||
61 | } | ||
60 | } | 62 | } |
61 | return self; | 63 | return self; |
62 | out_delete: | 64 | out_delete: |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index faa84f5d4f54..3350119f6909 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -337,7 +337,7 @@ static int kernel_maps__split_kallsyms(symbol_filter_t filter, int use_modules) | |||
337 | return -1; | 337 | return -1; |
338 | } | 338 | } |
339 | 339 | ||
340 | map->map_ip = vdso__map_ip; | 340 | map->map_ip = map->unmap_ip = identity__map_ip; |
341 | kernel_maps__insert(map); | 341 | kernel_maps__insert(map); |
342 | ++kernel_range; | 342 | ++kernel_range; |
343 | } | 343 | } |
@@ -790,7 +790,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
790 | dso__delete(curr_dso); | 790 | dso__delete(curr_dso); |
791 | goto out_elf_end; | 791 | goto out_elf_end; |
792 | } | 792 | } |
793 | curr_map->map_ip = vdso__map_ip; | 793 | curr_map->map_ip = identity__map_ip; |
794 | curr_map->unmap_ip = identity__map_ip; | ||
794 | curr_dso->origin = DSO__ORIG_KERNEL; | 795 | curr_dso->origin = DSO__ORIG_KERNEL; |
795 | kernel_maps__insert(curr_map); | 796 | kernel_maps__insert(curr_map); |
796 | dsos__add(curr_dso); | 797 | dsos__add(curr_dso); |
@@ -1158,6 +1159,7 @@ static struct map *map__new2(u64 start, struct dso *dso) | |||
1158 | self->pgoff = 0; | 1159 | self->pgoff = 0; |
1159 | self->dso = dso; | 1160 | self->dso = dso; |
1160 | self->map_ip = map__map_ip; | 1161 | self->map_ip = map__map_ip; |
1162 | self->unmap_ip = map__unmap_ip; | ||
1161 | RB_CLEAR_NODE(&self->rb_node); | 1163 | RB_CLEAR_NODE(&self->rb_node); |
1162 | } | 1164 | } |
1163 | return self; | 1165 | return self; |
@@ -1259,7 +1261,7 @@ int dsos__load_kernel(const char *vmlinux, unsigned int sym_priv_size, | |||
1259 | if (kernel_map == NULL) | 1261 | if (kernel_map == NULL) |
1260 | goto out_delete_dso; | 1262 | goto out_delete_dso; |
1261 | 1263 | ||
1262 | kernel_map->map_ip = vdso__map_ip; | 1264 | kernel_map->map_ip = kernel_map->unmap_ip = identity__map_ip; |
1263 | 1265 | ||
1264 | if (use_modules && dsos__load_modules(sym_priv_size) < 0) { | 1266 | if (use_modules && dsos__load_modules(sym_priv_size) < 0) { |
1265 | fprintf(stderr, "Failed to load list of modules in use! " | 1267 | fprintf(stderr, "Failed to load list of modules in use! " |