aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-annotate.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r--tools/perf/builtin-annotate.c73
1 files changed, 32 insertions, 41 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index df516dce9540..7d5a3b1bcda9 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -63,6 +63,7 @@ static void hist_hit(struct hist_entry *he, u64 ip)
63 return; 63 return;
64 64
65 sym_size = sym->end - sym->start; 65 sym_size = sym->end - sym->start;
66 ip = he->map->map_ip(he->map, ip);
66 offset = ip - sym->start; 67 offset = ip - sym->start;
67 68
68 if (offset >= sym_size) 69 if (offset >= sym_size)
@@ -80,7 +81,7 @@ static void hist_hit(struct hist_entry *he, u64 ip)
80} 81}
81 82
82static int 83static int
83hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 84hist_entry__add(struct thread *thread, struct map *map,
84 struct symbol *sym, u64 ip, char level) 85 struct symbol *sym, u64 ip, char level)
85{ 86{
86 struct rb_node **p = &hist.rb_node; 87 struct rb_node **p = &hist.rb_node;
@@ -89,7 +90,6 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
89 struct hist_entry entry = { 90 struct hist_entry entry = {
90 .thread = thread, 91 .thread = thread,
91 .map = map, 92 .map = map,
92 .dso = dso,
93 .sym = sym, 93 .sym = sym,
94 .ip = ip, 94 .ip = ip,
95 .level = level, 95 .level = level,
@@ -130,10 +130,10 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
130{ 130{
131 char level; 131 char level;
132 int show = 0; 132 int show = 0;
133 struct dso *dso = NULL;
134 struct thread *thread; 133 struct thread *thread;
135 u64 ip = event->ip.ip; 134 u64 ip = event->ip.ip;
136 struct map *map = NULL; 135 struct map *map = NULL;
136 struct symbol *sym = NULL;
137 137
138 thread = threads__findnew(event->ip.pid, &threads, &last_match); 138 thread = threads__findnew(event->ip.pid, &threads, &last_match);
139 139
@@ -155,32 +155,35 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
155 if (event->header.misc & PERF_RECORD_MISC_KERNEL) { 155 if (event->header.misc & PERF_RECORD_MISC_KERNEL) {
156 show = SHOW_KERNEL; 156 show = SHOW_KERNEL;
157 level = 'k'; 157 level = 'k';
158 158 sym = kernel_maps__find_symbol(ip, &map);
159 dso = kernel_dso; 159 dump_printf(" ...... dso: %s\n",
160 160 map ? map->dso->long_name : "<not found>");
161 dump_printf(" ...... dso: %s\n", dso->name);
162
163 } else if (event->header.misc & PERF_RECORD_MISC_USER) { 161 } else if (event->header.misc & PERF_RECORD_MISC_USER) {
164
165 show = SHOW_USER; 162 show = SHOW_USER;
166 level = '.'; 163 level = '.';
167
168 map = thread__find_map(thread, ip); 164 map = thread__find_map(thread, ip);
169 if (map != NULL) { 165 if (map != NULL) {
166got_map:
170 ip = map->map_ip(map, ip); 167 ip = map->map_ip(map, ip);
171 dso = map->dso; 168 sym = map->dso->find_symbol(map->dso, ip);
172 } else { 169 } else {
173 /* 170 /*
174 * If this is outside of all known maps, 171 * If this is outside of all known maps,
175 * and is a negative address, try to look it 172 * and is a negative address, try to look it
176 * up in the kernel dso, as it might be a 173 * up in the kernel dso, as it might be a
177 * vsyscall (which executes in user-mode): 174 * vsyscall or vdso (which executes in user-mode).
175 *
176 * XXX This is nasty, we should have a symbol list in
177 * the "[vdso]" dso, but for now lets use the old
178 * trick of looking in the whole kernel symbol list.
178 */ 179 */
179 if ((long long)ip < 0) 180 if ((long long)ip < 0) {
180 dso = kernel_dso; 181 map = kernel_map;
182 goto got_map;
183 }
181 } 184 }
182 dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 185 dump_printf(" ...... dso: %s\n",
183 186 map ? map->dso->long_name : "<not found>");
184 } else { 187 } else {
185 show = SHOW_HV; 188 show = SHOW_HV;
186 level = 'H'; 189 level = 'H';
@@ -188,12 +191,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
188 } 191 }
189 192
190 if (show & show_mask) { 193 if (show & show_mask) {
191 struct symbol *sym = NULL; 194 if (hist_entry__add(thread, map, sym, ip, level)) {
192
193 if (dso)
194 sym = dso->find_symbol(dso, ip);
195
196 if (hist_entry__add(thread, map, dso, sym, ip, level)) {
197 fprintf(stderr, 195 fprintf(stderr,
198 "problem incrementing symbol count, skipping event\n"); 196 "problem incrementing symbol count, skipping event\n");
199 return -1; 197 return -1;
@@ -313,7 +311,7 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
313} 311}
314 312
315static int 313static int
316parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) 314parse_line(FILE *file, struct symbol *sym, u64 len)
317{ 315{
318 char *line = NULL, *tmp, *tmp2; 316 char *line = NULL, *tmp, *tmp2;
319 static const char *prev_line; 317 static const char *prev_line;
@@ -363,7 +361,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
363 const char *color; 361 const char *color;
364 struct sym_ext *sym_ext = sym->priv; 362 struct sym_ext *sym_ext = sym->priv;
365 363
366 offset = line_ip - start; 364 offset = line_ip - sym->start;
367 if (offset < len) 365 if (offset < len)
368 hits = sym->hist[offset]; 366 hits = sym->hist[offset];
369 367
@@ -442,7 +440,7 @@ static void free_source_line(struct symbol *sym, int len)
442 440
443/* Get the filename:line for the colored entries */ 441/* Get the filename:line for the colored entries */
444static void 442static void
445get_source_line(struct symbol *sym, u64 start, int len, const char *filename) 443get_source_line(struct symbol *sym, int len, const char *filename)
446{ 444{
447 int i; 445 int i;
448 char cmd[PATH_MAX * 2]; 446 char cmd[PATH_MAX * 2];
@@ -467,7 +465,7 @@ get_source_line(struct symbol *sym, u64 start, int len, const char *filename)
467 if (sym_ext[i].percent <= 0.5) 465 if (sym_ext[i].percent <= 0.5)
468 continue; 466 continue;
469 467
470 offset = start + i; 468 offset = sym->start + i;
471 sprintf(cmd, "addr2line -e %s %016llx", filename, offset); 469 sprintf(cmd, "addr2line -e %s %016llx", filename, offset);
472 fp = popen(cmd, "r"); 470 fp = popen(cmd, "r");
473 if (!fp) 471 if (!fp)
@@ -519,31 +517,23 @@ static void print_summary(const char *filename)
519 517
520static void annotate_sym(struct dso *dso, struct symbol *sym) 518static void annotate_sym(struct dso *dso, struct symbol *sym)
521{ 519{
522 const char *filename = dso->name, *d_filename; 520 const char *filename = dso->long_name, *d_filename;
523 u64 start, end, len; 521 u64 len;
524 char command[PATH_MAX*2]; 522 char command[PATH_MAX*2];
525 FILE *file; 523 FILE *file;
526 524
527 if (!filename) 525 if (!filename)
528 return; 526 return;
529 if (sym->module) 527
530 filename = sym->module->path;
531 else if (dso == kernel_dso)
532 filename = vmlinux_name;
533
534 start = sym->obj_start;
535 if (!start)
536 start = sym->start;
537 if (full_paths) 528 if (full_paths)
538 d_filename = filename; 529 d_filename = filename;
539 else 530 else
540 d_filename = basename(filename); 531 d_filename = basename(filename);
541 532
542 end = start + sym->end - sym->start + 1;
543 len = sym->end - sym->start; 533 len = sym->end - sym->start;
544 534
545 if (print_line) { 535 if (print_line) {
546 get_source_line(sym, start, len, filename); 536 get_source_line(sym, len, filename);
547 print_summary(filename); 537 print_summary(filename);
548 } 538 }
549 539
@@ -552,10 +542,11 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
552 printf("------------------------------------------------\n"); 542 printf("------------------------------------------------\n");
553 543
554 if (verbose >= 2) 544 if (verbose >= 2)
555 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 545 printf("annotating [%p] %30s : [%p] %30s\n",
546 dso, dso->long_name, sym, sym->name);
556 547
557 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", 548 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
558 (u64)start, (u64)end, filename, filename); 549 sym->start, sym->end, filename, filename);
559 550
560 if (verbose >= 3) 551 if (verbose >= 3)
561 printf("doing: %s\n", command); 552 printf("doing: %s\n", command);
@@ -565,7 +556,7 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
565 return; 556 return;
566 557
567 while (!feof(file)) { 558 while (!feof(file)) {
568 if (parse_line(file, sym, start, len) < 0) 559 if (parse_line(file, sym, len) < 0)
569 break; 560 break;
570 } 561 }
571 562