diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-04-13 03:50:21 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-04-13 03:50:21 -0400 |
commit | 659c36fcda403013a01b85da07cf2d9711e6d6c7 (patch) | |
tree | ece2e7d0e2c19ea5a3d0ec172ad0b81a8a19021d /tools/perf/util/annotate.c | |
parent | 9521d830b6341d1887dcfc2aebde23fbfa5f1473 (diff) | |
parent | 5a7ed29c7572d00a75e8c4529e30c5ac2ef82271 (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Fixes and improvements for perf/core:
. Overhaul the tools/ makefiles, gluing them to the top level Makefile, from
Borislav Petkov.
. Move the UI files from tools/perf/util/ui/ to tools/perf/ui/. Also move
the GTK+ browser to tools/perf/ui/gtk/, from Namhyung Kim.
. Only fallback to sw cycles counter on ENOENT for the hw cycles, from
Robert Richter
. Trivial fixes from Robert Richter
. Handle the autogenerated bison/flex files better, from Namhyung and Jiri Olsa.
. Navigate jump instructions in the annotate browser, just press enter or ->,
still needs support for a jump navigation history, i.e. to go back.
. Search string in the annotate browser: same keys as vim:
/ forward
n next backward/forward
? backward
. Clarify number of events/samples in the report header, from Ashay Rane
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/util/annotate.c')
-rw-r--r-- | tools/perf/util/annotate.c | 55 |
1 files changed, 32 insertions, 23 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index e5a462f1d07c..1e7fd52bd29d 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
@@ -28,8 +28,8 @@ int symbol__annotate_init(struct map *map __used, struct symbol *sym) | |||
28 | int symbol__alloc_hist(struct symbol *sym) | 28 | int symbol__alloc_hist(struct symbol *sym) |
29 | { | 29 | { |
30 | struct annotation *notes = symbol__annotation(sym); | 30 | struct annotation *notes = symbol__annotation(sym); |
31 | size_t sizeof_sym_hist = (sizeof(struct sym_hist) + | 31 | const size_t size = sym->end - sym->start + 1; |
32 | (sym->end - sym->start) * sizeof(u64)); | 32 | size_t sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64)); |
33 | 33 | ||
34 | notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist); | 34 | notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist); |
35 | if (notes->src == NULL) | 35 | if (notes->src == NULL) |
@@ -64,8 +64,8 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | |||
64 | 64 | ||
65 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); | 65 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); |
66 | 66 | ||
67 | if (addr >= sym->end) | 67 | if (addr < sym->start || addr > sym->end) |
68 | return 0; | 68 | return -ERANGE; |
69 | 69 | ||
70 | offset = addr - sym->start; | 70 | offset = addr - sym->start; |
71 | h = annotation__histogram(notes, evidx); | 71 | h = annotation__histogram(notes, evidx); |
@@ -84,10 +84,15 @@ static struct objdump_line *objdump_line__new(s64 offset, char *line, size_t pri | |||
84 | 84 | ||
85 | if (self != NULL) { | 85 | if (self != NULL) { |
86 | self->offset = offset; | 86 | self->offset = offset; |
87 | self->line = line; | 87 | self->line = strdup(line); |
88 | if (self->line == NULL) | ||
89 | goto out_delete; | ||
88 | } | 90 | } |
89 | 91 | ||
90 | return self; | 92 | return self; |
93 | out_delete: | ||
94 | free(self); | ||
95 | return NULL; | ||
91 | } | 96 | } |
92 | 97 | ||
93 | void objdump_line__free(struct objdump_line *self) | 98 | void objdump_line__free(struct objdump_line *self) |
@@ -112,7 +117,7 @@ struct objdump_line *objdump__get_next_ip_line(struct list_head *head, | |||
112 | } | 117 | } |
113 | 118 | ||
114 | static int objdump_line__print(struct objdump_line *oline, struct symbol *sym, | 119 | static int objdump_line__print(struct objdump_line *oline, struct symbol *sym, |
115 | int evidx, u64 len, int min_pcnt, | 120 | u64 start, int evidx, u64 len, int min_pcnt, |
116 | int printed, int max_lines, | 121 | int printed, int max_lines, |
117 | struct objdump_line *queue) | 122 | struct objdump_line *queue) |
118 | { | 123 | { |
@@ -128,6 +133,7 @@ static int objdump_line__print(struct objdump_line *oline, struct symbol *sym, | |||
128 | struct source_line *src_line = notes->src->lines; | 133 | struct source_line *src_line = notes->src->lines; |
129 | struct sym_hist *h = annotation__histogram(notes, evidx); | 134 | struct sym_hist *h = annotation__histogram(notes, evidx); |
130 | s64 offset = oline->offset; | 135 | s64 offset = oline->offset; |
136 | const u64 addr = start + offset; | ||
131 | struct objdump_line *next; | 137 | struct objdump_line *next; |
132 | 138 | ||
133 | next = objdump__get_next_ip_line(¬es->src->source, oline); | 139 | next = objdump__get_next_ip_line(¬es->src->source, oline); |
@@ -157,7 +163,7 @@ static int objdump_line__print(struct objdump_line *oline, struct symbol *sym, | |||
157 | list_for_each_entry_from(queue, ¬es->src->source, node) { | 163 | list_for_each_entry_from(queue, ¬es->src->source, node) { |
158 | if (queue == oline) | 164 | if (queue == oline) |
159 | break; | 165 | break; |
160 | objdump_line__print(queue, sym, evidx, len, | 166 | objdump_line__print(queue, sym, start, evidx, len, |
161 | 0, 0, 1, NULL); | 167 | 0, 0, 1, NULL); |
162 | } | 168 | } |
163 | } | 169 | } |
@@ -180,6 +186,7 @@ static int objdump_line__print(struct objdump_line *oline, struct symbol *sym, | |||
180 | 186 | ||
181 | color_fprintf(stdout, color, " %7.2f", percent); | 187 | color_fprintf(stdout, color, " %7.2f", percent); |
182 | printf(" : "); | 188 | printf(" : "); |
189 | color_fprintf(stdout, PERF_COLOR_MAGENTA, " %" PRIx64 ":", addr); | ||
183 | color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", oline->line); | 190 | color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", oline->line); |
184 | } else if (max_lines && printed >= max_lines) | 191 | } else if (max_lines && printed >= max_lines) |
185 | return 1; | 192 | return 1; |
@@ -201,7 +208,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | |||
201 | { | 208 | { |
202 | struct annotation *notes = symbol__annotation(sym); | 209 | struct annotation *notes = symbol__annotation(sym); |
203 | struct objdump_line *objdump_line; | 210 | struct objdump_line *objdump_line; |
204 | char *line = NULL, *tmp, *tmp2, *c; | 211 | char *line = NULL, *parsed_line, *tmp, *tmp2, *c; |
205 | size_t line_len; | 212 | size_t line_len; |
206 | s64 line_ip, offset = -1; | 213 | s64 line_ip, offset = -1; |
207 | 214 | ||
@@ -219,6 +226,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | |||
219 | *c = 0; | 226 | *c = 0; |
220 | 227 | ||
221 | line_ip = -1; | 228 | line_ip = -1; |
229 | parsed_line = line; | ||
222 | 230 | ||
223 | /* | 231 | /* |
224 | * Strip leading spaces: | 232 | * Strip leading spaces: |
@@ -246,13 +254,16 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | |||
246 | offset = line_ip - start; | 254 | offset = line_ip - start; |
247 | if (offset < 0 || (u64)line_ip > end) | 255 | if (offset < 0 || (u64)line_ip > end) |
248 | offset = -1; | 256 | offset = -1; |
257 | else | ||
258 | parsed_line = tmp2 + 1; | ||
249 | } | 259 | } |
250 | 260 | ||
251 | objdump_line = objdump_line__new(offset, line, privsize); | 261 | objdump_line = objdump_line__new(offset, parsed_line, privsize); |
252 | if (objdump_line == NULL) { | 262 | free(line); |
253 | free(line); | 263 | |
264 | if (objdump_line == NULL) | ||
254 | return -1; | 265 | return -1; |
255 | } | 266 | |
256 | objdump__add_line(¬es->src->source, objdump_line); | 267 | objdump__add_line(¬es->src->source, objdump_line); |
257 | 268 | ||
258 | return 0; | 269 | return 0; |
@@ -408,7 +419,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, | |||
408 | if (!notes->src->lines) | 419 | if (!notes->src->lines) |
409 | return -1; | 420 | return -1; |
410 | 421 | ||
411 | start = map->unmap_ip(map, sym->start); | 422 | start = map__rip_2objdump(map, sym->start); |
412 | 423 | ||
413 | for (i = 0; i < len; i++) { | 424 | for (i = 0; i < len; i++) { |
414 | char *path = NULL; | 425 | char *path = NULL; |
@@ -493,6 +504,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, | |||
493 | const char *filename = dso->long_name, *d_filename; | 504 | const char *filename = dso->long_name, *d_filename; |
494 | struct annotation *notes = symbol__annotation(sym); | 505 | struct annotation *notes = symbol__annotation(sym); |
495 | struct objdump_line *pos, *queue = NULL; | 506 | struct objdump_line *pos, *queue = NULL; |
507 | u64 start = map__rip_2objdump(map, sym->start); | ||
496 | int printed = 2, queue_len = 0; | 508 | int printed = 2, queue_len = 0; |
497 | int more = 0; | 509 | int more = 0; |
498 | u64 len; | 510 | u64 len; |
@@ -516,8 +528,9 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx, | |||
516 | queue_len = 0; | 528 | queue_len = 0; |
517 | } | 529 | } |
518 | 530 | ||
519 | switch (objdump_line__print(pos, sym, evidx, len, min_pcnt, | 531 | switch (objdump_line__print(pos, sym, start, evidx, len, |
520 | printed, max_lines, queue)) { | 532 | min_pcnt, printed, max_lines, |
533 | queue)) { | ||
521 | case 0: | 534 | case 0: |
522 | ++printed; | 535 | ++printed; |
523 | if (context) { | 536 | if (context) { |
@@ -561,16 +574,12 @@ void symbol__annotate_decay_histogram(struct symbol *sym, int evidx) | |||
561 | { | 574 | { |
562 | struct annotation *notes = symbol__annotation(sym); | 575 | struct annotation *notes = symbol__annotation(sym); |
563 | struct sym_hist *h = annotation__histogram(notes, evidx); | 576 | struct sym_hist *h = annotation__histogram(notes, evidx); |
564 | struct objdump_line *pos; | 577 | int len = sym->end - sym->start, offset; |
565 | int len = sym->end - sym->start; | ||
566 | 578 | ||
567 | h->sum = 0; | 579 | h->sum = 0; |
568 | 580 | for (offset = 0; offset < len; ++offset) { | |
569 | list_for_each_entry(pos, ¬es->src->source, node) { | 581 | h->addr[offset] = h->addr[offset] * 7 / 8; |
570 | if (pos->offset != -1 && pos->offset < len) { | 582 | h->sum += h->addr[offset]; |
571 | h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8; | ||
572 | h->sum += h->addr[pos->offset]; | ||
573 | } | ||
574 | } | 583 | } |
575 | } | 584 | } |
576 | 585 | ||