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