diff options
Diffstat (limited to 'tools/perf/builtin-annotate.c')
| -rw-r--r-- | tools/perf/builtin-annotate.c | 73 |
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 | ||
| 82 | static int | 83 | static int |
| 83 | hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, | 84 | hist_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) { |
| 166 | got_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 | ||
| 315 | static int | 313 | static int |
| 316 | parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) | 314 | parse_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 */ |
| 444 | static void | 442 | static void |
| 445 | get_source_line(struct symbol *sym, u64 start, int len, const char *filename) | 443 | get_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 | ||
| 520 | static void annotate_sym(struct dso *dso, struct symbol *sym) | 518 | static 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 | ||
