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