aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-10-19 15:17:57 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-20 01:55:51 -0400
commited52ce2e3c33dc7626a40fa2da766d1a6460e543 (patch)
tree037f7791b8f493b1adc27d9f9692922ed886844e
parentbbe2987bea26a684ff11d887dfc4cf39b22c27a2 (diff)
perf tools: Add ->unmap_ip operation to struct map
We need this because we get section relative addresses when reading the symtabs, but when a tool like 'perf annotate' needs to match these address to what 'objdump -dS' produces we need the address + section back again. So in annotate now we look at the 'struct hist_entry' instances (that weren't really being used) so that we iterate only over the symbols that had some hit and get the map where that particular hit happened so that we can get the right address to match with annotate. Verified that at least: perf annotate mmap_read_counter # Uses the ~/bin/perf binary perf annotate --vmlinux /home/acme/git/build/perf/vmlinux intel_pmu_enable_all on a 'perf record perf top' session seems to work. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Mike Galbraith <efault@gmx.de> LKML-Reference: <1255979877-12533-1-git-send-email-acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-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! "