]> Pileus Git - ~andy/linux/blob - tools/perf/util/annotate.c
Merge tag 'disintegrate-sh-20121009' of git://git.infradead.org/users/dhowells/linux...
[~andy/linux] / tools / perf / util / annotate.c
1 /*
2  * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3  *
4  * Parts came from builtin-annotate.c, see those files for further
5  * copyright notes.
6  *
7  * Released under the GPL v2. (and only v2, not any later version)
8  */
9
10 #include "util.h"
11 #include "build-id.h"
12 #include "color.h"
13 #include "cache.h"
14 #include "symbol.h"
15 #include "debug.h"
16 #include "annotate.h"
17 #include <pthread.h>
18
19 const char      *disassembler_style;
20 const char      *objdump_path;
21
22 static struct ins *ins__find(const char *name);
23 static int disasm_line__parse(char *line, char **namep, char **rawp);
24
25 static void ins__delete(struct ins_operands *ops)
26 {
27         free(ops->source.raw);
28         free(ops->source.name);
29         free(ops->target.raw);
30         free(ops->target.name);
31 }
32
33 static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
34                               struct ins_operands *ops)
35 {
36         return scnprintf(bf, size, "%-6.6s %s", ins->name, ops->raw);
37 }
38
39 int ins__scnprintf(struct ins *ins, char *bf, size_t size,
40                   struct ins_operands *ops)
41 {
42         if (ins->ops->scnprintf)
43                 return ins->ops->scnprintf(ins, bf, size, ops);
44
45         return ins__raw_scnprintf(ins, bf, size, ops);
46 }
47
48 static int call__parse(struct ins_operands *ops)
49 {
50         char *endptr, *tok, *name;
51
52         ops->target.addr = strtoull(ops->raw, &endptr, 16);
53
54         name = strchr(endptr, '<');
55         if (name == NULL)
56                 goto indirect_call;
57
58         name++;
59
60         tok = strchr(name, '>');
61         if (tok == NULL)
62                 return -1;
63
64         *tok = '\0';
65         ops->target.name = strdup(name);
66         *tok = '>';
67
68         return ops->target.name == NULL ? -1 : 0;
69
70 indirect_call:
71         tok = strchr(endptr, '(');
72         if (tok != NULL) {
73                 ops->target.addr = 0;
74                 return 0;
75         }
76
77         tok = strchr(endptr, '*');
78         if (tok == NULL)
79                 return -1;
80
81         ops->target.addr = strtoull(tok + 1, NULL, 16);
82         return 0;
83 }
84
85 static int call__scnprintf(struct ins *ins, char *bf, size_t size,
86                            struct ins_operands *ops)
87 {
88         if (ops->target.name)
89                 return scnprintf(bf, size, "%-6.6s %s", ins->name, ops->target.name);
90
91         if (ops->target.addr == 0)
92                 return ins__raw_scnprintf(ins, bf, size, ops);
93
94         return scnprintf(bf, size, "%-6.6s *%" PRIx64, ins->name, ops->target.addr);
95 }
96
97 static struct ins_ops call_ops = {
98         .parse     = call__parse,
99         .scnprintf = call__scnprintf,
100 };
101
102 bool ins__is_call(const struct ins *ins)
103 {
104         return ins->ops == &call_ops;
105 }
106
107 static int jump__parse(struct ins_operands *ops)
108 {
109         const char *s = strchr(ops->raw, '+');
110
111         ops->target.addr = strtoll(ops->raw, NULL, 16);
112
113         if (s++ != NULL)
114                 ops->target.offset = strtoll(s, NULL, 16);
115         else
116                 ops->target.offset = UINT64_MAX;
117
118         return 0;
119 }
120
121 static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
122                            struct ins_operands *ops)
123 {
124         return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset);
125 }
126
127 static struct ins_ops jump_ops = {
128         .parse     = jump__parse,
129         .scnprintf = jump__scnprintf,
130 };
131
132 bool ins__is_jump(const struct ins *ins)
133 {
134         return ins->ops == &jump_ops;
135 }
136
137 static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
138 {
139         char *endptr, *name, *t;
140
141         if (strstr(raw, "(%rip)") == NULL)
142                 return 0;
143
144         *addrp = strtoull(comment, &endptr, 16);
145         name = strchr(endptr, '<');
146         if (name == NULL)
147                 return -1;
148
149         name++;
150
151         t = strchr(name, '>');
152         if (t == NULL)
153                 return 0;
154
155         *t = '\0';
156         *namep = strdup(name);
157         *t = '>';
158
159         return 0;
160 }
161
162 static int lock__parse(struct ins_operands *ops)
163 {
164         char *name;
165
166         ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
167         if (ops->locked.ops == NULL)
168                 return 0;
169
170         if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0)
171                 goto out_free_ops;
172
173         ops->locked.ins = ins__find(name);
174         if (ops->locked.ins == NULL)
175                 goto out_free_ops;
176
177         if (!ops->locked.ins->ops)
178                 return 0;
179
180         if (ops->locked.ins->ops->parse)
181                 ops->locked.ins->ops->parse(ops->locked.ops);
182
183         return 0;
184
185 out_free_ops:
186         free(ops->locked.ops);
187         ops->locked.ops = NULL;
188         return 0;
189 }
190
191 static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
192                            struct ins_operands *ops)
193 {
194         int printed;
195
196         if (ops->locked.ins == NULL)
197                 return ins__raw_scnprintf(ins, bf, size, ops);
198
199         printed = scnprintf(bf, size, "%-6.6s ", ins->name);
200         return printed + ins__scnprintf(ops->locked.ins, bf + printed,
201                                         size - printed, ops->locked.ops);
202 }
203
204 static void lock__delete(struct ins_operands *ops)
205 {
206         free(ops->locked.ops);
207         free(ops->target.raw);
208         free(ops->target.name);
209 }
210
211 static struct ins_ops lock_ops = {
212         .free      = lock__delete,
213         .parse     = lock__parse,
214         .scnprintf = lock__scnprintf,
215 };
216
217 static int mov__parse(struct ins_operands *ops)
218 {
219         char *s = strchr(ops->raw, ','), *target, *comment, prev;
220
221         if (s == NULL)
222                 return -1;
223
224         *s = '\0';
225         ops->source.raw = strdup(ops->raw);
226         *s = ',';
227         
228         if (ops->source.raw == NULL)
229                 return -1;
230
231         target = ++s;
232
233         while (s[0] != '\0' && !isspace(s[0]))
234                 ++s;
235         prev = *s;
236         *s = '\0';
237
238         ops->target.raw = strdup(target);
239         *s = prev;
240
241         if (ops->target.raw == NULL)
242                 goto out_free_source;
243
244         comment = strchr(s, '#');
245         if (comment == NULL)
246                 return 0;
247
248         while (comment[0] != '\0' && isspace(comment[0]))
249                 ++comment;
250
251         comment__symbol(ops->source.raw, comment, &ops->source.addr, &ops->source.name);
252         comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name);
253
254         return 0;
255
256 out_free_source:
257         free(ops->source.raw);
258         ops->source.raw = NULL;
259         return -1;
260 }
261
262 static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
263                            struct ins_operands *ops)
264 {
265         return scnprintf(bf, size, "%-6.6s %s,%s", ins->name,
266                          ops->source.name ?: ops->source.raw,
267                          ops->target.name ?: ops->target.raw);
268 }
269
270 static struct ins_ops mov_ops = {
271         .parse     = mov__parse,
272         .scnprintf = mov__scnprintf,
273 };
274
275 static int dec__parse(struct ins_operands *ops)
276 {
277         char *target, *comment, *s, prev;
278
279         target = s = ops->raw;
280
281         while (s[0] != '\0' && !isspace(s[0]))
282                 ++s;
283         prev = *s;
284         *s = '\0';
285
286         ops->target.raw = strdup(target);
287         *s = prev;
288
289         if (ops->target.raw == NULL)
290                 return -1;
291
292         comment = strchr(s, '#');
293         if (comment == NULL)
294                 return 0;
295
296         while (comment[0] != '\0' && isspace(comment[0]))
297                 ++comment;
298
299         comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name);
300
301         return 0;
302 }
303
304 static int dec__scnprintf(struct ins *ins, char *bf, size_t size,
305                            struct ins_operands *ops)
306 {
307         return scnprintf(bf, size, "%-6.6s %s", ins->name,
308                          ops->target.name ?: ops->target.raw);
309 }
310
311 static struct ins_ops dec_ops = {
312         .parse     = dec__parse,
313         .scnprintf = dec__scnprintf,
314 };
315
316 static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size,
317                           struct ins_operands *ops __maybe_unused)
318 {
319         return scnprintf(bf, size, "%-6.6s", "nop");
320 }
321
322 static struct ins_ops nop_ops = {
323         .scnprintf = nop__scnprintf,
324 };
325
326 /*
327  * Must be sorted by name!
328  */
329 static struct ins instructions[] = {
330         { .name = "add",   .ops  = &mov_ops, },
331         { .name = "addl",  .ops  = &mov_ops, },
332         { .name = "addq",  .ops  = &mov_ops, },
333         { .name = "addw",  .ops  = &mov_ops, },
334         { .name = "and",   .ops  = &mov_ops, },
335         { .name = "bts",   .ops  = &mov_ops, },
336         { .name = "call",  .ops  = &call_ops, },
337         { .name = "callq", .ops  = &call_ops, },
338         { .name = "cmp",   .ops  = &mov_ops, },
339         { .name = "cmpb",  .ops  = &mov_ops, },
340         { .name = "cmpl",  .ops  = &mov_ops, },
341         { .name = "cmpq",  .ops  = &mov_ops, },
342         { .name = "cmpw",  .ops  = &mov_ops, },
343         { .name = "cmpxch", .ops  = &mov_ops, },
344         { .name = "dec",   .ops  = &dec_ops, },
345         { .name = "decl",  .ops  = &dec_ops, },
346         { .name = "imul",  .ops  = &mov_ops, },
347         { .name = "inc",   .ops  = &dec_ops, },
348         { .name = "incl",  .ops  = &dec_ops, },
349         { .name = "ja",    .ops  = &jump_ops, },
350         { .name = "jae",   .ops  = &jump_ops, },
351         { .name = "jb",    .ops  = &jump_ops, },
352         { .name = "jbe",   .ops  = &jump_ops, },
353         { .name = "jc",    .ops  = &jump_ops, },
354         { .name = "jcxz",  .ops  = &jump_ops, },
355         { .name = "je",    .ops  = &jump_ops, },
356         { .name = "jecxz", .ops  = &jump_ops, },
357         { .name = "jg",    .ops  = &jump_ops, },
358         { .name = "jge",   .ops  = &jump_ops, },
359         { .name = "jl",    .ops  = &jump_ops, },
360         { .name = "jle",   .ops  = &jump_ops, },
361         { .name = "jmp",   .ops  = &jump_ops, },
362         { .name = "jmpq",  .ops  = &jump_ops, },
363         { .name = "jna",   .ops  = &jump_ops, },
364         { .name = "jnae",  .ops  = &jump_ops, },
365         { .name = "jnb",   .ops  = &jump_ops, },
366         { .name = "jnbe",  .ops  = &jump_ops, },
367         { .name = "jnc",   .ops  = &jump_ops, },
368         { .name = "jne",   .ops  = &jump_ops, },
369         { .name = "jng",   .ops  = &jump_ops, },
370         { .name = "jnge",  .ops  = &jump_ops, },
371         { .name = "jnl",   .ops  = &jump_ops, },
372         { .name = "jnle",  .ops  = &jump_ops, },
373         { .name = "jno",   .ops  = &jump_ops, },
374         { .name = "jnp",   .ops  = &jump_ops, },
375         { .name = "jns",   .ops  = &jump_ops, },
376         { .name = "jnz",   .ops  = &jump_ops, },
377         { .name = "jo",    .ops  = &jump_ops, },
378         { .name = "jp",    .ops  = &jump_ops, },
379         { .name = "jpe",   .ops  = &jump_ops, },
380         { .name = "jpo",   .ops  = &jump_ops, },
381         { .name = "jrcxz", .ops  = &jump_ops, },
382         { .name = "js",    .ops  = &jump_ops, },
383         { .name = "jz",    .ops  = &jump_ops, },
384         { .name = "lea",   .ops  = &mov_ops, },
385         { .name = "lock",  .ops  = &lock_ops, },
386         { .name = "mov",   .ops  = &mov_ops, },
387         { .name = "movb",  .ops  = &mov_ops, },
388         { .name = "movdqa",.ops  = &mov_ops, },
389         { .name = "movl",  .ops  = &mov_ops, },
390         { .name = "movq",  .ops  = &mov_ops, },
391         { .name = "movslq", .ops  = &mov_ops, },
392         { .name = "movzbl", .ops  = &mov_ops, },
393         { .name = "movzwl", .ops  = &mov_ops, },
394         { .name = "nop",   .ops  = &nop_ops, },
395         { .name = "nopl",  .ops  = &nop_ops, },
396         { .name = "nopw",  .ops  = &nop_ops, },
397         { .name = "or",    .ops  = &mov_ops, },
398         { .name = "orl",   .ops  = &mov_ops, },
399         { .name = "test",  .ops  = &mov_ops, },
400         { .name = "testb", .ops  = &mov_ops, },
401         { .name = "testl", .ops  = &mov_ops, },
402         { .name = "xadd",  .ops  = &mov_ops, },
403 };
404
405 static int ins__cmp(const void *name, const void *insp)
406 {
407         const struct ins *ins = insp;
408
409         return strcmp(name, ins->name);
410 }
411
412 static struct ins *ins__find(const char *name)
413 {
414         const int nmemb = ARRAY_SIZE(instructions);
415
416         return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp);
417 }
418
419 int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym)
420 {
421         struct annotation *notes = symbol__annotation(sym);
422         pthread_mutex_init(&notes->lock, NULL);
423         return 0;
424 }
425
426 int symbol__alloc_hist(struct symbol *sym)
427 {
428         struct annotation *notes = symbol__annotation(sym);
429         const size_t size = symbol__size(sym);
430         size_t sizeof_sym_hist;
431
432         /* Check for overflow when calculating sizeof_sym_hist */
433         if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(u64))
434                 return -1;
435
436         sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64));
437
438         /* Check for overflow in zalloc argument */
439         if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src))
440                                 / symbol_conf.nr_events)
441                 return -1;
442
443         notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist);
444         if (notes->src == NULL)
445                 return -1;
446         notes->src->sizeof_sym_hist = sizeof_sym_hist;
447         notes->src->nr_histograms   = symbol_conf.nr_events;
448         INIT_LIST_HEAD(&notes->src->source);
449         return 0;
450 }
451
452 void symbol__annotate_zero_histograms(struct symbol *sym)
453 {
454         struct annotation *notes = symbol__annotation(sym);
455
456         pthread_mutex_lock(&notes->lock);
457         if (notes->src != NULL)
458                 memset(notes->src->histograms, 0,
459                        notes->src->nr_histograms * notes->src->sizeof_sym_hist);
460         pthread_mutex_unlock(&notes->lock);
461 }
462
463 int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
464                              int evidx, u64 addr)
465 {
466         unsigned offset;
467         struct annotation *notes;
468         struct sym_hist *h;
469
470         notes = symbol__annotation(sym);
471         if (notes->src == NULL)
472                 return -ENOMEM;
473
474         pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
475
476         if (addr < sym->start || addr > sym->end)
477                 return -ERANGE;
478
479         offset = addr - sym->start;
480         h = annotation__histogram(notes, evidx);
481         h->sum++;
482         h->addr[offset]++;
483
484         pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
485                   ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name,
486                   addr, addr - sym->start, evidx, h->addr[offset]);
487         return 0;
488 }
489
490 static void disasm_line__init_ins(struct disasm_line *dl)
491 {
492         dl->ins = ins__find(dl->name);
493
494         if (dl->ins == NULL)
495                 return;
496
497         if (!dl->ins->ops)
498                 return;
499
500         if (dl->ins->ops->parse)
501                 dl->ins->ops->parse(&dl->ops);
502 }
503
504 static int disasm_line__parse(char *line, char **namep, char **rawp)
505 {
506         char *name = line, tmp;
507
508         while (isspace(name[0]))
509                 ++name;
510
511         if (name[0] == '\0')
512                 return -1;
513
514         *rawp = name + 1;
515
516         while ((*rawp)[0] != '\0' && !isspace((*rawp)[0]))
517                 ++*rawp;
518
519         tmp = (*rawp)[0];
520         (*rawp)[0] = '\0';
521         *namep = strdup(name);
522
523         if (*namep == NULL)
524                 goto out_free_name;
525
526         (*rawp)[0] = tmp;
527
528         if ((*rawp)[0] != '\0') {
529                 (*rawp)++;
530                 while (isspace((*rawp)[0]))
531                         ++(*rawp);
532         }
533
534         return 0;
535
536 out_free_name:
537         free(*namep);
538         *namep = NULL;
539         return -1;
540 }
541
542 static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize)
543 {
544         struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
545
546         if (dl != NULL) {
547                 dl->offset = offset;
548                 dl->line = strdup(line);
549                 if (dl->line == NULL)
550                         goto out_delete;
551
552                 if (offset != -1) {
553                         if (disasm_line__parse(dl->line, &dl->name, &dl->ops.raw) < 0)
554                                 goto out_free_line;
555
556                         disasm_line__init_ins(dl);
557                 }
558         }
559
560         return dl;
561
562 out_free_line:
563         free(dl->line);
564 out_delete:
565         free(dl);
566         return NULL;
567 }
568
569 void disasm_line__free(struct disasm_line *dl)
570 {
571         free(dl->line);
572         free(dl->name);
573         if (dl->ins && dl->ins->ops->free)
574                 dl->ins->ops->free(&dl->ops);
575         else
576                 ins__delete(&dl->ops);
577         free(dl);
578 }
579
580 int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw)
581 {
582         if (raw || !dl->ins)
583                 return scnprintf(bf, size, "%-6.6s %s", dl->name, dl->ops.raw);
584
585         return ins__scnprintf(dl->ins, bf, size, &dl->ops);
586 }
587
588 static void disasm__add(struct list_head *head, struct disasm_line *line)
589 {
590         list_add_tail(&line->node, head);
591 }
592
593 struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos)
594 {
595         list_for_each_entry_continue(pos, head, node)
596                 if (pos->offset >= 0)
597                         return pos;
598
599         return NULL;
600 }
601
602 static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 start,
603                       int evidx, u64 len, int min_pcnt, int printed,
604                       int max_lines, struct disasm_line *queue)
605 {
606         static const char *prev_line;
607         static const char *prev_color;
608
609         if (dl->offset != -1) {
610                 const char *path = NULL;
611                 unsigned int hits = 0;
612                 double percent = 0.0;
613                 const char *color;
614                 struct annotation *notes = symbol__annotation(sym);
615                 struct source_line *src_line = notes->src->lines;
616                 struct sym_hist *h = annotation__histogram(notes, evidx);
617                 s64 offset = dl->offset;
618                 const u64 addr = start + offset;
619                 struct disasm_line *next;
620
621                 next = disasm__get_next_ip_line(&notes->src->source, dl);
622
623                 while (offset < (s64)len &&
624                        (next == NULL || offset < next->offset)) {
625                         if (src_line) {
626                                 if (path == NULL)
627                                         path = src_line[offset].path;
628                                 percent += src_line[offset].percent;
629                         } else
630                                 hits += h->addr[offset];
631
632                         ++offset;
633                 }
634
635                 if (src_line == NULL && h->sum)
636                         percent = 100.0 * hits / h->sum;
637
638                 if (percent < min_pcnt)
639                         return -1;
640
641                 if (max_lines && printed >= max_lines)
642                         return 1;
643
644                 if (queue != NULL) {
645                         list_for_each_entry_from(queue, &notes->src->source, node) {
646                                 if (queue == dl)
647                                         break;
648                                 disasm_line__print(queue, sym, start, evidx, len,
649                                                     0, 0, 1, NULL);
650                         }
651                 }
652
653                 color = get_percent_color(percent);
654
655                 /*
656                  * Also color the filename and line if needed, with
657                  * the same color than the percentage. Don't print it
658                  * twice for close colored addr with the same filename:line
659                  */
660                 if (path) {
661                         if (!prev_line || strcmp(prev_line, path)
662                                        || color != prev_color) {
663                                 color_fprintf(stdout, color, " %s", path);
664                                 prev_line = path;
665                                 prev_color = color;
666                         }
667                 }
668
669                 color_fprintf(stdout, color, " %7.2f", percent);
670                 printf(" :      ");
671                 color_fprintf(stdout, PERF_COLOR_MAGENTA, "  %" PRIx64 ":", addr);
672                 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", dl->line);
673         } else if (max_lines && printed >= max_lines)
674                 return 1;
675         else {
676                 if (queue)
677                         return -1;
678
679                 if (!*dl->line)
680                         printf("         :\n");
681                 else
682                         printf("         :      %s\n", dl->line);
683         }
684
685         return 0;
686 }
687
688 static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
689                                       FILE *file, size_t privsize)
690 {
691         struct annotation *notes = symbol__annotation(sym);
692         struct disasm_line *dl;
693         char *line = NULL, *parsed_line, *tmp, *tmp2, *c;
694         size_t line_len;
695         s64 line_ip, offset = -1;
696
697         if (getline(&line, &line_len, file) < 0)
698                 return -1;
699
700         if (!line)
701                 return -1;
702
703         while (line_len != 0 && isspace(line[line_len - 1]))
704                 line[--line_len] = '\0';
705
706         c = strchr(line, '\n');
707         if (c)
708                 *c = 0;
709
710         line_ip = -1;
711         parsed_line = line;
712
713         /*
714          * Strip leading spaces:
715          */
716         tmp = line;
717         while (*tmp) {
718                 if (*tmp != ' ')
719                         break;
720                 tmp++;
721         }
722
723         if (*tmp) {
724                 /*
725                  * Parse hexa addresses followed by ':'
726                  */
727                 line_ip = strtoull(tmp, &tmp2, 16);
728                 if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0')
729                         line_ip = -1;
730         }
731
732         if (line_ip != -1) {
733                 u64 start = map__rip_2objdump(map, sym->start),
734                     end = map__rip_2objdump(map, sym->end);
735
736                 offset = line_ip - start;
737                 if (offset < 0 || (u64)line_ip > end)
738                         offset = -1;
739                 else
740                         parsed_line = tmp2 + 1;
741         }
742
743         dl = disasm_line__new(offset, parsed_line, privsize);
744         free(line);
745
746         if (dl == NULL)
747                 return -1;
748
749         disasm__add(&notes->src->source, dl);
750
751         return 0;
752 }
753
754 int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
755 {
756         struct dso *dso = map->dso;
757         char *filename = dso__build_id_filename(dso, NULL, 0);
758         bool free_filename = true;
759         char command[PATH_MAX * 2];
760         FILE *file;
761         int err = 0;
762         char symfs_filename[PATH_MAX];
763
764         if (filename) {
765                 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
766                          symbol_conf.symfs, filename);
767         }
768
769         if (filename == NULL) {
770                 if (dso->has_build_id) {
771                         pr_err("Can't annotate %s: not enough memory\n",
772                                sym->name);
773                         return -ENOMEM;
774                 }
775                 goto fallback;
776         } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
777                    strstr(command, "[kernel.kallsyms]") ||
778                    access(symfs_filename, R_OK)) {
779                 free(filename);
780 fallback:
781                 /*
782                  * If we don't have build-ids or the build-id file isn't in the
783                  * cache, or is just a kallsyms file, well, lets hope that this
784                  * DSO is the same as when 'perf record' ran.
785                  */
786                 filename = dso->long_name;
787                 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
788                          symbol_conf.symfs, filename);
789                 free_filename = false;
790         }
791
792         if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) {
793                 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id ";
794                 char *build_id_msg = NULL;
795
796                 if (dso->annotate_warned)
797                         goto out_free_filename;
798
799                 if (dso->has_build_id) {
800                         build_id__sprintf(dso->build_id,
801                                           sizeof(dso->build_id), bf + 15);
802                         build_id_msg = bf;
803                 }
804                 err = -ENOENT;
805                 dso->annotate_warned = 1;
806                 pr_err("Can't annotate %s:\n\n"
807                        "No vmlinux file%s\nwas found in the path.\n\n"
808                        "Please use:\n\n"
809                        "  perf buildid-cache -av vmlinux\n\n"
810                        "or:\n\n"
811                        "  --vmlinux vmlinux\n",
812                        sym->name, build_id_msg ?: "");
813                 goto out_free_filename;
814         }
815
816         pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
817                  filename, sym->name, map->unmap_ip(map, sym->start),
818                  map->unmap_ip(map, sym->end));
819
820         pr_debug("annotating [%p] %30s : [%p] %30s\n",
821                  dso, dso->long_name, sym, sym->name);
822
823         snprintf(command, sizeof(command),
824                  "%s %s%s --start-address=0x%016" PRIx64
825                  " --stop-address=0x%016" PRIx64
826                  " -d %s %s -C %s|grep -v %s|expand",
827                  objdump_path ? objdump_path : "objdump",
828                  disassembler_style ? "-M " : "",
829                  disassembler_style ? disassembler_style : "",
830                  map__rip_2objdump(map, sym->start),
831                  map__rip_2objdump(map, sym->end+1),
832                  symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
833                  symbol_conf.annotate_src ? "-S" : "",
834                  symfs_filename, filename);
835
836         pr_debug("Executing: %s\n", command);
837
838         file = popen(command, "r");
839         if (!file)
840                 goto out_free_filename;
841
842         while (!feof(file))
843                 if (symbol__parse_objdump_line(sym, map, file, privsize) < 0)
844                         break;
845
846         pclose(file);
847 out_free_filename:
848         if (free_filename)
849                 free(filename);
850         return err;
851 }
852
853 static void insert_source_line(struct rb_root *root, struct source_line *src_line)
854 {
855         struct source_line *iter;
856         struct rb_node **p = &root->rb_node;
857         struct rb_node *parent = NULL;
858
859         while (*p != NULL) {
860                 parent = *p;
861                 iter = rb_entry(parent, struct source_line, node);
862
863                 if (src_line->percent > iter->percent)
864                         p = &(*p)->rb_left;
865                 else
866                         p = &(*p)->rb_right;
867         }
868
869         rb_link_node(&src_line->node, parent, p);
870         rb_insert_color(&src_line->node, root);
871 }
872
873 static void symbol__free_source_line(struct symbol *sym, int len)
874 {
875         struct annotation *notes = symbol__annotation(sym);
876         struct source_line *src_line = notes->src->lines;
877         int i;
878
879         for (i = 0; i < len; i++)
880                 free(src_line[i].path);
881
882         free(src_line);
883         notes->src->lines = NULL;
884 }
885
886 /* Get the filename:line for the colored entries */
887 static int symbol__get_source_line(struct symbol *sym, struct map *map,
888                                    int evidx, struct rb_root *root, int len,
889                                    const char *filename)
890 {
891         u64 start;
892         int i;
893         char cmd[PATH_MAX * 2];
894         struct source_line *src_line;
895         struct annotation *notes = symbol__annotation(sym);
896         struct sym_hist *h = annotation__histogram(notes, evidx);
897
898         if (!h->sum)
899                 return 0;
900
901         src_line = notes->src->lines = calloc(len, sizeof(struct source_line));
902         if (!notes->src->lines)
903                 return -1;
904
905         start = map__rip_2objdump(map, sym->start);
906
907         for (i = 0; i < len; i++) {
908                 char *path = NULL;
909                 size_t line_len;
910                 u64 offset;
911                 FILE *fp;
912
913                 src_line[i].percent = 100.0 * h->addr[i] / h->sum;
914                 if (src_line[i].percent <= 0.5)
915                         continue;
916
917                 offset = start + i;
918                 sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset);
919                 fp = popen(cmd, "r");
920                 if (!fp)
921                         continue;
922
923                 if (getline(&path, &line_len, fp) < 0 || !line_len)
924                         goto next;
925
926                 src_line[i].path = malloc(sizeof(char) * line_len + 1);
927                 if (!src_line[i].path)
928                         goto next;
929
930                 strcpy(src_line[i].path, path);
931                 insert_source_line(root, &src_line[i]);
932
933         next:
934                 pclose(fp);
935         }
936
937         return 0;
938 }
939
940 static void print_summary(struct rb_root *root, const char *filename)
941 {
942         struct source_line *src_line;
943         struct rb_node *node;
944
945         printf("\nSorted summary for file %s\n", filename);
946         printf("----------------------------------------------\n\n");
947
948         if (RB_EMPTY_ROOT(root)) {
949                 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
950                 return;
951         }
952
953         node = rb_first(root);
954         while (node) {
955                 double percent;
956                 const char *color;
957                 char *path;
958
959                 src_line = rb_entry(node, struct source_line, node);
960                 percent = src_line->percent;
961                 color = get_percent_color(percent);
962                 path = src_line->path;
963
964                 color_fprintf(stdout, color, " %7.2f %s", percent, path);
965                 node = rb_next(node);
966         }
967 }
968
969 static void symbol__annotate_hits(struct symbol *sym, int evidx)
970 {
971         struct annotation *notes = symbol__annotation(sym);
972         struct sym_hist *h = annotation__histogram(notes, evidx);
973         u64 len = symbol__size(sym), offset;
974
975         for (offset = 0; offset < len; ++offset)
976                 if (h->addr[offset] != 0)
977                         printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
978                                sym->start + offset, h->addr[offset]);
979         printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
980 }
981
982 int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
983                             bool full_paths, int min_pcnt, int max_lines,
984                             int context)
985 {
986         struct dso *dso = map->dso;
987         char *filename;
988         const char *d_filename;
989         struct annotation *notes = symbol__annotation(sym);
990         struct disasm_line *pos, *queue = NULL;
991         u64 start = map__rip_2objdump(map, sym->start);
992         int printed = 2, queue_len = 0;
993         int more = 0;
994         u64 len;
995
996         filename = strdup(dso->long_name);
997         if (!filename)
998                 return -ENOMEM;
999
1000         if (full_paths)
1001                 d_filename = filename;
1002         else
1003                 d_filename = basename(filename);
1004
1005         len = symbol__size(sym);
1006
1007         printf(" Percent |      Source code & Disassembly of %s\n", d_filename);
1008         printf("------------------------------------------------\n");
1009
1010         if (verbose)
1011                 symbol__annotate_hits(sym, evidx);
1012
1013         list_for_each_entry(pos, &notes->src->source, node) {
1014                 if (context && queue == NULL) {
1015                         queue = pos;
1016                         queue_len = 0;
1017                 }
1018
1019                 switch (disasm_line__print(pos, sym, start, evidx, len,
1020                                             min_pcnt, printed, max_lines,
1021                                             queue)) {
1022                 case 0:
1023                         ++printed;
1024                         if (context) {
1025                                 printed += queue_len;
1026                                 queue = NULL;
1027                                 queue_len = 0;
1028                         }
1029                         break;
1030                 case 1:
1031                         /* filtered by max_lines */
1032                         ++more;
1033                         break;
1034                 case -1:
1035                 default:
1036                         /*
1037                          * Filtered by min_pcnt or non IP lines when
1038                          * context != 0
1039                          */
1040                         if (!context)
1041                                 break;
1042                         if (queue_len == context)
1043                                 queue = list_entry(queue->node.next, typeof(*queue), node);
1044                         else
1045                                 ++queue_len;
1046                         break;
1047                 }
1048         }
1049
1050         free(filename);
1051
1052         return more;
1053 }
1054
1055 void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
1056 {
1057         struct annotation *notes = symbol__annotation(sym);
1058         struct sym_hist *h = annotation__histogram(notes, evidx);
1059
1060         memset(h, 0, notes->src->sizeof_sym_hist);
1061 }
1062
1063 void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
1064 {
1065         struct annotation *notes = symbol__annotation(sym);
1066         struct sym_hist *h = annotation__histogram(notes, evidx);
1067         int len = symbol__size(sym), offset;
1068
1069         h->sum = 0;
1070         for (offset = 0; offset < len; ++offset) {
1071                 h->addr[offset] = h->addr[offset] * 7 / 8;
1072                 h->sum += h->addr[offset];
1073         }
1074 }
1075
1076 void disasm__purge(struct list_head *head)
1077 {
1078         struct disasm_line *pos, *n;
1079
1080         list_for_each_entry_safe(pos, n, head, node) {
1081                 list_del(&pos->node);
1082                 disasm_line__free(pos);
1083         }
1084 }
1085
1086 static size_t disasm_line__fprintf(struct disasm_line *dl, FILE *fp)
1087 {
1088         size_t printed;
1089
1090         if (dl->offset == -1)
1091                 return fprintf(fp, "%s\n", dl->line);
1092
1093         printed = fprintf(fp, "%#" PRIx64 " %s", dl->offset, dl->name);
1094
1095         if (dl->ops.raw[0] != '\0') {
1096                 printed += fprintf(fp, "%.*s %s\n", 6 - (int)printed, " ",
1097                                    dl->ops.raw);
1098         }
1099
1100         return printed + fprintf(fp, "\n");
1101 }
1102
1103 size_t disasm__fprintf(struct list_head *head, FILE *fp)
1104 {
1105         struct disasm_line *pos;
1106         size_t printed = 0;
1107
1108         list_for_each_entry(pos, head, node)
1109                 printed += disasm_line__fprintf(pos, fp);
1110
1111         return printed;
1112 }
1113
1114 int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
1115                          bool print_lines, bool full_paths, int min_pcnt,
1116                          int max_lines)
1117 {
1118         struct dso *dso = map->dso;
1119         const char *filename = dso->long_name;
1120         struct rb_root source_line = RB_ROOT;
1121         u64 len;
1122
1123         if (symbol__annotate(sym, map, 0) < 0)
1124                 return -1;
1125
1126         len = symbol__size(sym);
1127
1128         if (print_lines) {
1129                 symbol__get_source_line(sym, map, evidx, &source_line,
1130                                         len, filename);
1131                 print_summary(&source_line, filename);
1132         }
1133
1134         symbol__annotate_printf(sym, map, evidx, full_paths,
1135                                 min_pcnt, max_lines, 0);
1136         if (print_lines)
1137                 symbol__free_source_line(sym, len);
1138
1139         disasm__purge(&symbol__annotation(sym)->src->source);
1140
1141         return 0;
1142 }