aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-annotate.c135
1 files changed, 112 insertions, 23 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index e47dd1587e39..5ec5de995872 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -145,21 +145,58 @@ static int process_sample_event(event_t *event, struct perf_session *session)
145 return 0; 145 return 0;
146} 146}
147 147
148static int parse_line(FILE *file, struct hist_entry *he, u64 len) 148struct objdump_line {
149 struct list_head node;
150 s64 offset;
151 char *line;
152};
153
154static struct objdump_line *objdump_line__new(s64 offset, char *line)
155{
156 struct objdump_line *self = malloc(sizeof(*self));
157
158 if (self != NULL) {
159 self->offset = offset;
160 self->line = line;
161 }
162
163 return self;
164}
165
166static void objdump_line__free(struct objdump_line *self)
167{
168 free(self->line);
169 free(self);
170}
171
172static void objdump__add_line(struct list_head *head, struct objdump_line *line)
173{
174 list_add_tail(&line->node, head);
175}
176
177static struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
178 struct objdump_line *pos)
179{
180 list_for_each_entry_continue(pos, head, node)
181 if (pos->offset >= 0)
182 return pos;
183
184 return NULL;
185}
186
187static int parse_line(FILE *file, struct hist_entry *he,
188 struct list_head *head)
149{ 189{
150 struct symbol *sym = he->sym; 190 struct symbol *sym = he->sym;
191 struct objdump_line *objdump_line;
151 char *line = NULL, *tmp, *tmp2; 192 char *line = NULL, *tmp, *tmp2;
152 static const char *prev_line;
153 static const char *prev_color;
154 unsigned int offset;
155 size_t line_len; 193 size_t line_len;
156 u64 start; 194 s64 line_ip, offset = -1;
157 s64 line_ip;
158 int ret;
159 char *c; 195 char *c;
160 196
161 if (getline(&line, &line_len, file) < 0) 197 if (getline(&line, &line_len, file) < 0)
162 return -1; 198 return -1;
199
163 if (!line) 200 if (!line)
164 return -1; 201 return -1;
165 202
@@ -168,8 +205,6 @@ static int parse_line(FILE *file, struct hist_entry *he, u64 len)
168 *c = 0; 205 *c = 0;
169 206
170 line_ip = -1; 207 line_ip = -1;
171 offset = 0;
172 ret = -2;
173 208
174 /* 209 /*
175 * Strip leading spaces: 210 * Strip leading spaces:
@@ -190,9 +225,30 @@ static int parse_line(FILE *file, struct hist_entry *he, u64 len)
190 line_ip = -1; 225 line_ip = -1;
191 } 226 }
192 227
193 start = map__rip_2objdump(he->map, sym->start);
194
195 if (line_ip != -1) { 228 if (line_ip != -1) {
229 u64 start = map__rip_2objdump(he->map, sym->start);
230 offset = line_ip - start;
231 }
232
233 objdump_line = objdump_line__new(offset, line);
234 if (objdump_line == NULL) {
235 free(line);
236 return -1;
237 }
238 objdump__add_line(head, objdump_line);
239
240 return 0;
241}
242
243static int objdump_line__print(struct objdump_line *self,
244 struct list_head *head,
245 struct hist_entry *he, u64 len)
246{
247 struct symbol *sym = he->sym;
248 static const char *prev_line;
249 static const char *prev_color;
250
251 if (self->offset != -1) {
196 const char *path = NULL; 252 const char *path = NULL;
197 unsigned int hits = 0; 253 unsigned int hits = 0;
198 double percent = 0.0; 254 double percent = 0.0;
@@ -200,15 +256,22 @@ static int parse_line(FILE *file, struct hist_entry *he, u64 len)
200 struct sym_priv *priv = symbol__priv(sym); 256 struct sym_priv *priv = symbol__priv(sym);
201 struct sym_ext *sym_ext = priv->ext; 257 struct sym_ext *sym_ext = priv->ext;
202 struct sym_hist *h = priv->hist; 258 struct sym_hist *h = priv->hist;
259 s64 offset = self->offset;
260 struct objdump_line *next = objdump__get_next_ip_line(head, self);
261
262 while (offset < (s64)len &&
263 (next == NULL || offset < next->offset)) {
264 if (sym_ext) {
265 if (path == NULL)
266 path = sym_ext[offset].path;
267 percent += sym_ext[offset].percent;
268 } else
269 hits += h->ip[offset];
270
271 ++offset;
272 }
203 273
204 offset = line_ip - start; 274 if (sym_ext == NULL && h->sum)
205 if (offset < len)
206 hits = h->ip[offset];
207
208 if (offset < len && sym_ext) {
209 path = sym_ext[offset].path;
210 percent = sym_ext[offset].percent;
211 } else if (h->sum)
212 percent = 100.0 * hits / h->sum; 275 percent = 100.0 * hits / h->sum;
213 276
214 color = get_percent_color(percent); 277 color = get_percent_color(percent);
@@ -229,12 +292,12 @@ static int parse_line(FILE *file, struct hist_entry *he, u64 len)
229 292
230 color_fprintf(stdout, color, " %7.2f", percent); 293 color_fprintf(stdout, color, " %7.2f", percent);
231 printf(" : "); 294 printf(" : ");
232 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", line); 295 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", self->line);
233 } else { 296 } else {
234 if (!*line) 297 if (!*self->line)
235 printf(" :\n"); 298 printf(" :\n");
236 else 299 else
237 printf(" : %s\n", line); 300 printf(" : %s\n", self->line);
238 } 301 }
239 302
240 return 0; 303 return 0;
@@ -360,6 +423,20 @@ static void print_summary(const char *filename)
360 } 423 }
361} 424}
362 425
426static void hist_entry__print_hits(struct hist_entry *self)
427{
428 struct symbol *sym = self->sym;
429 struct sym_priv *priv = symbol__priv(sym);
430 struct sym_hist *h = priv->hist;
431 u64 len = sym->end - sym->start, offset;
432
433 for (offset = 0; offset < len; ++offset)
434 if (h->ip[offset] != 0)
435 printf("%*Lx: %Lu\n", BITS_PER_LONG / 2,
436 sym->start + offset, h->ip[offset]);
437 printf("%*s: %Lu\n", BITS_PER_LONG / 2, "h->sum", h->sum);
438}
439
363static void annotate_sym(struct hist_entry *he) 440static void annotate_sym(struct hist_entry *he)
364{ 441{
365 struct map *map = he->map; 442 struct map *map = he->map;
@@ -369,6 +446,8 @@ static void annotate_sym(struct hist_entry *he)
369 u64 len; 446 u64 len;
370 char command[PATH_MAX*2]; 447 char command[PATH_MAX*2];
371 FILE *file; 448 FILE *file;
449 LIST_HEAD(head);
450 struct objdump_line *pos, *n;
372 451
373 if (!filename) 452 if (!filename)
374 return; 453 return;
@@ -410,11 +489,21 @@ static void annotate_sym(struct hist_entry *he)
410 return; 489 return;
411 490
412 while (!feof(file)) { 491 while (!feof(file)) {
413 if (parse_line(file, he, len) < 0) 492 if (parse_line(file, he, &head) < 0)
414 break; 493 break;
415 } 494 }
416 495
417 pclose(file); 496 pclose(file);
497
498 if (verbose)
499 hist_entry__print_hits(he);
500
501 list_for_each_entry_safe(pos, n, &head, node) {
502 objdump_line__print(pos, &head, he, len);
503 list_del(&pos->node);
504 objdump_line__free(pos);
505 }
506
418 if (print_line) 507 if (print_line)
419 free_source_line(he, len); 508 free_source_line(he, len);
420} 509}