Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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 <errno.h>
11#include <inttypes.h>
12#include "util.h"
13#include "ui/ui.h"
14#include "sort.h"
15#include "build-id.h"
16#include "color.h"
17#include "config.h"
18#include "cache.h"
19#include "symbol.h"
20#include "units.h"
21#include "debug.h"
22#include "annotate.h"
23#include "evsel.h"
24#include "evlist.h"
25#include "block-range.h"
26#include "string2.h"
27#include "arch/common.h"
28#include <regex.h>
29#include <pthread.h>
30#include <linux/bitops.h>
31#include <linux/kernel.h>
32
33/* FIXME: For the HE_COLORSET */
34#include "ui/browser.h"
35
36/*
37 * FIXME: Using the same values as slang.h,
38 * but that header may not be available everywhere
39 */
40#define LARROW_CHAR ((unsigned char)',')
41#define RARROW_CHAR ((unsigned char)'+')
42#define DARROW_CHAR ((unsigned char)'.')
43#define UARROW_CHAR ((unsigned char)'-')
44
45#include "sane_ctype.h"
46
47struct annotation_options annotation__default_options = {
48 .use_offset = true,
49 .jump_arrows = true,
50 .annotate_src = true,
51 .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS,
52 .percent_type = PERCENT_PERIOD_LOCAL,
53};
54
55static regex_t file_lineno;
56
57static struct ins_ops *ins__find(struct arch *arch, const char *name);
58static void ins__sort(struct arch *arch);
59static int disasm_line__parse(char *line, const char **namep, char **rawp);
60
61struct arch {
62 const char *name;
63 struct ins *instructions;
64 size_t nr_instructions;
65 size_t nr_instructions_allocated;
66 struct ins_ops *(*associate_instruction_ops)(struct arch *arch, const char *name);
67 bool sorted_instructions;
68 bool initialized;
69 void *priv;
70 unsigned int model;
71 unsigned int family;
72 int (*init)(struct arch *arch, char *cpuid);
73 bool (*ins_is_fused)(struct arch *arch, const char *ins1,
74 const char *ins2);
75 struct {
76 char comment_char;
77 char skip_functions_char;
78 } objdump;
79};
80
81static struct ins_ops call_ops;
82static struct ins_ops dec_ops;
83static struct ins_ops jump_ops;
84static struct ins_ops mov_ops;
85static struct ins_ops nop_ops;
86static struct ins_ops lock_ops;
87static struct ins_ops ret_ops;
88
89static int arch__grow_instructions(struct arch *arch)
90{
91 struct ins *new_instructions;
92 size_t new_nr_allocated;
93
94 if (arch->nr_instructions_allocated == 0 && arch->instructions)
95 goto grow_from_non_allocated_table;
96
97 new_nr_allocated = arch->nr_instructions_allocated + 128;
98 new_instructions = realloc(arch->instructions, new_nr_allocated * sizeof(struct ins));
99 if (new_instructions == NULL)
100 return -1;
101
102out_update_instructions:
103 arch->instructions = new_instructions;
104 arch->nr_instructions_allocated = new_nr_allocated;
105 return 0;
106
107grow_from_non_allocated_table:
108 new_nr_allocated = arch->nr_instructions + 128;
109 new_instructions = calloc(new_nr_allocated, sizeof(struct ins));
110 if (new_instructions == NULL)
111 return -1;
112
113 memcpy(new_instructions, arch->instructions, arch->nr_instructions);
114 goto out_update_instructions;
115}
116
117static int arch__associate_ins_ops(struct arch* arch, const char *name, struct ins_ops *ops)
118{
119 struct ins *ins;
120
121 if (arch->nr_instructions == arch->nr_instructions_allocated &&
122 arch__grow_instructions(arch))
123 return -1;
124
125 ins = &arch->instructions[arch->nr_instructions];
126 ins->name = strdup(name);
127 if (!ins->name)
128 return -1;
129
130 ins->ops = ops;
131 arch->nr_instructions++;
132
133 ins__sort(arch);
134 return 0;
135}
136
137#include "arch/arm/annotate/instructions.c"
138#include "arch/arm64/annotate/instructions.c"
139#include "arch/x86/annotate/instructions.c"
140#include "arch/powerpc/annotate/instructions.c"
141#include "arch/s390/annotate/instructions.c"
142
143static struct arch architectures[] = {
144 {
145 .name = "arm",
146 .init = arm__annotate_init,
147 },
148 {
149 .name = "arm64",
150 .init = arm64__annotate_init,
151 },
152 {
153 .name = "x86",
154 .init = x86__annotate_init,
155 .instructions = x86__instructions,
156 .nr_instructions = ARRAY_SIZE(x86__instructions),
157 .ins_is_fused = x86__ins_is_fused,
158 .objdump = {
159 .comment_char = '#',
160 },
161 },
162 {
163 .name = "powerpc",
164 .init = powerpc__annotate_init,
165 },
166 {
167 .name = "s390",
168 .init = s390__annotate_init,
169 .objdump = {
170 .comment_char = '#',
171 },
172 },
173};
174
175static void ins__delete(struct ins_operands *ops)
176{
177 if (ops == NULL)
178 return;
179 zfree(&ops->source.raw);
180 zfree(&ops->source.name);
181 zfree(&ops->target.raw);
182 zfree(&ops->target.name);
183}
184
185static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
186 struct ins_operands *ops)
187{
188 return scnprintf(bf, size, "%-6s %s", ins->name, ops->raw);
189}
190
191int ins__scnprintf(struct ins *ins, char *bf, size_t size,
192 struct ins_operands *ops)
193{
194 if (ins->ops->scnprintf)
195 return ins->ops->scnprintf(ins, bf, size, ops);
196
197 return ins__raw_scnprintf(ins, bf, size, ops);
198}
199
200bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
201{
202 if (!arch || !arch->ins_is_fused)
203 return false;
204
205 return arch->ins_is_fused(arch, ins1, ins2);
206}
207
208static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
209{
210 char *endptr, *tok, *name;
211 struct map *map = ms->map;
212 struct addr_map_symbol target = {
213 .map = map,
214 };
215
216 ops->target.addr = strtoull(ops->raw, &endptr, 16);
217
218 name = strchr(endptr, '<');
219 if (name == NULL)
220 goto indirect_call;
221
222 name++;
223
224 if (arch->objdump.skip_functions_char &&
225 strchr(name, arch->objdump.skip_functions_char))
226 return -1;
227
228 tok = strchr(name, '>');
229 if (tok == NULL)
230 return -1;
231
232 *tok = '\0';
233 ops->target.name = strdup(name);
234 *tok = '>';
235
236 if (ops->target.name == NULL)
237 return -1;
238find_target:
239 target.addr = map__objdump_2mem(map, ops->target.addr);
240
241 if (map_groups__find_ams(&target) == 0 &&
242 map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
243 ops->target.sym = target.sym;
244
245 return 0;
246
247indirect_call:
248 tok = strchr(endptr, '*');
249 if (tok != NULL)
250 ops->target.addr = strtoull(tok + 1, NULL, 16);
251 goto find_target;
252}
253
254static int call__scnprintf(struct ins *ins, char *bf, size_t size,
255 struct ins_operands *ops)
256{
257 if (ops->target.sym)
258 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
259
260 if (ops->target.addr == 0)
261 return ins__raw_scnprintf(ins, bf, size, ops);
262
263 if (ops->target.name)
264 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.name);
265
266 return scnprintf(bf, size, "%-6s *%" PRIx64, ins->name, ops->target.addr);
267}
268
269static struct ins_ops call_ops = {
270 .parse = call__parse,
271 .scnprintf = call__scnprintf,
272};
273
274bool ins__is_call(const struct ins *ins)
275{
276 return ins->ops == &call_ops || ins->ops == &s390_call_ops;
277}
278
279static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms)
280{
281 struct map *map = ms->map;
282 struct symbol *sym = ms->sym;
283 struct addr_map_symbol target = {
284 .map = map,
285 };
286 const char *c = strchr(ops->raw, ',');
287 u64 start, end;
288 /*
289 * Examples of lines to parse for the _cpp_lex_token@@Base
290 * function:
291 *
292 * 1159e6c: jne 115aa32 <_cpp_lex_token@@Base+0xf92>
293 * 1159e8b: jne c469be <cpp_named_operator2name@@Base+0xa72>
294 *
295 * The first is a jump to an offset inside the same function,
296 * the second is to another function, i.e. that 0xa72 is an
297 * offset in the cpp_named_operator2name@@base function.
298 */
299 /*
300 * skip over possible up to 2 operands to get to address, e.g.:
301 * tbnz w0, #26, ffff0000083cd190 <security_file_permission+0xd0>
302 */
303 if (c++ != NULL) {
304 ops->target.addr = strtoull(c, NULL, 16);
305 if (!ops->target.addr) {
306 c = strchr(c, ',');
307 if (c++ != NULL)
308 ops->target.addr = strtoull(c, NULL, 16);
309 }
310 } else {
311 ops->target.addr = strtoull(ops->raw, NULL, 16);
312 }
313
314 target.addr = map__objdump_2mem(map, ops->target.addr);
315 start = map->unmap_ip(map, sym->start),
316 end = map->unmap_ip(map, sym->end);
317
318 ops->target.outside = target.addr < start || target.addr > end;
319
320 /*
321 * FIXME: things like this in _cpp_lex_token (gcc's cc1 program):
322
323 cpp_named_operator2name@@Base+0xa72
324
325 * Point to a place that is after the cpp_named_operator2name
326 * boundaries, i.e. in the ELF symbol table for cc1
327 * cpp_named_operator2name is marked as being 32-bytes long, but it in
328 * fact is much larger than that, so we seem to need a symbols__find()
329 * routine that looks for >= current->start and < next_symbol->start,
330 * possibly just for C++ objects?
331 *
332 * For now lets just make some progress by marking jumps to outside the
333 * current function as call like.
334 *
335 * Actual navigation will come next, with further understanding of how
336 * the symbol searching and disassembly should be done.
337 */
338 if (map_groups__find_ams(&target) == 0 &&
339 map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr)
340 ops->target.sym = target.sym;
341
342 if (!ops->target.outside) {
343 ops->target.offset = target.addr - start;
344 ops->target.offset_avail = true;
345 } else {
346 ops->target.offset_avail = false;
347 }
348
349 return 0;
350}
351
352static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
353 struct ins_operands *ops)
354{
355 const char *c;
356
357 if (!ops->target.addr || ops->target.offset < 0)
358 return ins__raw_scnprintf(ins, bf, size, ops);
359
360 if (ops->target.outside && ops->target.sym != NULL)
361 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
362
363 c = strchr(ops->raw, ',');
364 if (c != NULL) {
365 const char *c2 = strchr(c + 1, ',');
366
367 /* check for 3-op insn */
368 if (c2 != NULL)
369 c = c2;
370 c++;
371
372 /* mirror arch objdump's space-after-comma style */
373 if (*c == ' ')
374 c++;
375 }
376
377 return scnprintf(bf, size, "%-6s %.*s%" PRIx64,
378 ins->name, c ? c - ops->raw : 0, ops->raw,
379 ops->target.offset);
380}
381
382static struct ins_ops jump_ops = {
383 .parse = jump__parse,
384 .scnprintf = jump__scnprintf,
385};
386
387bool ins__is_jump(const struct ins *ins)
388{
389 return ins->ops == &jump_ops;
390}
391
392static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
393{
394 char *endptr, *name, *t;
395
396 if (strstr(raw, "(%rip)") == NULL)
397 return 0;
398
399 *addrp = strtoull(comment, &endptr, 16);
400 if (endptr == comment)
401 return 0;
402 name = strchr(endptr, '<');
403 if (name == NULL)
404 return -1;
405
406 name++;
407
408 t = strchr(name, '>');
409 if (t == NULL)
410 return 0;
411
412 *t = '\0';
413 *namep = strdup(name);
414 *t = '>';
415
416 return 0;
417}
418
419static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
420{
421 ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
422 if (ops->locked.ops == NULL)
423 return 0;
424
425 if (disasm_line__parse(ops->raw, &ops->locked.ins.name, &ops->locked.ops->raw) < 0)
426 goto out_free_ops;
427
428 ops->locked.ins.ops = ins__find(arch, ops->locked.ins.name);
429
430 if (ops->locked.ins.ops == NULL)
431 goto out_free_ops;
432
433 if (ops->locked.ins.ops->parse &&
434 ops->locked.ins.ops->parse(arch, ops->locked.ops, ms) < 0)
435 goto out_free_ops;
436
437 return 0;
438
439out_free_ops:
440 zfree(&ops->locked.ops);
441 return 0;
442}
443
444static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
445 struct ins_operands *ops)
446{
447 int printed;
448
449 if (ops->locked.ins.ops == NULL)
450 return ins__raw_scnprintf(ins, bf, size, ops);
451
452 printed = scnprintf(bf, size, "%-6s ", ins->name);
453 return printed + ins__scnprintf(&ops->locked.ins, bf + printed,
454 size - printed, ops->locked.ops);
455}
456
457static void lock__delete(struct ins_operands *ops)
458{
459 struct ins *ins = &ops->locked.ins;
460
461 if (ins->ops && ins->ops->free)
462 ins->ops->free(ops->locked.ops);
463 else
464 ins__delete(ops->locked.ops);
465
466 zfree(&ops->locked.ops);
467 zfree(&ops->target.raw);
468 zfree(&ops->target.name);
469}
470
471static struct ins_ops lock_ops = {
472 .free = lock__delete,
473 .parse = lock__parse,
474 .scnprintf = lock__scnprintf,
475};
476
477static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
478{
479 char *s = strchr(ops->raw, ','), *target, *comment, prev;
480
481 if (s == NULL)
482 return -1;
483
484 *s = '\0';
485 ops->source.raw = strdup(ops->raw);
486 *s = ',';
487
488 if (ops->source.raw == NULL)
489 return -1;
490
491 target = ++s;
492 comment = strchr(s, arch->objdump.comment_char);
493
494 if (comment != NULL)
495 s = comment - 1;
496 else
497 s = strchr(s, '\0') - 1;
498
499 while (s > target && isspace(s[0]))
500 --s;
501 s++;
502 prev = *s;
503 *s = '\0';
504
505 ops->target.raw = strdup(target);
506 *s = prev;
507
508 if (ops->target.raw == NULL)
509 goto out_free_source;
510
511 if (comment == NULL)
512 return 0;
513
514 comment = ltrim(comment);
515 comment__symbol(ops->source.raw, comment + 1, &ops->source.addr, &ops->source.name);
516 comment__symbol(ops->target.raw, comment + 1, &ops->target.addr, &ops->target.name);
517
518 return 0;
519
520out_free_source:
521 zfree(&ops->source.raw);
522 return -1;
523}
524
525static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
526 struct ins_operands *ops)
527{
528 return scnprintf(bf, size, "%-6s %s,%s", ins->name,
529 ops->source.name ?: ops->source.raw,
530 ops->target.name ?: ops->target.raw);
531}
532
533static struct ins_ops mov_ops = {
534 .parse = mov__parse,
535 .scnprintf = mov__scnprintf,
536};
537
538static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
539{
540 char *target, *comment, *s, prev;
541
542 target = s = ops->raw;
543
544 while (s[0] != '\0' && !isspace(s[0]))
545 ++s;
546 prev = *s;
547 *s = '\0';
548
549 ops->target.raw = strdup(target);
550 *s = prev;
551
552 if (ops->target.raw == NULL)
553 return -1;
554
555 comment = strchr(s, arch->objdump.comment_char);
556 if (comment == NULL)
557 return 0;
558
559 comment = ltrim(comment);
560 comment__symbol(ops->target.raw, comment + 1, &ops->target.addr, &ops->target.name);
561
562 return 0;
563}
564
565static int dec__scnprintf(struct ins *ins, char *bf, size_t size,
566 struct ins_operands *ops)
567{
568 return scnprintf(bf, size, "%-6s %s", ins->name,
569 ops->target.name ?: ops->target.raw);
570}
571
572static struct ins_ops dec_ops = {
573 .parse = dec__parse,
574 .scnprintf = dec__scnprintf,
575};
576
577static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size,
578 struct ins_operands *ops __maybe_unused)
579{
580 return scnprintf(bf, size, "%-6s", "nop");
581}
582
583static struct ins_ops nop_ops = {
584 .scnprintf = nop__scnprintf,
585};
586
587static struct ins_ops ret_ops = {
588 .scnprintf = ins__raw_scnprintf,
589};
590
591bool ins__is_ret(const struct ins *ins)
592{
593 return ins->ops == &ret_ops;
594}
595
596bool ins__is_lock(const struct ins *ins)
597{
598 return ins->ops == &lock_ops;
599}
600
601static int ins__key_cmp(const void *name, const void *insp)
602{
603 const struct ins *ins = insp;
604
605 return strcmp(name, ins->name);
606}
607
608static int ins__cmp(const void *a, const void *b)
609{
610 const struct ins *ia = a;
611 const struct ins *ib = b;
612
613 return strcmp(ia->name, ib->name);
614}
615
616static void ins__sort(struct arch *arch)
617{
618 const int nmemb = arch->nr_instructions;
619
620 qsort(arch->instructions, nmemb, sizeof(struct ins), ins__cmp);
621}
622
623static struct ins_ops *__ins__find(struct arch *arch, const char *name)
624{
625 struct ins *ins;
626 const int nmemb = arch->nr_instructions;
627
628 if (!arch->sorted_instructions) {
629 ins__sort(arch);
630 arch->sorted_instructions = true;
631 }
632
633 ins = bsearch(name, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp);
634 return ins ? ins->ops : NULL;
635}
636
637static struct ins_ops *ins__find(struct arch *arch, const char *name)
638{
639 struct ins_ops *ops = __ins__find(arch, name);
640
641 if (!ops && arch->associate_instruction_ops)
642 ops = arch->associate_instruction_ops(arch, name);
643
644 return ops;
645}
646
647static int arch__key_cmp(const void *name, const void *archp)
648{
649 const struct arch *arch = archp;
650
651 return strcmp(name, arch->name);
652}
653
654static int arch__cmp(const void *a, const void *b)
655{
656 const struct arch *aa = a;
657 const struct arch *ab = b;
658
659 return strcmp(aa->name, ab->name);
660}
661
662static void arch__sort(void)
663{
664 const int nmemb = ARRAY_SIZE(architectures);
665
666 qsort(architectures, nmemb, sizeof(struct arch), arch__cmp);
667}
668
669static struct arch *arch__find(const char *name)
670{
671 const int nmemb = ARRAY_SIZE(architectures);
672 static bool sorted;
673
674 if (!sorted) {
675 arch__sort();
676 sorted = true;
677 }
678
679 return bsearch(name, architectures, nmemb, sizeof(struct arch), arch__key_cmp);
680}
681
682static struct annotated_source *annotated_source__new(void)
683{
684 struct annotated_source *src = zalloc(sizeof(*src));
685
686 if (src != NULL)
687 INIT_LIST_HEAD(&src->source);
688
689 return src;
690}
691
692static __maybe_unused void annotated_source__delete(struct annotated_source *src)
693{
694 if (src == NULL)
695 return;
696 zfree(&src->histograms);
697 zfree(&src->cycles_hist);
698 free(src);
699}
700
701static int annotated_source__alloc_histograms(struct annotated_source *src,
702 size_t size, int nr_hists)
703{
704 size_t sizeof_sym_hist;
705
706 /*
707 * Add buffer of one element for zero length symbol.
708 * When sample is taken from first instruction of
709 * zero length symbol, perf still resolves it and
710 * shows symbol name in perf report and allows to
711 * annotate it.
712 */
713 if (size == 0)
714 size = 1;
715
716 /* Check for overflow when calculating sizeof_sym_hist */
717 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(struct sym_hist_entry))
718 return -1;
719
720 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(struct sym_hist_entry));
721
722 /* Check for overflow in zalloc argument */
723 if (sizeof_sym_hist > SIZE_MAX / nr_hists)
724 return -1;
725
726 src->sizeof_sym_hist = sizeof_sym_hist;
727 src->nr_histograms = nr_hists;
728 src->histograms = calloc(nr_hists, sizeof_sym_hist) ;
729 return src->histograms ? 0 : -1;
730}
731
732/* The cycles histogram is lazily allocated. */
733static int symbol__alloc_hist_cycles(struct symbol *sym)
734{
735 struct annotation *notes = symbol__annotation(sym);
736 const size_t size = symbol__size(sym);
737
738 notes->src->cycles_hist = calloc(size, sizeof(struct cyc_hist));
739 if (notes->src->cycles_hist == NULL)
740 return -1;
741 return 0;
742}
743
744void symbol__annotate_zero_histograms(struct symbol *sym)
745{
746 struct annotation *notes = symbol__annotation(sym);
747
748 pthread_mutex_lock(¬es->lock);
749 if (notes->src != NULL) {
750 memset(notes->src->histograms, 0,
751 notes->src->nr_histograms * notes->src->sizeof_sym_hist);
752 if (notes->src->cycles_hist)
753 memset(notes->src->cycles_hist, 0,
754 symbol__size(sym) * sizeof(struct cyc_hist));
755 }
756 pthread_mutex_unlock(¬es->lock);
757}
758
759static int __symbol__account_cycles(struct cyc_hist *ch,
760 u64 start,
761 unsigned offset, unsigned cycles,
762 unsigned have_start)
763{
764 /*
765 * For now we can only account one basic block per
766 * final jump. But multiple could be overlapping.
767 * Always account the longest one. So when
768 * a shorter one has been already seen throw it away.
769 *
770 * We separately always account the full cycles.
771 */
772 ch[offset].num_aggr++;
773 ch[offset].cycles_aggr += cycles;
774
775 if (cycles > ch[offset].cycles_max)
776 ch[offset].cycles_max = cycles;
777
778 if (ch[offset].cycles_min) {
779 if (cycles && cycles < ch[offset].cycles_min)
780 ch[offset].cycles_min = cycles;
781 } else
782 ch[offset].cycles_min = cycles;
783
784 if (!have_start && ch[offset].have_start)
785 return 0;
786 if (ch[offset].num) {
787 if (have_start && (!ch[offset].have_start ||
788 ch[offset].start > start)) {
789 ch[offset].have_start = 0;
790 ch[offset].cycles = 0;
791 ch[offset].num = 0;
792 if (ch[offset].reset < 0xffff)
793 ch[offset].reset++;
794 } else if (have_start &&
795 ch[offset].start < start)
796 return 0;
797 }
798 ch[offset].have_start = have_start;
799 ch[offset].start = start;
800 ch[offset].cycles += cycles;
801 ch[offset].num++;
802 return 0;
803}
804
805static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
806 struct annotated_source *src, int evidx, u64 addr,
807 struct perf_sample *sample)
808{
809 unsigned offset;
810 struct sym_hist *h;
811
812 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
813
814 if ((addr < sym->start || addr >= sym->end) &&
815 (addr != sym->end || sym->start != sym->end)) {
816 pr_debug("%s(%d): ERANGE! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 "\n",
817 __func__, __LINE__, sym->name, sym->start, addr, sym->end);
818 return -ERANGE;
819 }
820
821 offset = addr - sym->start;
822 h = annotated_source__histogram(src, evidx);
823 if (h == NULL) {
824 pr_debug("%s(%d): ENOMEM! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 ", func: %d\n",
825 __func__, __LINE__, sym->name, sym->start, addr, sym->end, sym->type == STT_FUNC);
826 return -ENOMEM;
827 }
828 h->nr_samples++;
829 h->addr[offset].nr_samples++;
830 h->period += sample->period;
831 h->addr[offset].period += sample->period;
832
833 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
834 ", evidx=%d] => nr_samples: %" PRIu64 ", period: %" PRIu64 "\n",
835 sym->start, sym->name, addr, addr - sym->start, evidx,
836 h->addr[offset].nr_samples, h->addr[offset].period);
837 return 0;
838}
839
840static struct cyc_hist *symbol__cycles_hist(struct symbol *sym)
841{
842 struct annotation *notes = symbol__annotation(sym);
843
844 if (notes->src == NULL) {
845 notes->src = annotated_source__new();
846 if (notes->src == NULL)
847 return NULL;
848 goto alloc_cycles_hist;
849 }
850
851 if (!notes->src->cycles_hist) {
852alloc_cycles_hist:
853 symbol__alloc_hist_cycles(sym);
854 }
855
856 return notes->src->cycles_hist;
857}
858
859struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists)
860{
861 struct annotation *notes = symbol__annotation(sym);
862
863 if (notes->src == NULL) {
864 notes->src = annotated_source__new();
865 if (notes->src == NULL)
866 return NULL;
867 goto alloc_histograms;
868 }
869
870 if (notes->src->histograms == NULL) {
871alloc_histograms:
872 annotated_source__alloc_histograms(notes->src, symbol__size(sym),
873 nr_hists);
874 }
875
876 return notes->src;
877}
878
879static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
880 struct perf_evsel *evsel, u64 addr,
881 struct perf_sample *sample)
882{
883 struct annotated_source *src;
884
885 if (sym == NULL)
886 return 0;
887 src = symbol__hists(sym, evsel->evlist->nr_entries);
888 if (src == NULL)
889 return -ENOMEM;
890 return __symbol__inc_addr_samples(sym, map, src, evsel->idx, addr, sample);
891}
892
893static int symbol__account_cycles(u64 addr, u64 start,
894 struct symbol *sym, unsigned cycles)
895{
896 struct cyc_hist *cycles_hist;
897 unsigned offset;
898
899 if (sym == NULL)
900 return 0;
901 cycles_hist = symbol__cycles_hist(sym);
902 if (cycles_hist == NULL)
903 return -ENOMEM;
904 if (addr < sym->start || addr >= sym->end)
905 return -ERANGE;
906
907 if (start) {
908 if (start < sym->start || start >= sym->end)
909 return -ERANGE;
910 if (start >= addr)
911 start = 0;
912 }
913 offset = addr - sym->start;
914 return __symbol__account_cycles(cycles_hist,
915 start ? start - sym->start : 0,
916 offset, cycles,
917 !!start);
918}
919
920int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
921 struct addr_map_symbol *start,
922 unsigned cycles)
923{
924 u64 saddr = 0;
925 int err;
926
927 if (!cycles)
928 return 0;
929
930 /*
931 * Only set start when IPC can be computed. We can only
932 * compute it when the basic block is completely in a single
933 * function.
934 * Special case the case when the jump is elsewhere, but
935 * it starts on the function start.
936 */
937 if (start &&
938 (start->sym == ams->sym ||
939 (ams->sym &&
940 start->addr == ams->sym->start + ams->map->start)))
941 saddr = start->al_addr;
942 if (saddr == 0)
943 pr_debug2("BB with bad start: addr %"PRIx64" start %"PRIx64" sym %"PRIx64" saddr %"PRIx64"\n",
944 ams->addr,
945 start ? start->addr : 0,
946 ams->sym ? ams->sym->start + ams->map->start : 0,
947 saddr);
948 err = symbol__account_cycles(ams->al_addr, saddr, ams->sym, cycles);
949 if (err)
950 pr_debug2("account_cycles failed %d\n", err);
951 return err;
952}
953
954static unsigned annotation__count_insn(struct annotation *notes, u64 start, u64 end)
955{
956 unsigned n_insn = 0;
957 u64 offset;
958
959 for (offset = start; offset <= end; offset++) {
960 if (notes->offsets[offset])
961 n_insn++;
962 }
963 return n_insn;
964}
965
966static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 end, struct cyc_hist *ch)
967{
968 unsigned n_insn;
969 u64 offset;
970
971 n_insn = annotation__count_insn(notes, start, end);
972 if (n_insn && ch->num && ch->cycles) {
973 float ipc = n_insn / ((double)ch->cycles / (double)ch->num);
974
975 /* Hide data when there are too many overlaps. */
976 if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2)
977 return;
978
979 for (offset = start; offset <= end; offset++) {
980 struct annotation_line *al = notes->offsets[offset];
981
982 if (al)
983 al->ipc = ipc;
984 }
985 }
986}
987
988void annotation__compute_ipc(struct annotation *notes, size_t size)
989{
990 u64 offset;
991
992 if (!notes->src || !notes->src->cycles_hist)
993 return;
994
995 pthread_mutex_lock(¬es->lock);
996 for (offset = 0; offset < size; ++offset) {
997 struct cyc_hist *ch;
998
999 ch = ¬es->src->cycles_hist[offset];
1000 if (ch && ch->cycles) {
1001 struct annotation_line *al;
1002
1003 if (ch->have_start)
1004 annotation__count_and_fill(notes, ch->start, offset, ch);
1005 al = notes->offsets[offset];
1006 if (al && ch->num_aggr) {
1007 al->cycles = ch->cycles_aggr / ch->num_aggr;
1008 al->cycles_max = ch->cycles_max;
1009 al->cycles_min = ch->cycles_min;
1010 }
1011 notes->have_cycles = true;
1012 }
1013 }
1014 pthread_mutex_unlock(¬es->lock);
1015}
1016
1017int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
1018 struct perf_evsel *evsel)
1019{
1020 return symbol__inc_addr_samples(ams->sym, ams->map, evsel, ams->al_addr, sample);
1021}
1022
1023int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
1024 struct perf_evsel *evsel, u64 ip)
1025{
1026 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evsel, ip, sample);
1027}
1028
1029static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms)
1030{
1031 dl->ins.ops = ins__find(arch, dl->ins.name);
1032
1033 if (!dl->ins.ops)
1034 return;
1035
1036 if (dl->ins.ops->parse && dl->ins.ops->parse(arch, &dl->ops, ms) < 0)
1037 dl->ins.ops = NULL;
1038}
1039
1040static int disasm_line__parse(char *line, const char **namep, char **rawp)
1041{
1042 char tmp, *name = ltrim(line);
1043
1044 if (name[0] == '\0')
1045 return -1;
1046
1047 *rawp = name + 1;
1048
1049 while ((*rawp)[0] != '\0' && !isspace((*rawp)[0]))
1050 ++*rawp;
1051
1052 tmp = (*rawp)[0];
1053 (*rawp)[0] = '\0';
1054 *namep = strdup(name);
1055
1056 if (*namep == NULL)
1057 goto out_free_name;
1058
1059 (*rawp)[0] = tmp;
1060 *rawp = ltrim(*rawp);
1061
1062 return 0;
1063
1064out_free_name:
1065 free((void *)namep);
1066 *namep = NULL;
1067 return -1;
1068}
1069
1070struct annotate_args {
1071 size_t privsize;
1072 struct arch *arch;
1073 struct map_symbol ms;
1074 struct perf_evsel *evsel;
1075 struct annotation_options *options;
1076 s64 offset;
1077 char *line;
1078 int line_nr;
1079};
1080
1081static void annotation_line__delete(struct annotation_line *al)
1082{
1083 void *ptr = (void *) al - al->privsize;
1084
1085 free_srcline(al->path);
1086 zfree(&al->line);
1087 free(ptr);
1088}
1089
1090/*
1091 * Allocating the annotation line data with following
1092 * structure:
1093 *
1094 * --------------------------------------
1095 * private space | struct annotation_line
1096 * --------------------------------------
1097 *
1098 * Size of the private space is stored in 'struct annotation_line'.
1099 *
1100 */
1101static struct annotation_line *
1102annotation_line__new(struct annotate_args *args, size_t privsize)
1103{
1104 struct annotation_line *al;
1105 struct perf_evsel *evsel = args->evsel;
1106 size_t size = privsize + sizeof(*al);
1107 int nr = 1;
1108
1109 if (perf_evsel__is_group_event(evsel))
1110 nr = evsel->nr_members;
1111
1112 size += sizeof(al->data[0]) * nr;
1113
1114 al = zalloc(size);
1115 if (al) {
1116 al = (void *) al + privsize;
1117 al->privsize = privsize;
1118 al->offset = args->offset;
1119 al->line = strdup(args->line);
1120 al->line_nr = args->line_nr;
1121 al->data_nr = nr;
1122 }
1123
1124 return al;
1125}
1126
1127/*
1128 * Allocating the disasm annotation line data with
1129 * following structure:
1130 *
1131 * ------------------------------------------------------------
1132 * privsize space | struct disasm_line | struct annotation_line
1133 * ------------------------------------------------------------
1134 *
1135 * We have 'struct annotation_line' member as last member
1136 * of 'struct disasm_line' to have an easy access.
1137 *
1138 */
1139static struct disasm_line *disasm_line__new(struct annotate_args *args)
1140{
1141 struct disasm_line *dl = NULL;
1142 struct annotation_line *al;
1143 size_t privsize = args->privsize + offsetof(struct disasm_line, al);
1144
1145 al = annotation_line__new(args, privsize);
1146 if (al != NULL) {
1147 dl = disasm_line(al);
1148
1149 if (dl->al.line == NULL)
1150 goto out_delete;
1151
1152 if (args->offset != -1) {
1153 if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
1154 goto out_free_line;
1155
1156 disasm_line__init_ins(dl, args->arch, &args->ms);
1157 }
1158 }
1159
1160 return dl;
1161
1162out_free_line:
1163 zfree(&dl->al.line);
1164out_delete:
1165 free(dl);
1166 return NULL;
1167}
1168
1169void disasm_line__free(struct disasm_line *dl)
1170{
1171 if (dl->ins.ops && dl->ins.ops->free)
1172 dl->ins.ops->free(&dl->ops);
1173 else
1174 ins__delete(&dl->ops);
1175 free((void *)dl->ins.name);
1176 dl->ins.name = NULL;
1177 annotation_line__delete(&dl->al);
1178}
1179
1180int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw)
1181{
1182 if (raw || !dl->ins.ops)
1183 return scnprintf(bf, size, "%-6s %s", dl->ins.name, dl->ops.raw);
1184
1185 return ins__scnprintf(&dl->ins, bf, size, &dl->ops);
1186}
1187
1188static void annotation_line__add(struct annotation_line *al, struct list_head *head)
1189{
1190 list_add_tail(&al->node, head);
1191}
1192
1193struct annotation_line *
1194annotation_line__next(struct annotation_line *pos, struct list_head *head)
1195{
1196 list_for_each_entry_continue(pos, head, node)
1197 if (pos->offset >= 0)
1198 return pos;
1199
1200 return NULL;
1201}
1202
1203static const char *annotate__address_color(struct block_range *br)
1204{
1205 double cov = block_range__coverage(br);
1206
1207 if (cov >= 0) {
1208 /* mark red for >75% coverage */
1209 if (cov > 0.75)
1210 return PERF_COLOR_RED;
1211
1212 /* mark dull for <1% coverage */
1213 if (cov < 0.01)
1214 return PERF_COLOR_NORMAL;
1215 }
1216
1217 return PERF_COLOR_MAGENTA;
1218}
1219
1220static const char *annotate__asm_color(struct block_range *br)
1221{
1222 double cov = block_range__coverage(br);
1223
1224 if (cov >= 0) {
1225 /* mark dull for <1% coverage */
1226 if (cov < 0.01)
1227 return PERF_COLOR_NORMAL;
1228 }
1229
1230 return PERF_COLOR_BLUE;
1231}
1232
1233static void annotate__branch_printf(struct block_range *br, u64 addr)
1234{
1235 bool emit_comment = true;
1236
1237 if (!br)
1238 return;
1239
1240#if 1
1241 if (br->is_target && br->start == addr) {
1242 struct block_range *branch = br;
1243 double p;
1244
1245 /*
1246 * Find matching branch to our target.
1247 */
1248 while (!branch->is_branch)
1249 branch = block_range__next(branch);
1250
1251 p = 100 *(double)br->entry / branch->coverage;
1252
1253 if (p > 0.1) {
1254 if (emit_comment) {
1255 emit_comment = false;
1256 printf("\t#");
1257 }
1258
1259 /*
1260 * The percentage of coverage joined at this target in relation
1261 * to the next branch.
1262 */
1263 printf(" +%.2f%%", p);
1264 }
1265 }
1266#endif
1267 if (br->is_branch && br->end == addr) {
1268 double p = 100*(double)br->taken / br->coverage;
1269
1270 if (p > 0.1) {
1271 if (emit_comment) {
1272 emit_comment = false;
1273 printf("\t#");
1274 }
1275
1276 /*
1277 * The percentage of coverage leaving at this branch, and
1278 * its prediction ratio.
1279 */
1280 printf(" -%.2f%% (p:%.2f%%)", p, 100*(double)br->pred / br->taken);
1281 }
1282 }
1283}
1284
1285static int disasm_line__print(struct disasm_line *dl, u64 start, int addr_fmt_width)
1286{
1287 s64 offset = dl->al.offset;
1288 const u64 addr = start + offset;
1289 struct block_range *br;
1290
1291 br = block_range__find(addr);
1292 color_fprintf(stdout, annotate__address_color(br), " %*" PRIx64 ":", addr_fmt_width, addr);
1293 color_fprintf(stdout, annotate__asm_color(br), "%s", dl->al.line);
1294 annotate__branch_printf(br, addr);
1295 return 0;
1296}
1297
1298static int
1299annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start,
1300 struct perf_evsel *evsel, u64 len, int min_pcnt, int printed,
1301 int max_lines, struct annotation_line *queue, int addr_fmt_width,
1302 int percent_type)
1303{
1304 struct disasm_line *dl = container_of(al, struct disasm_line, al);
1305 static const char *prev_line;
1306 static const char *prev_color;
1307
1308 if (al->offset != -1) {
1309 double max_percent = 0.0;
1310 int i, nr_percent = 1;
1311 const char *color;
1312 struct annotation *notes = symbol__annotation(sym);
1313
1314 for (i = 0; i < al->data_nr; i++) {
1315 double percent;
1316
1317 percent = annotation_data__percent(&al->data[i],
1318 percent_type);
1319
1320 if (percent > max_percent)
1321 max_percent = percent;
1322 }
1323
1324 if (al->data_nr > nr_percent)
1325 nr_percent = al->data_nr;
1326
1327 if (max_percent < min_pcnt)
1328 return -1;
1329
1330 if (max_lines && printed >= max_lines)
1331 return 1;
1332
1333 if (queue != NULL) {
1334 list_for_each_entry_from(queue, ¬es->src->source, node) {
1335 if (queue == al)
1336 break;
1337 annotation_line__print(queue, sym, start, evsel, len,
1338 0, 0, 1, NULL, addr_fmt_width,
1339 percent_type);
1340 }
1341 }
1342
1343 color = get_percent_color(max_percent);
1344
1345 /*
1346 * Also color the filename and line if needed, with
1347 * the same color than the percentage. Don't print it
1348 * twice for close colored addr with the same filename:line
1349 */
1350 if (al->path) {
1351 if (!prev_line || strcmp(prev_line, al->path)
1352 || color != prev_color) {
1353 color_fprintf(stdout, color, " %s", al->path);
1354 prev_line = al->path;
1355 prev_color = color;
1356 }
1357 }
1358
1359 for (i = 0; i < nr_percent; i++) {
1360 struct annotation_data *data = &al->data[i];
1361 double percent;
1362
1363 percent = annotation_data__percent(data, percent_type);
1364 color = get_percent_color(percent);
1365
1366 if (symbol_conf.show_total_period)
1367 color_fprintf(stdout, color, " %11" PRIu64,
1368 data->he.period);
1369 else if (symbol_conf.show_nr_samples)
1370 color_fprintf(stdout, color, " %7" PRIu64,
1371 data->he.nr_samples);
1372 else
1373 color_fprintf(stdout, color, " %7.2f", percent);
1374 }
1375
1376 printf(" : ");
1377
1378 disasm_line__print(dl, start, addr_fmt_width);
1379 printf("\n");
1380 } else if (max_lines && printed >= max_lines)
1381 return 1;
1382 else {
1383 int width = symbol_conf.show_total_period ? 12 : 8;
1384
1385 if (queue)
1386 return -1;
1387
1388 if (perf_evsel__is_group_event(evsel))
1389 width *= evsel->nr_members;
1390
1391 if (!*al->line)
1392 printf(" %*s:\n", width, " ");
1393 else
1394 printf(" %*s: %*s %s\n", width, " ", addr_fmt_width, " ", al->line);
1395 }
1396
1397 return 0;
1398}
1399
1400/*
1401 * symbol__parse_objdump_line() parses objdump output (with -d --no-show-raw)
1402 * which looks like following
1403 *
1404 * 0000000000415500 <_init>:
1405 * 415500: sub $0x8,%rsp
1406 * 415504: mov 0x2f5ad5(%rip),%rax # 70afe0 <_DYNAMIC+0x2f8>
1407 * 41550b: test %rax,%rax
1408 * 41550e: je 415515 <_init+0x15>
1409 * 415510: callq 416e70 <__gmon_start__@plt>
1410 * 415515: add $0x8,%rsp
1411 * 415519: retq
1412 *
1413 * it will be parsed and saved into struct disasm_line as
1414 * <offset> <name> <ops.raw>
1415 *
1416 * The offset will be a relative offset from the start of the symbol and -1
1417 * means that it's not a disassembly line so should be treated differently.
1418 * The ops.raw part will be parsed further according to type of the instruction.
1419 */
1420static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
1421 struct annotate_args *args,
1422 int *line_nr)
1423{
1424 struct map *map = args->ms.map;
1425 struct annotation *notes = symbol__annotation(sym);
1426 struct disasm_line *dl;
1427 char *line = NULL, *parsed_line, *tmp, *tmp2;
1428 size_t line_len;
1429 s64 line_ip, offset = -1;
1430 regmatch_t match[2];
1431
1432 if (getline(&line, &line_len, file) < 0)
1433 return -1;
1434
1435 if (!line)
1436 return -1;
1437
1438 line_ip = -1;
1439 parsed_line = rtrim(line);
1440
1441 /* /filename:linenr ? Save line number and ignore. */
1442 if (regexec(&file_lineno, parsed_line, 2, match, 0) == 0) {
1443 *line_nr = atoi(parsed_line + match[1].rm_so);
1444 return 0;
1445 }
1446
1447 tmp = ltrim(parsed_line);
1448 if (*tmp) {
1449 /*
1450 * Parse hexa addresses followed by ':'
1451 */
1452 line_ip = strtoull(tmp, &tmp2, 16);
1453 if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0')
1454 line_ip = -1;
1455 }
1456
1457 if (line_ip != -1) {
1458 u64 start = map__rip_2objdump(map, sym->start),
1459 end = map__rip_2objdump(map, sym->end);
1460
1461 offset = line_ip - start;
1462 if ((u64)line_ip < start || (u64)line_ip >= end)
1463 offset = -1;
1464 else
1465 parsed_line = tmp2 + 1;
1466 }
1467
1468 args->offset = offset;
1469 args->line = parsed_line;
1470 args->line_nr = *line_nr;
1471 args->ms.sym = sym;
1472
1473 dl = disasm_line__new(args);
1474 free(line);
1475 (*line_nr)++;
1476
1477 if (dl == NULL)
1478 return -1;
1479
1480 if (!disasm_line__has_local_offset(dl)) {
1481 dl->ops.target.offset = dl->ops.target.addr -
1482 map__rip_2objdump(map, sym->start);
1483 dl->ops.target.offset_avail = true;
1484 }
1485
1486 /* kcore has no symbols, so add the call target symbol */
1487 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.sym) {
1488 struct addr_map_symbol target = {
1489 .map = map,
1490 .addr = dl->ops.target.addr,
1491 };
1492
1493 if (!map_groups__find_ams(&target) &&
1494 target.sym->start == target.al_addr)
1495 dl->ops.target.sym = target.sym;
1496 }
1497
1498 annotation_line__add(&dl->al, ¬es->src->source);
1499
1500 return 0;
1501}
1502
1503static __attribute__((constructor)) void symbol__init_regexpr(void)
1504{
1505 regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED);
1506}
1507
1508static void delete_last_nop(struct symbol *sym)
1509{
1510 struct annotation *notes = symbol__annotation(sym);
1511 struct list_head *list = ¬es->src->source;
1512 struct disasm_line *dl;
1513
1514 while (!list_empty(list)) {
1515 dl = list_entry(list->prev, struct disasm_line, al.node);
1516
1517 if (dl->ins.ops) {
1518 if (dl->ins.ops != &nop_ops)
1519 return;
1520 } else {
1521 if (!strstr(dl->al.line, " nop ") &&
1522 !strstr(dl->al.line, " nopl ") &&
1523 !strstr(dl->al.line, " nopw "))
1524 return;
1525 }
1526
1527 list_del(&dl->al.node);
1528 disasm_line__free(dl);
1529 }
1530}
1531
1532int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map,
1533 int errnum, char *buf, size_t buflen)
1534{
1535 struct dso *dso = map->dso;
1536
1537 BUG_ON(buflen == 0);
1538
1539 if (errnum >= 0) {
1540 str_error_r(errnum, buf, buflen);
1541 return 0;
1542 }
1543
1544 switch (errnum) {
1545 case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: {
1546 char bf[SBUILD_ID_SIZE + 15] = " with build id ";
1547 char *build_id_msg = NULL;
1548
1549 if (dso->has_build_id) {
1550 build_id__sprintf(dso->build_id,
1551 sizeof(dso->build_id), bf + 15);
1552 build_id_msg = bf;
1553 }
1554 scnprintf(buf, buflen,
1555 "No vmlinux file%s\nwas found in the path.\n\n"
1556 "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"
1557 "Please use:\n\n"
1558 " perf buildid-cache -vu vmlinux\n\n"
1559 "or:\n\n"
1560 " --vmlinux vmlinux\n", build_id_msg ?: "");
1561 }
1562 break;
1563 default:
1564 scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum);
1565 break;
1566 }
1567
1568 return 0;
1569}
1570
1571static int dso__disassemble_filename(struct dso *dso, char *filename, size_t filename_size)
1572{
1573 char linkname[PATH_MAX];
1574 char *build_id_filename;
1575 char *build_id_path = NULL;
1576 char *pos;
1577
1578 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1579 !dso__is_kcore(dso))
1580 return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
1581
1582 build_id_filename = dso__build_id_filename(dso, NULL, 0, false);
1583 if (build_id_filename) {
1584 __symbol__join_symfs(filename, filename_size, build_id_filename);
1585 free(build_id_filename);
1586 } else {
1587 if (dso->has_build_id)
1588 return ENOMEM;
1589 goto fallback;
1590 }
1591
1592 build_id_path = strdup(filename);
1593 if (!build_id_path)
1594 return -1;
1595
1596 /*
1597 * old style build-id cache has name of XX/XXXXXXX.. while
1598 * new style has XX/XXXXXXX../{elf,kallsyms,vdso}.
1599 * extract the build-id part of dirname in the new style only.
1600 */
1601 pos = strrchr(build_id_path, '/');
1602 if (pos && strlen(pos) < SBUILD_ID_SIZE - 2)
1603 dirname(build_id_path);
1604
1605 if (dso__is_kcore(dso) ||
1606 readlink(build_id_path, linkname, sizeof(linkname)) < 0 ||
1607 strstr(linkname, DSO__NAME_KALLSYMS) ||
1608 access(filename, R_OK)) {
1609fallback:
1610 /*
1611 * If we don't have build-ids or the build-id file isn't in the
1612 * cache, or is just a kallsyms file, well, lets hope that this
1613 * DSO is the same as when 'perf record' ran.
1614 */
1615 __symbol__join_symfs(filename, filename_size, dso->long_name);
1616 }
1617
1618 free(build_id_path);
1619 return 0;
1620}
1621
1622static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1623{
1624 struct annotation_options *opts = args->options;
1625 struct map *map = args->ms.map;
1626 struct dso *dso = map->dso;
1627 char *command;
1628 FILE *file;
1629 char symfs_filename[PATH_MAX];
1630 struct kcore_extract kce;
1631 bool delete_extract = false;
1632 bool decomp = false;
1633 int stdout_fd[2];
1634 int lineno = 0;
1635 int nline;
1636 pid_t pid;
1637 int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));
1638
1639 if (err)
1640 return err;
1641
1642 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
1643 symfs_filename, sym->name, map->unmap_ip(map, sym->start),
1644 map->unmap_ip(map, sym->end));
1645
1646 pr_debug("annotating [%p] %30s : [%p] %30s\n",
1647 dso, dso->long_name, sym, sym->name);
1648
1649 if (dso__is_kcore(dso)) {
1650 kce.kcore_filename = symfs_filename;
1651 kce.addr = map__rip_2objdump(map, sym->start);
1652 kce.offs = sym->start;
1653 kce.len = sym->end - sym->start;
1654 if (!kcore_extract__create(&kce)) {
1655 delete_extract = true;
1656 strlcpy(symfs_filename, kce.extract_filename,
1657 sizeof(symfs_filename));
1658 }
1659 } else if (dso__needs_decompress(dso)) {
1660 char tmp[KMOD_DECOMP_LEN];
1661
1662 if (dso__decompress_kmodule_path(dso, symfs_filename,
1663 tmp, sizeof(tmp)) < 0)
1664 goto out;
1665
1666 decomp = true;
1667 strcpy(symfs_filename, tmp);
1668 }
1669
1670 err = asprintf(&command,
1671 "%s %s%s --start-address=0x%016" PRIx64
1672 " --stop-address=0x%016" PRIx64
1673 " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
1674 opts->objdump_path ?: "objdump",
1675 opts->disassembler_style ? "-M " : "",
1676 opts->disassembler_style ?: "",
1677 map__rip_2objdump(map, sym->start),
1678 map__rip_2objdump(map, sym->end),
1679 opts->show_asm_raw ? "" : "--no-show-raw",
1680 opts->annotate_src ? "-S" : "",
1681 symfs_filename, symfs_filename);
1682
1683 if (err < 0) {
1684 pr_err("Failure allocating memory for the command to run\n");
1685 goto out_remove_tmp;
1686 }
1687
1688 pr_debug("Executing: %s\n", command);
1689
1690 err = -1;
1691 if (pipe(stdout_fd) < 0) {
1692 pr_err("Failure creating the pipe to run %s\n", command);
1693 goto out_free_command;
1694 }
1695
1696 pid = fork();
1697 if (pid < 0) {
1698 pr_err("Failure forking to run %s\n", command);
1699 goto out_close_stdout;
1700 }
1701
1702 if (pid == 0) {
1703 close(stdout_fd[0]);
1704 dup2(stdout_fd[1], 1);
1705 close(stdout_fd[1]);
1706 execl("/bin/sh", "sh", "-c", command, NULL);
1707 perror(command);
1708 exit(-1);
1709 }
1710
1711 close(stdout_fd[1]);
1712
1713 file = fdopen(stdout_fd[0], "r");
1714 if (!file) {
1715 pr_err("Failure creating FILE stream for %s\n", command);
1716 /*
1717 * If we were using debug info should retry with
1718 * original binary.
1719 */
1720 goto out_free_command;
1721 }
1722
1723 nline = 0;
1724 while (!feof(file)) {
1725 /*
1726 * The source code line number (lineno) needs to be kept in
1727 * accross calls to symbol__parse_objdump_line(), so that it
1728 * can associate it with the instructions till the next one.
1729 * See disasm_line__new() and struct disasm_line::line_nr.
1730 */
1731 if (symbol__parse_objdump_line(sym, file, args, &lineno) < 0)
1732 break;
1733 nline++;
1734 }
1735
1736 if (nline == 0)
1737 pr_err("No output from %s\n", command);
1738
1739 /*
1740 * kallsyms does not have symbol sizes so there may a nop at the end.
1741 * Remove it.
1742 */
1743 if (dso__is_kcore(dso))
1744 delete_last_nop(sym);
1745
1746 fclose(file);
1747 err = 0;
1748out_free_command:
1749 free(command);
1750out_remove_tmp:
1751 close(stdout_fd[0]);
1752
1753 if (decomp)
1754 unlink(symfs_filename);
1755
1756 if (delete_extract)
1757 kcore_extract__delete(&kce);
1758out:
1759 return err;
1760
1761out_close_stdout:
1762 close(stdout_fd[1]);
1763 goto out_free_command;
1764}
1765
1766static void calc_percent(struct sym_hist *sym_hist,
1767 struct hists *hists,
1768 struct annotation_data *data,
1769 s64 offset, s64 end)
1770{
1771 unsigned int hits = 0;
1772 u64 period = 0;
1773
1774 while (offset < end) {
1775 hits += sym_hist->addr[offset].nr_samples;
1776 period += sym_hist->addr[offset].period;
1777 ++offset;
1778 }
1779
1780 if (sym_hist->nr_samples) {
1781 data->he.period = period;
1782 data->he.nr_samples = hits;
1783 data->percent[PERCENT_HITS_LOCAL] = 100.0 * hits / sym_hist->nr_samples;
1784 }
1785
1786 if (hists->stats.nr_non_filtered_samples)
1787 data->percent[PERCENT_HITS_GLOBAL] = 100.0 * hits / hists->stats.nr_non_filtered_samples;
1788
1789 if (sym_hist->period)
1790 data->percent[PERCENT_PERIOD_LOCAL] = 100.0 * period / sym_hist->period;
1791
1792 if (hists->stats.total_period)
1793 data->percent[PERCENT_PERIOD_GLOBAL] = 100.0 * period / hists->stats.total_period;
1794}
1795
1796static void annotation__calc_percent(struct annotation *notes,
1797 struct perf_evsel *leader, s64 len)
1798{
1799 struct annotation_line *al, *next;
1800 struct perf_evsel *evsel;
1801
1802 list_for_each_entry(al, ¬es->src->source, node) {
1803 s64 end;
1804 int i = 0;
1805
1806 if (al->offset == -1)
1807 continue;
1808
1809 next = annotation_line__next(al, ¬es->src->source);
1810 end = next ? next->offset : len;
1811
1812 for_each_group_evsel(evsel, leader) {
1813 struct hists *hists = evsel__hists(evsel);
1814 struct annotation_data *data;
1815 struct sym_hist *sym_hist;
1816
1817 BUG_ON(i >= al->data_nr);
1818
1819 sym_hist = annotation__histogram(notes, evsel->idx);
1820 data = &al->data[i++];
1821
1822 calc_percent(sym_hist, hists, data, al->offset, end);
1823 }
1824 }
1825}
1826
1827void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel)
1828{
1829 struct annotation *notes = symbol__annotation(sym);
1830
1831 annotation__calc_percent(notes, evsel, symbol__size(sym));
1832}
1833
1834int symbol__annotate(struct symbol *sym, struct map *map,
1835 struct perf_evsel *evsel, size_t privsize,
1836 struct annotation_options *options,
1837 struct arch **parch)
1838{
1839 struct annotate_args args = {
1840 .privsize = privsize,
1841 .evsel = evsel,
1842 .options = options,
1843 };
1844 struct perf_env *env = perf_evsel__env(evsel);
1845 const char *arch_name = perf_env__arch(env);
1846 struct arch *arch;
1847 int err;
1848
1849 if (!arch_name)
1850 return -1;
1851
1852 args.arch = arch = arch__find(arch_name);
1853 if (arch == NULL)
1854 return -ENOTSUP;
1855
1856 if (parch)
1857 *parch = arch;
1858
1859 if (arch->init) {
1860 err = arch->init(arch, env ? env->cpuid : NULL);
1861 if (err) {
1862 pr_err("%s: failed to initialize %s arch priv area\n", __func__, arch->name);
1863 return err;
1864 }
1865 }
1866
1867 args.ms.map = map;
1868 args.ms.sym = sym;
1869
1870 return symbol__disassemble(sym, &args);
1871}
1872
1873static void insert_source_line(struct rb_root *root, struct annotation_line *al,
1874 struct annotation_options *opts)
1875{
1876 struct annotation_line *iter;
1877 struct rb_node **p = &root->rb_node;
1878 struct rb_node *parent = NULL;
1879 int i, ret;
1880
1881 while (*p != NULL) {
1882 parent = *p;
1883 iter = rb_entry(parent, struct annotation_line, rb_node);
1884
1885 ret = strcmp(iter->path, al->path);
1886 if (ret == 0) {
1887 for (i = 0; i < al->data_nr; i++) {
1888 iter->data[i].percent_sum += annotation_data__percent(&al->data[i],
1889 opts->percent_type);
1890 }
1891 return;
1892 }
1893
1894 if (ret < 0)
1895 p = &(*p)->rb_left;
1896 else
1897 p = &(*p)->rb_right;
1898 }
1899
1900 for (i = 0; i < al->data_nr; i++) {
1901 al->data[i].percent_sum = annotation_data__percent(&al->data[i],
1902 opts->percent_type);
1903 }
1904
1905 rb_link_node(&al->rb_node, parent, p);
1906 rb_insert_color(&al->rb_node, root);
1907}
1908
1909static int cmp_source_line(struct annotation_line *a, struct annotation_line *b)
1910{
1911 int i;
1912
1913 for (i = 0; i < a->data_nr; i++) {
1914 if (a->data[i].percent_sum == b->data[i].percent_sum)
1915 continue;
1916 return a->data[i].percent_sum > b->data[i].percent_sum;
1917 }
1918
1919 return 0;
1920}
1921
1922static void __resort_source_line(struct rb_root *root, struct annotation_line *al)
1923{
1924 struct annotation_line *iter;
1925 struct rb_node **p = &root->rb_node;
1926 struct rb_node *parent = NULL;
1927
1928 while (*p != NULL) {
1929 parent = *p;
1930 iter = rb_entry(parent, struct annotation_line, rb_node);
1931
1932 if (cmp_source_line(al, iter))
1933 p = &(*p)->rb_left;
1934 else
1935 p = &(*p)->rb_right;
1936 }
1937
1938 rb_link_node(&al->rb_node, parent, p);
1939 rb_insert_color(&al->rb_node, root);
1940}
1941
1942static void resort_source_line(struct rb_root *dest_root, struct rb_root *src_root)
1943{
1944 struct annotation_line *al;
1945 struct rb_node *node;
1946
1947 node = rb_first(src_root);
1948 while (node) {
1949 struct rb_node *next;
1950
1951 al = rb_entry(node, struct annotation_line, rb_node);
1952 next = rb_next(node);
1953 rb_erase(node, src_root);
1954
1955 __resort_source_line(dest_root, al);
1956 node = next;
1957 }
1958}
1959
1960static void print_summary(struct rb_root *root, const char *filename)
1961{
1962 struct annotation_line *al;
1963 struct rb_node *node;
1964
1965 printf("\nSorted summary for file %s\n", filename);
1966 printf("----------------------------------------------\n\n");
1967
1968 if (RB_EMPTY_ROOT(root)) {
1969 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
1970 return;
1971 }
1972
1973 node = rb_first(root);
1974 while (node) {
1975 double percent, percent_max = 0.0;
1976 const char *color;
1977 char *path;
1978 int i;
1979
1980 al = rb_entry(node, struct annotation_line, rb_node);
1981 for (i = 0; i < al->data_nr; i++) {
1982 percent = al->data[i].percent_sum;
1983 color = get_percent_color(percent);
1984 color_fprintf(stdout, color, " %7.2f", percent);
1985
1986 if (percent > percent_max)
1987 percent_max = percent;
1988 }
1989
1990 path = al->path;
1991 color = get_percent_color(percent_max);
1992 color_fprintf(stdout, color, " %s\n", path);
1993
1994 node = rb_next(node);
1995 }
1996}
1997
1998static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
1999{
2000 struct annotation *notes = symbol__annotation(sym);
2001 struct sym_hist *h = annotation__histogram(notes, evsel->idx);
2002 u64 len = symbol__size(sym), offset;
2003
2004 for (offset = 0; offset < len; ++offset)
2005 if (h->addr[offset].nr_samples != 0)
2006 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
2007 sym->start + offset, h->addr[offset].nr_samples);
2008 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->nr_samples", h->nr_samples);
2009}
2010
2011static int annotated_source__addr_fmt_width(struct list_head *lines, u64 start)
2012{
2013 char bf[32];
2014 struct annotation_line *line;
2015
2016 list_for_each_entry_reverse(line, lines, node) {
2017 if (line->offset != -1)
2018 return scnprintf(bf, sizeof(bf), "%" PRIx64, start + line->offset);
2019 }
2020
2021 return 0;
2022}
2023
2024int symbol__annotate_printf(struct symbol *sym, struct map *map,
2025 struct perf_evsel *evsel,
2026 struct annotation_options *opts)
2027{
2028 struct dso *dso = map->dso;
2029 char *filename;
2030 const char *d_filename;
2031 const char *evsel_name = perf_evsel__name(evsel);
2032 struct annotation *notes = symbol__annotation(sym);
2033 struct sym_hist *h = annotation__histogram(notes, evsel->idx);
2034 struct annotation_line *pos, *queue = NULL;
2035 u64 start = map__rip_2objdump(map, sym->start);
2036 int printed = 2, queue_len = 0, addr_fmt_width;
2037 int more = 0;
2038 bool context = opts->context;
2039 u64 len;
2040 int width = symbol_conf.show_total_period ? 12 : 8;
2041 int graph_dotted_len;
2042 char buf[512];
2043
2044 filename = strdup(dso->long_name);
2045 if (!filename)
2046 return -ENOMEM;
2047
2048 if (opts->full_path)
2049 d_filename = filename;
2050 else
2051 d_filename = basename(filename);
2052
2053 len = symbol__size(sym);
2054
2055 if (perf_evsel__is_group_event(evsel)) {
2056 width *= evsel->nr_members;
2057 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2058 evsel_name = buf;
2059 }
2060
2061 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples, "
2062 "percent: %s)\n",
2063 width, width, symbol_conf.show_total_period ? "Period" :
2064 symbol_conf.show_nr_samples ? "Samples" : "Percent",
2065 d_filename, evsel_name, h->nr_samples,
2066 percent_type_str(opts->percent_type));
2067
2068 printf("%-*.*s----\n",
2069 graph_dotted_len, graph_dotted_len, graph_dotted_line);
2070
2071 if (verbose > 0)
2072 symbol__annotate_hits(sym, evsel);
2073
2074 addr_fmt_width = annotated_source__addr_fmt_width(¬es->src->source, start);
2075
2076 list_for_each_entry(pos, ¬es->src->source, node) {
2077 int err;
2078
2079 if (context && queue == NULL) {
2080 queue = pos;
2081 queue_len = 0;
2082 }
2083
2084 err = annotation_line__print(pos, sym, start, evsel, len,
2085 opts->min_pcnt, printed, opts->max_lines,
2086 queue, addr_fmt_width, opts->percent_type);
2087
2088 switch (err) {
2089 case 0:
2090 ++printed;
2091 if (context) {
2092 printed += queue_len;
2093 queue = NULL;
2094 queue_len = 0;
2095 }
2096 break;
2097 case 1:
2098 /* filtered by max_lines */
2099 ++more;
2100 break;
2101 case -1:
2102 default:
2103 /*
2104 * Filtered by min_pcnt or non IP lines when
2105 * context != 0
2106 */
2107 if (!context)
2108 break;
2109 if (queue_len == context)
2110 queue = list_entry(queue->node.next, typeof(*queue), node);
2111 else
2112 ++queue_len;
2113 break;
2114 }
2115 }
2116
2117 free(filename);
2118
2119 return more;
2120}
2121
2122static void FILE__set_percent_color(void *fp __maybe_unused,
2123 double percent __maybe_unused,
2124 bool current __maybe_unused)
2125{
2126}
2127
2128static int FILE__set_jumps_percent_color(void *fp __maybe_unused,
2129 int nr __maybe_unused, bool current __maybe_unused)
2130{
2131 return 0;
2132}
2133
2134static int FILE__set_color(void *fp __maybe_unused, int color __maybe_unused)
2135{
2136 return 0;
2137}
2138
2139static void FILE__printf(void *fp, const char *fmt, ...)
2140{
2141 va_list args;
2142
2143 va_start(args, fmt);
2144 vfprintf(fp, fmt, args);
2145 va_end(args);
2146}
2147
2148static void FILE__write_graph(void *fp, int graph)
2149{
2150 const char *s;
2151 switch (graph) {
2152
2153 case DARROW_CHAR: s = "↓"; break;
2154 case UARROW_CHAR: s = "↑"; break;
2155 case LARROW_CHAR: s = "←"; break;
2156 case RARROW_CHAR: s = "→"; break;
2157 default: s = "?"; break;
2158 }
2159
2160 fputs(s, fp);
2161}
2162
2163static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp,
2164 struct annotation_options *opts)
2165{
2166 struct annotation *notes = symbol__annotation(sym);
2167 struct annotation_write_ops wops = {
2168 .first_line = true,
2169 .obj = fp,
2170 .set_color = FILE__set_color,
2171 .set_percent_color = FILE__set_percent_color,
2172 .set_jumps_percent_color = FILE__set_jumps_percent_color,
2173 .printf = FILE__printf,
2174 .write_graph = FILE__write_graph,
2175 };
2176 struct annotation_line *al;
2177
2178 list_for_each_entry(al, ¬es->src->source, node) {
2179 if (annotation_line__filter(al, notes))
2180 continue;
2181 annotation_line__write(al, notes, &wops, opts);
2182 fputc('\n', fp);
2183 wops.first_line = false;
2184 }
2185
2186 return 0;
2187}
2188
2189int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel,
2190 struct annotation_options *opts)
2191{
2192 const char *ev_name = perf_evsel__name(evsel);
2193 char buf[1024];
2194 char *filename;
2195 int err = -1;
2196 FILE *fp;
2197
2198 if (asprintf(&filename, "%s.annotation", ms->sym->name) < 0)
2199 return -1;
2200
2201 fp = fopen(filename, "w");
2202 if (fp == NULL)
2203 goto out_free_filename;
2204
2205 if (perf_evsel__is_group_event(evsel)) {
2206 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2207 ev_name = buf;
2208 }
2209
2210 fprintf(fp, "%s() %s\nEvent: %s\n\n",
2211 ms->sym->name, ms->map->dso->long_name, ev_name);
2212 symbol__annotate_fprintf2(ms->sym, fp, opts);
2213
2214 fclose(fp);
2215 err = 0;
2216out_free_filename:
2217 free(filename);
2218 return err;
2219}
2220
2221void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
2222{
2223 struct annotation *notes = symbol__annotation(sym);
2224 struct sym_hist *h = annotation__histogram(notes, evidx);
2225
2226 memset(h, 0, notes->src->sizeof_sym_hist);
2227}
2228
2229void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
2230{
2231 struct annotation *notes = symbol__annotation(sym);
2232 struct sym_hist *h = annotation__histogram(notes, evidx);
2233 int len = symbol__size(sym), offset;
2234
2235 h->nr_samples = 0;
2236 for (offset = 0; offset < len; ++offset) {
2237 h->addr[offset].nr_samples = h->addr[offset].nr_samples * 7 / 8;
2238 h->nr_samples += h->addr[offset].nr_samples;
2239 }
2240}
2241
2242void annotated_source__purge(struct annotated_source *as)
2243{
2244 struct annotation_line *al, *n;
2245
2246 list_for_each_entry_safe(al, n, &as->source, node) {
2247 list_del(&al->node);
2248 disasm_line__free(disasm_line(al));
2249 }
2250}
2251
2252static size_t disasm_line__fprintf(struct disasm_line *dl, FILE *fp)
2253{
2254 size_t printed;
2255
2256 if (dl->al.offset == -1)
2257 return fprintf(fp, "%s\n", dl->al.line);
2258
2259 printed = fprintf(fp, "%#" PRIx64 " %s", dl->al.offset, dl->ins.name);
2260
2261 if (dl->ops.raw[0] != '\0') {
2262 printed += fprintf(fp, "%.*s %s\n", 6 - (int)printed, " ",
2263 dl->ops.raw);
2264 }
2265
2266 return printed + fprintf(fp, "\n");
2267}
2268
2269size_t disasm__fprintf(struct list_head *head, FILE *fp)
2270{
2271 struct disasm_line *pos;
2272 size_t printed = 0;
2273
2274 list_for_each_entry(pos, head, al.node)
2275 printed += disasm_line__fprintf(pos, fp);
2276
2277 return printed;
2278}
2279
2280bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym)
2281{
2282 if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) ||
2283 !disasm_line__has_local_offset(dl) || dl->ops.target.offset < 0 ||
2284 dl->ops.target.offset >= (s64)symbol__size(sym))
2285 return false;
2286
2287 return true;
2288}
2289
2290void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym)
2291{
2292 u64 offset, size = symbol__size(sym);
2293
2294 /* PLT symbols contain external offsets */
2295 if (strstr(sym->name, "@plt"))
2296 return;
2297
2298 for (offset = 0; offset < size; ++offset) {
2299 struct annotation_line *al = notes->offsets[offset];
2300 struct disasm_line *dl;
2301
2302 dl = disasm_line(al);
2303
2304 if (!disasm_line__is_valid_local_jump(dl, sym))
2305 continue;
2306
2307 al = notes->offsets[dl->ops.target.offset];
2308
2309 /*
2310 * FIXME: Oops, no jump target? Buggy disassembler? Or do we
2311 * have to adjust to the previous offset?
2312 */
2313 if (al == NULL)
2314 continue;
2315
2316 if (++al->jump_sources > notes->max_jump_sources)
2317 notes->max_jump_sources = al->jump_sources;
2318
2319 ++notes->nr_jumps;
2320 }
2321}
2322
2323void annotation__set_offsets(struct annotation *notes, s64 size)
2324{
2325 struct annotation_line *al;
2326
2327 notes->max_line_len = 0;
2328
2329 list_for_each_entry(al, ¬es->src->source, node) {
2330 size_t line_len = strlen(al->line);
2331
2332 if (notes->max_line_len < line_len)
2333 notes->max_line_len = line_len;
2334 al->idx = notes->nr_entries++;
2335 if (al->offset != -1) {
2336 al->idx_asm = notes->nr_asm_entries++;
2337 /*
2338 * FIXME: short term bandaid to cope with assembly
2339 * routines that comes with labels in the same column
2340 * as the address in objdump, sigh.
2341 *
2342 * E.g. copy_user_generic_unrolled
2343 */
2344 if (al->offset < size)
2345 notes->offsets[al->offset] = al;
2346 } else
2347 al->idx_asm = -1;
2348 }
2349}
2350
2351static inline int width_jumps(int n)
2352{
2353 if (n >= 100)
2354 return 5;
2355 if (n / 10)
2356 return 2;
2357 return 1;
2358}
2359
2360void annotation__init_column_widths(struct annotation *notes, struct symbol *sym)
2361{
2362 notes->widths.addr = notes->widths.target =
2363 notes->widths.min_addr = hex_width(symbol__size(sym));
2364 notes->widths.max_addr = hex_width(sym->end);
2365 notes->widths.jumps = width_jumps(notes->max_jump_sources);
2366}
2367
2368void annotation__update_column_widths(struct annotation *notes)
2369{
2370 if (notes->options->use_offset)
2371 notes->widths.target = notes->widths.min_addr;
2372 else
2373 notes->widths.target = notes->widths.max_addr;
2374
2375 notes->widths.addr = notes->widths.target;
2376
2377 if (notes->options->show_nr_jumps)
2378 notes->widths.addr += notes->widths.jumps + 1;
2379}
2380
2381static void annotation__calc_lines(struct annotation *notes, struct map *map,
2382 struct rb_root *root,
2383 struct annotation_options *opts)
2384{
2385 struct annotation_line *al;
2386 struct rb_root tmp_root = RB_ROOT;
2387
2388 list_for_each_entry(al, ¬es->src->source, node) {
2389 double percent_max = 0.0;
2390 int i;
2391
2392 for (i = 0; i < al->data_nr; i++) {
2393 double percent;
2394
2395 percent = annotation_data__percent(&al->data[i],
2396 opts->percent_type);
2397
2398 if (percent > percent_max)
2399 percent_max = percent;
2400 }
2401
2402 if (percent_max <= 0.5)
2403 continue;
2404
2405 al->path = get_srcline(map->dso, notes->start + al->offset, NULL,
2406 false, true, notes->start + al->offset);
2407 insert_source_line(&tmp_root, al, opts);
2408 }
2409
2410 resort_source_line(root, &tmp_root);
2411}
2412
2413static void symbol__calc_lines(struct symbol *sym, struct map *map,
2414 struct rb_root *root,
2415 struct annotation_options *opts)
2416{
2417 struct annotation *notes = symbol__annotation(sym);
2418
2419 annotation__calc_lines(notes, map, root, opts);
2420}
2421
2422int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2423 struct perf_evsel *evsel,
2424 struct annotation_options *opts)
2425{
2426 struct dso *dso = map->dso;
2427 struct rb_root source_line = RB_ROOT;
2428 struct hists *hists = evsel__hists(evsel);
2429 char buf[1024];
2430
2431 if (symbol__annotate2(sym, map, evsel, opts, NULL) < 0)
2432 return -1;
2433
2434 if (opts->print_lines) {
2435 srcline_full_filename = opts->full_path;
2436 symbol__calc_lines(sym, map, &source_line, opts);
2437 print_summary(&source_line, dso->long_name);
2438 }
2439
2440 hists__scnprintf_title(hists, buf, sizeof(buf));
2441 fprintf(stdout, "%s, [percent: %s]\n%s() %s\n",
2442 buf, percent_type_str(opts->percent_type), sym->name, dso->long_name);
2443 symbol__annotate_fprintf2(sym, stdout, opts);
2444
2445 annotated_source__purge(symbol__annotation(sym)->src);
2446
2447 return 0;
2448}
2449
2450int symbol__tty_annotate(struct symbol *sym, struct map *map,
2451 struct perf_evsel *evsel,
2452 struct annotation_options *opts)
2453{
2454 struct dso *dso = map->dso;
2455 struct rb_root source_line = RB_ROOT;
2456
2457 if (symbol__annotate(sym, map, evsel, 0, opts, NULL) < 0)
2458 return -1;
2459
2460 symbol__calc_percent(sym, evsel);
2461
2462 if (opts->print_lines) {
2463 srcline_full_filename = opts->full_path;
2464 symbol__calc_lines(sym, map, &source_line, opts);
2465 print_summary(&source_line, dso->long_name);
2466 }
2467
2468 symbol__annotate_printf(sym, map, evsel, opts);
2469
2470 annotated_source__purge(symbol__annotation(sym)->src);
2471
2472 return 0;
2473}
2474
2475bool ui__has_annotation(void)
2476{
2477 return use_browser == 1 && perf_hpp_list.sym;
2478}
2479
2480
2481static double annotation_line__max_percent(struct annotation_line *al,
2482 struct annotation *notes,
2483 unsigned int percent_type)
2484{
2485 double percent_max = 0.0;
2486 int i;
2487
2488 for (i = 0; i < notes->nr_events; i++) {
2489 double percent;
2490
2491 percent = annotation_data__percent(&al->data[i],
2492 percent_type);
2493
2494 if (percent > percent_max)
2495 percent_max = percent;
2496 }
2497
2498 return percent_max;
2499}
2500
2501static void disasm_line__write(struct disasm_line *dl, struct annotation *notes,
2502 void *obj, char *bf, size_t size,
2503 void (*obj__printf)(void *obj, const char *fmt, ...),
2504 void (*obj__write_graph)(void *obj, int graph))
2505{
2506 if (dl->ins.ops && dl->ins.ops->scnprintf) {
2507 if (ins__is_jump(&dl->ins)) {
2508 bool fwd;
2509
2510 if (dl->ops.target.outside)
2511 goto call_like;
2512 fwd = dl->ops.target.offset > dl->al.offset;
2513 obj__write_graph(obj, fwd ? DARROW_CHAR : UARROW_CHAR);
2514 obj__printf(obj, " ");
2515 } else if (ins__is_call(&dl->ins)) {
2516call_like:
2517 obj__write_graph(obj, RARROW_CHAR);
2518 obj__printf(obj, " ");
2519 } else if (ins__is_ret(&dl->ins)) {
2520 obj__write_graph(obj, LARROW_CHAR);
2521 obj__printf(obj, " ");
2522 } else {
2523 obj__printf(obj, " ");
2524 }
2525 } else {
2526 obj__printf(obj, " ");
2527 }
2528
2529 disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset);
2530}
2531
2532static void __annotation_line__write(struct annotation_line *al, struct annotation *notes,
2533 bool first_line, bool current_entry, bool change_color, int width,
2534 void *obj, unsigned int percent_type,
2535 int (*obj__set_color)(void *obj, int color),
2536 void (*obj__set_percent_color)(void *obj, double percent, bool current),
2537 int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current),
2538 void (*obj__printf)(void *obj, const char *fmt, ...),
2539 void (*obj__write_graph)(void *obj, int graph))
2540
2541{
2542 double percent_max = annotation_line__max_percent(al, notes, percent_type);
2543 int pcnt_width = annotation__pcnt_width(notes),
2544 cycles_width = annotation__cycles_width(notes);
2545 bool show_title = false;
2546 char bf[256];
2547 int printed;
2548
2549 if (first_line && (al->offset == -1 || percent_max == 0.0)) {
2550 if (notes->have_cycles) {
2551 if (al->ipc == 0.0 && al->cycles == 0)
2552 show_title = true;
2553 } else
2554 show_title = true;
2555 }
2556
2557 if (al->offset != -1 && percent_max != 0.0) {
2558 int i;
2559
2560 for (i = 0; i < notes->nr_events; i++) {
2561 double percent;
2562
2563 percent = annotation_data__percent(&al->data[i], percent_type);
2564
2565 obj__set_percent_color(obj, percent, current_entry);
2566 if (notes->options->show_total_period) {
2567 obj__printf(obj, "%11" PRIu64 " ", al->data[i].he.period);
2568 } else if (notes->options->show_nr_samples) {
2569 obj__printf(obj, "%6" PRIu64 " ",
2570 al->data[i].he.nr_samples);
2571 } else {
2572 obj__printf(obj, "%6.2f ", percent);
2573 }
2574 }
2575 } else {
2576 obj__set_percent_color(obj, 0, current_entry);
2577
2578 if (!show_title)
2579 obj__printf(obj, "%-*s", pcnt_width, " ");
2580 else {
2581 obj__printf(obj, "%-*s", pcnt_width,
2582 notes->options->show_total_period ? "Period" :
2583 notes->options->show_nr_samples ? "Samples" : "Percent");
2584 }
2585 }
2586
2587 if (notes->have_cycles) {
2588 if (al->ipc)
2589 obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc);
2590 else if (!show_title)
2591 obj__printf(obj, "%*s", ANNOTATION__IPC_WIDTH, " ");
2592 else
2593 obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
2594
2595 if (!notes->options->show_minmax_cycle) {
2596 if (al->cycles)
2597 obj__printf(obj, "%*" PRIu64 " ",
2598 ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
2599 else if (!show_title)
2600 obj__printf(obj, "%*s",
2601 ANNOTATION__CYCLES_WIDTH, " ");
2602 else
2603 obj__printf(obj, "%*s ",
2604 ANNOTATION__CYCLES_WIDTH - 1,
2605 "Cycle");
2606 } else {
2607 if (al->cycles) {
2608 char str[32];
2609
2610 scnprintf(str, sizeof(str),
2611 "%" PRIu64 "(%" PRIu64 "/%" PRIu64 ")",
2612 al->cycles, al->cycles_min,
2613 al->cycles_max);
2614
2615 obj__printf(obj, "%*s ",
2616 ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
2617 str);
2618 } else if (!show_title)
2619 obj__printf(obj, "%*s",
2620 ANNOTATION__MINMAX_CYCLES_WIDTH,
2621 " ");
2622 else
2623 obj__printf(obj, "%*s ",
2624 ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
2625 "Cycle(min/max)");
2626 }
2627 }
2628
2629 obj__printf(obj, " ");
2630
2631 if (!*al->line)
2632 obj__printf(obj, "%-*s", width - pcnt_width - cycles_width, " ");
2633 else if (al->offset == -1) {
2634 if (al->line_nr && notes->options->show_linenr)
2635 printed = scnprintf(bf, sizeof(bf), "%-*d ", notes->widths.addr + 1, al->line_nr);
2636 else
2637 printed = scnprintf(bf, sizeof(bf), "%-*s ", notes->widths.addr, " ");
2638 obj__printf(obj, bf);
2639 obj__printf(obj, "%-*s", width - printed - pcnt_width - cycles_width + 1, al->line);
2640 } else {
2641 u64 addr = al->offset;
2642 int color = -1;
2643
2644 if (!notes->options->use_offset)
2645 addr += notes->start;
2646
2647 if (!notes->options->use_offset) {
2648 printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
2649 } else {
2650 if (al->jump_sources &&
2651 notes->options->offset_level >= ANNOTATION__OFFSET_JUMP_TARGETS) {
2652 if (notes->options->show_nr_jumps) {
2653 int prev;
2654 printed = scnprintf(bf, sizeof(bf), "%*d ",
2655 notes->widths.jumps,
2656 al->jump_sources);
2657 prev = obj__set_jumps_percent_color(obj, al->jump_sources,
2658 current_entry);
2659 obj__printf(obj, bf);
2660 obj__set_color(obj, prev);
2661 }
2662print_addr:
2663 printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
2664 notes->widths.target, addr);
2665 } else if (ins__is_call(&disasm_line(al)->ins) &&
2666 notes->options->offset_level >= ANNOTATION__OFFSET_CALL) {
2667 goto print_addr;
2668 } else if (notes->options->offset_level == ANNOTATION__MAX_OFFSET_LEVEL) {
2669 goto print_addr;
2670 } else {
2671 printed = scnprintf(bf, sizeof(bf), "%-*s ",
2672 notes->widths.addr, " ");
2673 }
2674 }
2675
2676 if (change_color)
2677 color = obj__set_color(obj, HE_COLORSET_ADDR);
2678 obj__printf(obj, bf);
2679 if (change_color)
2680 obj__set_color(obj, color);
2681
2682 disasm_line__write(disasm_line(al), notes, obj, bf, sizeof(bf), obj__printf, obj__write_graph);
2683
2684 obj__printf(obj, "%-*s", width - pcnt_width - cycles_width - 3 - printed, bf);
2685 }
2686
2687}
2688
2689void annotation_line__write(struct annotation_line *al, struct annotation *notes,
2690 struct annotation_write_ops *wops,
2691 struct annotation_options *opts)
2692{
2693 __annotation_line__write(al, notes, wops->first_line, wops->current_entry,
2694 wops->change_color, wops->width, wops->obj,
2695 opts->percent_type,
2696 wops->set_color, wops->set_percent_color,
2697 wops->set_jumps_percent_color, wops->printf,
2698 wops->write_graph);
2699}
2700
2701int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel,
2702 struct annotation_options *options, struct arch **parch)
2703{
2704 struct annotation *notes = symbol__annotation(sym);
2705 size_t size = symbol__size(sym);
2706 int nr_pcnt = 1, err;
2707
2708 notes->offsets = zalloc(size * sizeof(struct annotation_line *));
2709 if (notes->offsets == NULL)
2710 return -1;
2711
2712 if (perf_evsel__is_group_event(evsel))
2713 nr_pcnt = evsel->nr_members;
2714
2715 err = symbol__annotate(sym, map, evsel, 0, options, parch);
2716 if (err)
2717 goto out_free_offsets;
2718
2719 notes->options = options;
2720
2721 symbol__calc_percent(sym, evsel);
2722
2723 notes->start = map__rip_2objdump(map, sym->start);
2724
2725 annotation__set_offsets(notes, size);
2726 annotation__mark_jump_targets(notes, sym);
2727 annotation__compute_ipc(notes, size);
2728 annotation__init_column_widths(notes, sym);
2729 notes->nr_events = nr_pcnt;
2730
2731 annotation__update_column_widths(notes);
2732
2733 return 0;
2734
2735out_free_offsets:
2736 zfree(¬es->offsets);
2737 return -1;
2738}
2739
2740#define ANNOTATION__CFG(n) \
2741 { .name = #n, .value = &annotation__default_options.n, }
2742
2743/*
2744 * Keep the entries sorted, they are bsearch'ed
2745 */
2746static struct annotation_config {
2747 const char *name;
2748 void *value;
2749} annotation__configs[] = {
2750 ANNOTATION__CFG(hide_src_code),
2751 ANNOTATION__CFG(jump_arrows),
2752 ANNOTATION__CFG(offset_level),
2753 ANNOTATION__CFG(show_linenr),
2754 ANNOTATION__CFG(show_nr_jumps),
2755 ANNOTATION__CFG(show_nr_samples),
2756 ANNOTATION__CFG(show_total_period),
2757 ANNOTATION__CFG(use_offset),
2758};
2759
2760#undef ANNOTATION__CFG
2761
2762static int annotation_config__cmp(const void *name, const void *cfgp)
2763{
2764 const struct annotation_config *cfg = cfgp;
2765
2766 return strcmp(name, cfg->name);
2767}
2768
2769static int annotation__config(const char *var, const char *value,
2770 void *data __maybe_unused)
2771{
2772 struct annotation_config *cfg;
2773 const char *name;
2774
2775 if (!strstarts(var, "annotate."))
2776 return 0;
2777
2778 name = var + 9;
2779 cfg = bsearch(name, annotation__configs, ARRAY_SIZE(annotation__configs),
2780 sizeof(struct annotation_config), annotation_config__cmp);
2781
2782 if (cfg == NULL)
2783 pr_debug("%s variable unknown, ignoring...", var);
2784 else if (strcmp(var, "annotate.offset_level") == 0) {
2785 perf_config_int(cfg->value, name, value);
2786
2787 if (*(int *)cfg->value > ANNOTATION__MAX_OFFSET_LEVEL)
2788 *(int *)cfg->value = ANNOTATION__MAX_OFFSET_LEVEL;
2789 else if (*(int *)cfg->value < ANNOTATION__MIN_OFFSET_LEVEL)
2790 *(int *)cfg->value = ANNOTATION__MIN_OFFSET_LEVEL;
2791 } else {
2792 *(bool *)cfg->value = perf_config_bool(name, value);
2793 }
2794 return 0;
2795}
2796
2797void annotation_config__init(void)
2798{
2799 perf_config(annotation__config, NULL);
2800
2801 annotation__default_options.show_total_period = symbol_conf.show_total_period;
2802 annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples;
2803}
2804
2805static unsigned int parse_percent_type(char *str1, char *str2)
2806{
2807 unsigned int type = (unsigned int) -1;
2808
2809 if (!strcmp("period", str1)) {
2810 if (!strcmp("local", str2))
2811 type = PERCENT_PERIOD_LOCAL;
2812 else if (!strcmp("global", str2))
2813 type = PERCENT_PERIOD_GLOBAL;
2814 }
2815
2816 if (!strcmp("hits", str1)) {
2817 if (!strcmp("local", str2))
2818 type = PERCENT_HITS_LOCAL;
2819 else if (!strcmp("global", str2))
2820 type = PERCENT_HITS_GLOBAL;
2821 }
2822
2823 return type;
2824}
2825
2826int annotate_parse_percent_type(const struct option *opt, const char *_str,
2827 int unset __maybe_unused)
2828{
2829 struct annotation_options *opts = opt->value;
2830 unsigned int type;
2831 char *str1, *str2;
2832 int err = -1;
2833
2834 str1 = strdup(_str);
2835 if (!str1)
2836 return -ENOMEM;
2837
2838 str2 = strchr(str1, '-');
2839 if (!str2)
2840 goto out;
2841
2842 *str2++ = 0;
2843
2844 type = parse_percent_type(str1, str2);
2845 if (type == (unsigned int) -1)
2846 type = parse_percent_type(str2, str1);
2847 if (type != (unsigned int) -1) {
2848 opts->percent_type = type;
2849 err = 0;
2850 }
2851
2852out:
2853 free(str1);
2854 return err;
2855}