aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-annotate.c62
-rw-r--r--tools/perf/util/event.h8
-rw-r--r--tools/perf/util/map.c6
-rw-r--r--tools/perf/util/symbol.c8
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
263static int 265static int parse_line(FILE *file, struct hist_entry *he, u64 len)
264parse_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 */
392static void 397static void
393get_source_line(struct symbol *sym, int len, const char *filename) 398get_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
468static void annotate_sym(struct dso *dso, struct symbol *sym) 476static 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)
518static void find_annotations(void) 536static 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
93static inline u64 vdso__map_ip(struct map *map __used, u64 ip) 94static inline u64 map__unmap_ip(struct map *map, u64 ip)
95{
96 return ip + map->start - map->pgoff;
97}
98
99static 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;
62out_delete: 64out_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! "