]> git.ipfire.org Git - thirdparty/linux.git/blame - tools/perf/util/annotate.c
perf annotate: Make local period the default percent type
[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"
763d8960 142
786c1b51
ACM
143static struct arch architectures[] = {
144 {
145 .name = "arm",
acc9bfb5 146 .init = arm__annotate_init,
786c1b51 147 },
0fcb1da4
KP
148 {
149 .name = "arm64",
150 .init = arm64__annotate_init,
151 },
786c1b51
ACM
152 {
153 .name = "x86",
696e2457 154 .init = x86__annotate_init,
763d8960
ACM
155 .instructions = x86__instructions,
156 .nr_instructions = ARRAY_SIZE(x86__instructions),
69fb09f6 157 .ins_is_fused = x86__ins_is_fused,
786c1b51
ACM
158 .objdump = {
159 .comment_char = '#',
160 },
161 },
dbdebdc5
RB
162 {
163 .name = "powerpc",
164 .init = powerpc__annotate_init,
165 },
e77852b3
CB
166 {
167 .name = "s390",
d9f8dfa9 168 .init = s390__annotate_init,
e77852b3
CB
169 .objdump = {
170 .comment_char = '#',
171 },
172 },
786c1b51
ACM
173};
174
c46219ac
ACM
175static void ins__delete(struct ins_operands *ops)
176{
3995614d
ACM
177 if (ops == NULL)
178 return;
74cf249d
ACM
179 zfree(&ops->source.raw);
180 zfree(&ops->source.name);
181 zfree(&ops->target.raw);
182 zfree(&ops->target.name);
c46219ac
ACM
183}
184
5417072b
ACM
185static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
186 struct ins_operands *ops)
187{
648388ae 188 return scnprintf(bf, size, "%-6s %s", ins->name, ops->raw);
5417072b
ACM
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
69fb09f6
JY
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
85a84e4f 208static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
d86b0597 209{
d2232885 210 char *endptr, *tok, *name;
85a84e4f 211 struct map *map = ms->map;
696703af
ACM
212 struct addr_map_symbol target = {
213 .map = map,
214 };
d2232885 215
44d1a3ed 216 ops->target.addr = strtoull(ops->raw, &endptr, 16);
d2232885
ACM
217
218 name = strchr(endptr, '<');
219 if (name == NULL)
220 goto indirect_call;
221
222 name++;
223
9c2fb451
ACM
224 if (arch->objdump.skip_functions_char &&
225 strchr(name, arch->objdump.skip_functions_char))
cfef25b8 226 return -1;
cfef25b8 227
d2232885
ACM
228 tok = strchr(name, '>');
229 if (tok == NULL)
230 return -1;
231
232 *tok = '\0';
44d1a3ed 233 ops->target.name = strdup(name);
d2232885
ACM
234 *tok = '>';
235
696703af
ACM
236 if (ops->target.name == NULL)
237 return -1;
238find_target:
239 target.addr = map__objdump_2mem(map, ops->target.addr);
d2232885 240
696703af
ACM
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;
e8ea1561 244
d86b0597 245 return 0;
696703af
ACM
246
247indirect_call:
248 tok = strchr(endptr, '*');
249 if (tok != NULL)
250 ops->target.addr = strtoull(tok + 1, NULL, 16);
251 goto find_target;
d86b0597
ACM
252}
253
d2232885 254static int call__scnprintf(struct ins *ins, char *bf, size_t size,
5417072b 255 struct ins_operands *ops)
d2232885 256{
696703af
ACM
257 if (ops->target.sym)
258 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
d2232885 259
e8ea1561
ACM
260 if (ops->target.addr == 0)
261 return ins__raw_scnprintf(ins, bf, size, ops);
262
4c9cb2c2
ACM
263 if (ops->target.name)
264 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.name);
265
648388ae 266 return scnprintf(bf, size, "%-6s *%" PRIx64, ins->name, ops->target.addr);
d2232885
ACM
267}
268
d86b0597 269static struct ins_ops call_ops = {
d2232885
ACM
270 .parse = call__parse,
271 .scnprintf = call__scnprintf,
d86b0597
ACM
272};
273
274bool ins__is_call(const struct ins *ins)
275{
0b58a77c 276 return ins->ops == &call_ops || ins->ops == &s390_call_ops;
d86b0597
ACM
277}
278
751b1783 279static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms)
4f9d0325 280{
751b1783
ACM
281 struct map *map = ms->map;
282 struct symbol *sym = ms->sym;
283 struct addr_map_symbol target = {
284 .map = map,
285 };
3ee2eb6d 286 const char *c = strchr(ops->raw, ',');
751b1783
ACM
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 */
b13bbeee
KP
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) {
3ee2eb6d 304 ops->target.addr = strtoull(c, NULL, 16);
b13bbeee
KP
305 if (!ops->target.addr) {
306 c = strchr(c, ',');
307 if (c++ != NULL)
308 ops->target.addr = strtoull(c, NULL, 16);
309 }
310 } else {
3ee2eb6d 311 ops->target.addr = strtoull(ops->raw, NULL, 16);
b13bbeee 312 }
fb29fa58 313
751b1783
ACM
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.
e4cc91b8 337 */
751b1783
ACM
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;
751b1783 341
980b68ec
ACM
342 if (!ops->target.outside) {
343 ops->target.offset = target.addr - start;
e216874c
RB
344 ops->target.offset_avail = true;
345 } else {
346 ops->target.offset_avail = false;
347 }
4f9d0325 348
4f9d0325
ACM
349 return 0;
350}
351
c7e6ead7 352static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
5417072b 353 struct ins_operands *ops)
28548d78 354{
c448234c 355 const char *c;
b13bbeee 356
e216874c 357 if (!ops->target.addr || ops->target.offset < 0)
bec60e50
RB
358 return ins__raw_scnprintf(ins, bf, size, ops);
359
e4cc91b8
ACM
360 if (ops->target.outside && ops->target.sym != NULL)
361 return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name);
362
c448234c 363 c = strchr(ops->raw, ',');
b13bbeee
KP
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
648388ae 377 return scnprintf(bf, size, "%-6s %.*s%" PRIx64,
b13bbeee
KP
378 ins->name, c ? c - ops->raw : 0, ops->raw,
379 ops->target.offset);
28548d78
ACM
380}
381
4f9d0325 382static struct ins_ops jump_ops = {
c7e6ead7
ACM
383 .parse = jump__parse,
384 .scnprintf = jump__scnprintf,
4f9d0325
ACM
385};
386
387bool ins__is_jump(const struct ins *ins)
388{
389 return ins->ops == &jump_ops;
390}
391
6de783b6
ACM
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);
35a8a148
TR
400 if (endptr == comment)
401 return 0;
6de783b6
ACM
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
85a84e4f 419static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
7a997fe4 420{
7a997fe4
ACM
421 ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
422 if (ops->locked.ops == NULL)
423 return 0;
424
75b49202 425 if (disasm_line__parse(ops->raw, &ops->locked.ins.name, &ops->locked.ops->raw) < 0)
7a997fe4
ACM
426 goto out_free_ops;
427
75b49202 428 ops->locked.ins.ops = ins__find(arch, ops->locked.ins.name);
0fb9f2aa 429
75b49202 430 if (ops->locked.ins.ops == NULL)
2ba34aaa 431 goto out_free_ops;
7a997fe4 432
75b49202 433 if (ops->locked.ins.ops->parse &&
85a84e4f 434 ops->locked.ins.ops->parse(arch, ops->locked.ops, ms) < 0)
be81908c 435 goto out_free_ops;
7a997fe4
ACM
436
437 return 0;
438
439out_free_ops:
04662523 440 zfree(&ops->locked.ops);
7a997fe4
ACM
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
75b49202 449 if (ops->locked.ins.ops == NULL)
7a997fe4
ACM
450 return ins__raw_scnprintf(ins, bf, size, ops);
451
648388ae 452 printed = scnprintf(bf, size, "%-6s ", ins->name);
75b49202 453 return printed + ins__scnprintf(&ops->locked.ins, bf + printed,
7a997fe4
ACM
454 size - printed, ops->locked.ops);
455}
456
c46219ac
ACM
457static void lock__delete(struct ins_operands *ops)
458{
75b49202 459 struct ins *ins = &ops->locked.ins;
0fb9f2aa 460
75b49202 461 if (ins->ops && ins->ops->free)
0fb9f2aa
RV
462 ins->ops->free(ops->locked.ops);
463 else
464 ins__delete(ops->locked.ops);
465
74cf249d
ACM
466 zfree(&ops->locked.ops);
467 zfree(&ops->target.raw);
468 zfree(&ops->target.name);
c46219ac
ACM
469}
470
7a997fe4 471static struct ins_ops lock_ops = {
c46219ac 472 .free = lock__delete,
7a997fe4
ACM
473 .parse = lock__parse,
474 .scnprintf = lock__scnprintf,
475};
476
85a84e4f 477static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
6de783b6
ACM
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 = ',';
48000a1a 487
6de783b6
ACM
488 if (ops->source.raw == NULL)
489 return -1;
490
491 target = ++s;
786c1b51 492 comment = strchr(s, arch->objdump.comment_char);
1e2bb043
AC
493
494 if (comment != NULL)
495 s = comment - 1;
496 else
497 s = strchr(s, '\0') - 1;
6de783b6 498
1e2bb043
AC
499 while (s > target && isspace(s[0]))
500 --s;
501 s++;
6de783b6
ACM
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
6de783b6
ACM
511 if (comment == NULL)
512 return 0;
513
4597cf06 514 comment = ltrim(comment);
35a8a148
TR
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);
6de783b6
ACM
517
518 return 0;
519
520out_free_source:
04662523 521 zfree(&ops->source.raw);
6de783b6
ACM
522 return -1;
523}
524
525static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
526 struct ins_operands *ops)
527{
648388ae 528 return scnprintf(bf, size, "%-6s %s,%s", ins->name,
6de783b6
ACM
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
85a84e4f 538static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
a43712c4
ACM
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
859afa6c 555 comment = strchr(s, arch->objdump.comment_char);
a43712c4
ACM
556 if (comment == NULL)
557 return 0;
558
4597cf06 559 comment = ltrim(comment);
35a8a148 560 comment__symbol(ops->target.raw, comment + 1, &ops->target.addr, &ops->target.name);
a43712c4
ACM
561
562 return 0;
563}
564
565static int dec__scnprintf(struct ins *ins, char *bf, size_t size,
566 struct ins_operands *ops)
567{
648388ae 568 return scnprintf(bf, size, "%-6s %s", ins->name,
a43712c4
ACM
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
1d037ca1
IT
577static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size,
578 struct ins_operands *ops __maybe_unused)
b9818e93 579{
648388ae 580 return scnprintf(bf, size, "%-6s", "nop");
b9818e93
ACM
581}
582
583static struct ins_ops nop_ops = {
584 .scnprintf = nop__scnprintf,
585};
586
6ef94929
NR
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
7e63a13a
JY
596bool ins__is_lock(const struct ins *ins)
597{
598 return ins->ops == &lock_ops;
599}
600
7e4c1498 601static int ins__key_cmp(const void *name, const void *insp)
4f9d0325
ACM
602{
603 const struct ins *ins = insp;
604
605 return strcmp(name, ins->name);
606}
607
7e4c1498
CR
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
763d8960 616static void ins__sort(struct arch *arch)
7e4c1498 617{
763d8960 618 const int nmemb = arch->nr_instructions;
7e4c1498 619
763d8960 620 qsort(arch->instructions, nmemb, sizeof(struct ins), ins__cmp);
7e4c1498
CR
621}
622
2a1ff812 623static struct ins_ops *__ins__find(struct arch *arch, const char *name)
4f9d0325 624{
75b49202 625 struct ins *ins;
763d8960 626 const int nmemb = arch->nr_instructions;
7e4c1498 627
763d8960
ACM
628 if (!arch->sorted_instructions) {
629 ins__sort(arch);
630 arch->sorted_instructions = true;
7e4c1498 631 }
4f9d0325 632
75b49202
ACM
633 ins = bsearch(name, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp);
634 return ins ? ins->ops : NULL;
4f9d0325
ACM
635}
636
2a1ff812
ACM
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
786c1b51
ACM
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
ca396503
ACM
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
14c8dde1 692static __maybe_unused void annotated_source__delete(struct annotated_source *src)
ca396503
ACM
693{
694 if (src == NULL)
695 return;
696 zfree(&src->histograms);
697 zfree(&src->cycles_hist);
698 free(src);
699}
700
be3e26d9
ACM
701static int annotated_source__alloc_histograms(struct annotated_source *src,
702 size_t size, int nr_hists)
ce6f4fab 703{
8696329b
CS
704 size_t sizeof_sym_hist;
705
331c7cb3
RB
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
8696329b 716 /* Check for overflow when calculating sizeof_sym_hist */
896bccd3 717 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(struct sym_hist_entry))
8696329b
CS
718 return -1;
719
896bccd3 720 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(struct sym_hist_entry));
8696329b
CS
721
722 /* Check for overflow in zalloc argument */
be3e26d9 723 if (sizeof_sym_hist > SIZE_MAX / nr_hists)
8696329b 724 return -1;
ce6f4fab 725
be3e26d9
ACM
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
d4957633
AK
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
36532461
ACM
744void symbol__annotate_zero_histograms(struct symbol *sym)
745{
746 struct annotation *notes = symbol__annotation(sym);
747
ce6f4fab 748 pthread_mutex_lock(&notes->lock);
d4957633 749 if (notes->src != NULL) {
ce6f4fab
ACM
750 memset(notes->src->histograms, 0,
751 notes->src->nr_histograms * notes->src->sizeof_sym_hist);
d4957633
AK
752 if (notes->src->cycles_hist)
753 memset(notes->src->cycles_hist, 0,
754 symbol__size(sym) * sizeof(struct cyc_hist));
755 }
ce6f4fab 756 pthread_mutex_unlock(&notes->lock);
36532461
ACM
757}
758
f40dd6d1 759static int __symbol__account_cycles(struct cyc_hist *ch,
d4957633
AK
760 u64 start,
761 unsigned offset, unsigned cycles,
762 unsigned have_start)
763{
d4957633
AK
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
48659ebf
JY
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
d4957633
AK
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
b66d8c0c 805static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
e1a91a83 806 struct annotated_source *src, int evidx, u64 addr,
461c17f0 807 struct perf_sample *sample)
78f7defe 808{
2f525d01 809 unsigned offset;
78f7defe
ACM
810 struct sym_hist *h;
811
78f7defe
ACM
812 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
813
edee44be
RB
814 if ((addr < sym->start || addr >= sym->end) &&
815 (addr != sym->end || sym->start != sym->end)) {
e3d006ce
ACM
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);
31d68e7b 818 return -ERANGE;
e3d006ce 819 }
78f7defe 820
2f525d01 821 offset = addr - sym->start;
e1a91a83 822 h = annotated_source__histogram(src, evidx);
8d628d26
ACM
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 }
8158683d 828 h->nr_samples++;
896bccd3 829 h->addr[offset].nr_samples++;
461c17f0
TS
830 h->period += sample->period;
831 h->addr[offset].period += sample->period;
78f7defe
ACM
832
833 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
461c17f0
TS
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);
78f7defe
ACM
837 return 0;
838}
839
c6b635ee 840static struct cyc_hist *symbol__cycles_hist(struct symbol *sym)
83be34a7
AK
841{
842 struct annotation *notes = symbol__annotation(sym);
843
844 if (notes->src == NULL) {
c6b635ee
ACM
845 notes->src = annotated_source__new();
846 if (notes->src == NULL)
83be34a7 847 return NULL;
c6b635ee 848 goto alloc_cycles_hist;
83be34a7 849 }
c6b635ee
ACM
850
851 if (!notes->src->cycles_hist) {
852alloc_cycles_hist:
853 symbol__alloc_hist_cycles(sym);
d4957633 854 }
c6b635ee
ACM
855
856 return notes->src->cycles_hist;
83be34a7
AK
857}
858
14c8dde1 859struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists)
e8ea922a
ACM
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),
0693f758 873 nr_hists);
e8ea922a
ACM
874 }
875
876 return notes->src;
877}
878
44e83039 879static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
e345f3bd 880 struct perf_evsel *evsel, u64 addr,
bab89f6a 881 struct perf_sample *sample)
b66d8c0c 882{
e8ea922a 883 struct annotated_source *src;
b66d8c0c 884
48c65bda 885 if (sym == NULL)
b66d8c0c 886 return 0;
0693f758 887 src = symbol__hists(sym, evsel->evlist->nr_entries);
e8ea922a 888 if (src == NULL)
83be34a7 889 return -ENOMEM;
e8ea922a 890 return __symbol__inc_addr_samples(sym, map, src, evsel->idx, addr, sample);
b66d8c0c
ACM
891}
892
d4957633
AK
893static int symbol__account_cycles(u64 addr, u64 start,
894 struct symbol *sym, unsigned cycles)
895{
c6b635ee 896 struct cyc_hist *cycles_hist;
d4957633
AK
897 unsigned offset;
898
899 if (sym == NULL)
900 return 0;
c6b635ee
ACM
901 cycles_hist = symbol__cycles_hist(sym);
902 if (cycles_hist == NULL)
d4957633
AK
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;
c6b635ee 914 return __symbol__account_cycles(cycles_hist,
d4957633
AK
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{
3d7245b0 924 u64 saddr = 0;
d4957633
AK
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)
3d7245b0 943 pr_debug2("BB with bad start: addr %"PRIx64" start %"PRIx64" sym %"PRIx64" saddr %"PRIx64"\n",
d4957633
AK
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
f56c083b
ACM
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(&notes->lock);
996 for (offset = 0; offset < size; ++offset) {
997 struct cyc_hist *ch;
998
999 ch = &notes->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];
48659ebf 1006 if (al && ch->num_aggr) {
f56c083b 1007 al->cycles = ch->cycles_aggr / ch->num_aggr;
48659ebf
JY
1008 al->cycles_max = ch->cycles_max;
1009 al->cycles_min = ch->cycles_min;
1010 }
f56c083b
ACM
1011 notes->have_cycles = true;
1012 }
1013 }
1014 pthread_mutex_unlock(&notes->lock);
1015}
1016
bab89f6a 1017int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
e345f3bd 1018 struct perf_evsel *evsel)
0f4e7a24 1019{
e345f3bd 1020 return symbol__inc_addr_samples(ams->sym, ams->map, evsel, ams->al_addr, sample);
0f4e7a24
ACM
1021}
1022
bab89f6a 1023int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
e345f3bd 1024 struct perf_evsel *evsel, u64 ip)
f626adff 1025{
e345f3bd 1026 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evsel, ip, sample);
f626adff
ACM
1027}
1028
85a84e4f 1029static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms)
4f9d0325 1030{
75b49202 1031 dl->ins.ops = ins__find(arch, dl->ins.name);
4f9d0325 1032
75b49202 1033 if (!dl->ins.ops)
4f9d0325
ACM
1034 return;
1035
85a84e4f 1036 if (dl->ins.ops->parse && dl->ins.ops->parse(arch, &dl->ops, ms) < 0)
75b49202 1037 dl->ins.ops = NULL;
4f9d0325
ACM
1038}
1039
75b49202 1040static int disasm_line__parse(char *line, const char **namep, char **rawp)
7a997fe4 1041{
4597cf06 1042 char tmp, *name = ltrim(line);
7a997fe4
ACM
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;
4597cf06 1060 *rawp = ltrim(*rawp);
7a997fe4
ACM
1061
1062 return 0;
1063
1064out_free_name:
75b49202
ACM
1065 free((void *)namep);
1066 *namep = NULL;
7a997fe4
ACM
1067 return -1;
1068}
1069
ea07c5aa
JO
1070struct annotate_args {
1071 size_t privsize;
24fe7b88 1072 struct arch *arch;
85a84e4f 1073 struct map_symbol ms;
d03a686e 1074 struct perf_evsel *evsel;
380195e2 1075 struct annotation_options *options;
4748834f
JO
1076 s64 offset;
1077 char *line;
1078 int line_nr;
ea07c5aa
JO
1079};
1080
c835e191
JO
1081static void annotation_line__delete(struct annotation_line *al)
1082{
1083 void *ptr = (void *) al - al->privsize;
1084
8b4c74dc 1085 free_srcline(al->path);
c835e191
JO
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;
7e304557 1105 struct perf_evsel *evsel = args->evsel;
c835e191 1106 size_t size = privsize + sizeof(*al);
7e304557
JO
1107 int nr = 1;
1108
1109 if (perf_evsel__is_group_event(evsel))
1110 nr = evsel->nr_members;
1111
c2f938ba 1112 size += sizeof(al->data[0]) * nr;
c835e191
JO
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;
c2f938ba 1121 al->data_nr = nr;
c835e191
JO
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 */
4748834f 1139static struct disasm_line *disasm_line__new(struct annotate_args *args)
78f7defe 1140{
c835e191
JO
1141 struct disasm_line *dl = NULL;
1142 struct annotation_line *al;
1143 size_t privsize = args->privsize + offsetof(struct disasm_line, al);
78f7defe 1144
c835e191
JO
1145 al = annotation_line__new(args, privsize);
1146 if (al != NULL) {
1147 dl = disasm_line(al);
d5490b96
JO
1148
1149 if (dl->al.line == NULL)
058b4cc9 1150 goto out_delete;
5145418b 1151
4748834f 1152 if (args->offset != -1) {
d5490b96 1153 if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
5145418b
ACM
1154 goto out_free_line;
1155
85a84e4f 1156 disasm_line__init_ins(dl, args->arch, &args->ms);
5145418b 1157 }
78f7defe
ACM
1158 }
1159
29ed6e76 1160 return dl;
5145418b
ACM
1161
1162out_free_line:
d5490b96 1163 zfree(&dl->al.line);
058b4cc9 1164out_delete:
29ed6e76 1165 free(dl);
058b4cc9 1166 return NULL;
78f7defe
ACM
1167}
1168
29ed6e76 1169void disasm_line__free(struct disasm_line *dl)
78f7defe 1170{
75b49202
ACM
1171 if (dl->ins.ops && dl->ins.ops->free)
1172 dl->ins.ops->free(&dl->ops);
c46219ac
ACM
1173 else
1174 ins__delete(&dl->ops);
75b49202
ACM
1175 free((void *)dl->ins.name);
1176 dl->ins.name = NULL;
c835e191 1177 annotation_line__delete(&dl->al);
78f7defe
ACM
1178}
1179
5417072b
ACM
1180int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw)
1181{
75b49202 1182 if (raw || !dl->ins.ops)
648388ae 1183 return scnprintf(bf, size, "%-6s %s", dl->ins.name, dl->ops.raw);
5417072b 1184
75b49202 1185 return ins__scnprintf(&dl->ins, bf, size, &dl->ops);
5417072b
ACM
1186}
1187
82b9d7ff 1188static void annotation_line__add(struct annotation_line *al, struct list_head *head)
78f7defe 1189{
82b9d7ff 1190 list_add_tail(&al->node, head);
78f7defe
ACM
1191}
1192
c4c72436
JO
1193struct annotation_line *
1194annotation_line__next(struct annotation_line *pos, struct list_head *head)
78f7defe 1195{
c4c72436
JO
1196 list_for_each_entry_continue(pos, head, node)
1197 if (pos->offset >= 0)
78f7defe
ACM
1198 return pos;
1199
1200 return NULL;
1201}
1202
70fbe057
PZ
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
f48e7c40 1285static int disasm_line__print(struct disasm_line *dl, u64 start, int addr_fmt_width)
78f7defe 1286{
29971f9a
JO
1287 s64 offset = dl->al.offset;
1288 const u64 addr = start + offset;
1289 struct block_range *br;
1290
1291 br = block_range__find(addr);
f48e7c40 1292 color_fprintf(stdout, annotate__address_color(br), " %*" PRIx64 ":", addr_fmt_width, addr);
29971f9a
JO
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,
796ca33d
JO
1301 int max_lines, struct annotation_line *queue, int addr_fmt_width,
1302 int percent_type)
29971f9a
JO
1303{
1304 struct disasm_line *dl = container_of(al, struct disasm_line, al);
78f7defe
ACM
1305 static const char *prev_line;
1306 static const char *prev_color;
1307
29971f9a 1308 if (al->offset != -1) {
f681d593 1309 double max_percent = 0.0;
b1dd4432 1310 int i, nr_percent = 1;
78f7defe
ACM
1311 const char *color;
1312 struct annotation *notes = symbol__annotation(sym);
ce6f4fab 1313
c2f938ba 1314 for (i = 0; i < al->data_nr; i++) {
6d9f0c2d
JO
1315 double percent;
1316
1317 percent = annotation_data__percent(&al->data[i],
796ca33d 1318 percent_type);
78f7defe 1319
6d9f0c2d
JO
1320 if (percent > max_percent)
1321 max_percent = percent;
b1dd4432
NK
1322 }
1323
c2f938ba
JO
1324 if (al->data_nr > nr_percent)
1325 nr_percent = al->data_nr;
04d2600a 1326
b1dd4432 1327 if (max_percent < min_pcnt)
36532461
ACM
1328 return -1;
1329
e3087b80 1330 if (max_lines && printed >= max_lines)
36532461 1331 return 1;
d040bd36 1332
d5e3d747 1333 if (queue != NULL) {
29971f9a
JO
1334 list_for_each_entry_from(queue, &notes->src->source, node) {
1335 if (queue == al)
d5e3d747 1336 break;
29971f9a 1337 annotation_line__print(queue, sym, start, evsel, len,
796ca33d
JO
1338 0, 0, 1, NULL, addr_fmt_width,
1339 percent_type);
d5e3d747
ACM
1340 }
1341 }
1342
b1dd4432 1343 color = get_percent_color(max_percent);
78f7defe
ACM
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 */
29971f9a
JO
1350 if (al->path) {
1351 if (!prev_line || strcmp(prev_line, al->path)
78f7defe 1352 || color != prev_color) {
29971f9a
JO
1353 color_fprintf(stdout, color, " %s", al->path);
1354 prev_line = al->path;
78f7defe
ACM
1355 prev_color = color;
1356 }
1357 }
1358
b1dd4432 1359 for (i = 0; i < nr_percent; i++) {
0440af74 1360 struct annotation_data *data = &al->data[i];
6d9f0c2d 1361 double percent;
f681d593 1362
796ca33d 1363 percent = annotation_data__percent(data, percent_type);
6d9f0c2d 1364 color = get_percent_color(percent);
0c4a5bce
ML
1365
1366 if (symbol_conf.show_total_period)
ce9ee4a2 1367 color_fprintf(stdout, color, " %11" PRIu64,
0440af74 1368 data->he.period);
1ac39372
TS
1369 else if (symbol_conf.show_nr_samples)
1370 color_fprintf(stdout, color, " %7" PRIu64,
0440af74 1371 data->he.nr_samples);
0c4a5bce 1372 else
6d9f0c2d 1373 color_fprintf(stdout, color, " %7.2f", percent);
b1dd4432
NK
1374 }
1375
f48e7c40 1376 printf(" : ");
70fbe057 1377
f48e7c40 1378 disasm_line__print(dl, start, addr_fmt_width);
70fbe057 1379 printf("\n");
e3087b80 1380 } else if (max_lines && printed >= max_lines)
36532461
ACM
1381 return 1;
1382 else {
ce9ee4a2 1383 int width = symbol_conf.show_total_period ? 12 : 8;
b1dd4432 1384
d5e3d747
ACM
1385 if (queue)
1386 return -1;
1387
759ff497 1388 if (perf_evsel__is_group_event(evsel))
b1dd4432
NK
1389 width *= evsel->nr_members;
1390
29971f9a 1391 if (!*al->line)
b1dd4432 1392 printf(" %*s:\n", width, " ");
78f7defe 1393 else
f48e7c40 1394 printf(" %*s: %*s %s\n", width, " ", addr_fmt_width, " ", al->line);
78f7defe 1395 }
36532461
ACM
1396
1397 return 0;
78f7defe
ACM
1398}
1399
3aec150a
NK
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 */
1a04db70 1420static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
ea07c5aa 1421 struct annotate_args *args,
e592488c 1422 int *line_nr)
78f7defe 1423{
85a84e4f 1424 struct map *map = args->ms.map;
ce6f4fab 1425 struct annotation *notes = symbol__annotation(sym);
29ed6e76 1426 struct disasm_line *dl;
4597cf06 1427 char *line = NULL, *parsed_line, *tmp, *tmp2;
78f7defe
ACM
1428 size_t line_len;
1429 s64 line_ip, offset = -1;
e592488c 1430 regmatch_t match[2];
78f7defe
ACM
1431
1432 if (getline(&line, &line_len, file) < 0)
1433 return -1;
1434
1435 if (!line)
1436 return -1;
1437
78f7defe 1438 line_ip = -1;
4597cf06 1439 parsed_line = rtrim(line);
78f7defe 1440
e592488c 1441 /* /filename:linenr ? Save line number and ignore. */
986a5bc0
TS
1442 if (regexec(&file_lineno, parsed_line, 2, match, 0) == 0) {
1443 *line_nr = atoi(parsed_line + match[1].rm_so);
e592488c
AK
1444 return 0;
1445 }
1446
4597cf06 1447 tmp = ltrim(parsed_line);
78f7defe
ACM
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;
2c241bd3 1462 if ((u64)line_ip < start || (u64)line_ip >= end)
78f7defe 1463 offset = -1;
058b4cc9
ACM
1464 else
1465 parsed_line = tmp2 + 1;
a31b7cc0 1466 }
78f7defe 1467
4748834f
JO
1468 args->offset = offset;
1469 args->line = parsed_line;
1470 args->line_nr = *line_nr;
85a84e4f 1471 args->ms.sym = sym;
4748834f
JO
1472
1473 dl = disasm_line__new(args);
058b4cc9 1474 free(line);
e592488c 1475 (*line_nr)++;
058b4cc9 1476
29ed6e76 1477 if (dl == NULL)
78f7defe 1478 return -1;
058b4cc9 1479
2eff0611 1480 if (!disasm_line__has_local_offset(dl)) {
bbb7f846
AH
1481 dl->ops.target.offset = dl->ops.target.addr -
1482 map__rip_2objdump(map, sym->start);
e216874c
RB
1483 dl->ops.target.offset_avail = true;
1484 }
bbb7f846 1485
696703af
ACM
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) {
6e427ab0
AH
1488 struct addr_map_symbol target = {
1489 .map = map,
1490 .addr = dl->ops.target.addr,
1491 };
1492
be39db9f 1493 if (!map_groups__find_ams(&target) &&
6e427ab0 1494 target.sym->start == target.al_addr)
696703af 1495 dl->ops.target.sym = target.sym;
b178170a
AH
1496 }
1497
82b9d7ff 1498 annotation_line__add(&dl->al, &notes->src->source);
78f7defe
ACM
1499
1500 return 0;
1501}
1502
e592488c
AK
1503static __attribute__((constructor)) void symbol__init_regexpr(void)
1504{
1505 regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED);
1506}
1507
484a5e74
AH
1508static void delete_last_nop(struct symbol *sym)
1509{
1510 struct annotation *notes = symbol__annotation(sym);
1511 struct list_head *list = &notes->src->source;
1512 struct disasm_line *dl;
1513
1514 while (!list_empty(list)) {
a17c4ca0 1515 dl = list_entry(list->prev, struct disasm_line, al.node);
484a5e74 1516
75b49202
ACM
1517 if (dl->ins.ops) {
1518 if (dl->ins.ops != &nop_ops)
484a5e74
AH
1519 return;
1520 } else {
d5490b96
JO
1521 if (!strstr(dl->al.line, " nop ") &&
1522 !strstr(dl->al.line, " nopl ") &&
1523 !strstr(dl->al.line, " nopw "))
484a5e74
AH
1524 return;
1525 }
1526
a17c4ca0 1527 list_del(&dl->al.node);
484a5e74
AH
1528 disasm_line__free(dl);
1529 }
1530}
1531
ee51d851
ACM
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
05ed3ac9 1571static int dso__disassemble_filename(struct dso *dso, char *filename, size_t filename_size)
78f7defe 1572{
05ed3ac9
ACM
1573 char linkname[PATH_MAX];
1574 char *build_id_filename;
6ebd2547 1575 char *build_id_path = NULL;
3619ef76 1576 char *pos;
78f7defe 1577
c12944f7
ACM
1578 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1579 !dso__is_kcore(dso))
05ed3ac9 1580 return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
c12944f7 1581
d2396999 1582 build_id_filename = dso__build_id_filename(dso, NULL, 0, false);
05ed3ac9
ACM
1583 if (build_id_filename) {
1584 __symbol__join_symfs(filename, filename_size, build_id_filename);
1585 free(build_id_filename);
3caee094 1586 } else {
ee51d851
ACM
1587 if (dso->has_build_id)
1588 return ENOMEM;
78f7defe 1589 goto fallback;
3caee094
ACM
1590 }
1591
6ebd2547
TS
1592 build_id_path = strdup(filename);
1593 if (!build_id_path)
1594 return -1;
1595
3619ef76
NK
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);
6ebd2547 1604
3caee094 1605 if (dso__is_kcore(dso) ||
6ebd2547 1606 readlink(build_id_path, linkname, sizeof(linkname)) < 0 ||
05ed3ac9
ACM
1607 strstr(linkname, DSO__NAME_KALLSYMS) ||
1608 access(filename, R_OK)) {
78f7defe
ACM
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 */
05ed3ac9 1615 __symbol__join_symfs(filename, filename_size, dso->long_name);
78f7defe
ACM
1616 }
1617
6ebd2547 1618 free(build_id_path);
05ed3ac9
ACM
1619 return 0;
1620}
1621
1a04db70 1622static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
05ed3ac9 1623{
1eddd9e4 1624 struct annotation_options *opts = args->options;
85a84e4f 1625 struct map *map = args->ms.map;
05ed3ac9 1626 struct dso *dso = map->dso;
6810158d 1627 char *command;
05ed3ac9
ACM
1628 FILE *file;
1629 char symfs_filename[PATH_MAX];
1630 struct kcore_extract kce;
1631 bool delete_extract = false;
1632 int stdout_fd[2];
1633 int lineno = 0;
1634 int nline;
1635 pid_t pid;
1636 int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));
1637
1638 if (err)
1639 return err;
1640
78f7defe 1641 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
3caee094 1642 symfs_filename, sym->name, map->unmap_ip(map, sym->start),
78f7defe
ACM
1643 map->unmap_ip(map, sym->end));
1644
78f7defe
ACM
1645 pr_debug("annotating [%p] %30s : [%p] %30s\n",
1646 dso, dso->long_name, sym, sym->name);
1647
afba19d9
AH
1648 if (dso__is_kcore(dso)) {
1649 kce.kcore_filename = symfs_filename;
1650 kce.addr = map__rip_2objdump(map, sym->start);
1651 kce.offs = sym->start;
2c241bd3 1652 kce.len = sym->end - sym->start;
afba19d9
AH
1653 if (!kcore_extract__create(&kce)) {
1654 delete_extract = true;
1655 strlcpy(symfs_filename, kce.extract_filename,
1656 sizeof(symfs_filename));
afba19d9 1657 }
2c7da8c5 1658 } else if (dso__needs_decompress(dso)) {
3c84fd53 1659 char tmp[KMOD_DECOMP_LEN];
2c7da8c5 1660
3c84fd53
NK
1661 if (dso__decompress_kmodule_path(dso, symfs_filename,
1662 tmp, sizeof(tmp)) < 0)
3caee094 1663 goto out;
2c7da8c5
JO
1664
1665 strcpy(symfs_filename, tmp);
afba19d9
AH
1666 }
1667
6810158d 1668 err = asprintf(&command,
7a4ec938 1669 "%s %s%s --start-address=0x%016" PRIx64
3e6a2a7f 1670 " --stop-address=0x%016" PRIx64
7b4500bc 1671 " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
f178fd2d 1672 opts->objdump_path ?: "objdump",
a47e843e
ACM
1673 opts->disassembler_style ? "-M " : "",
1674 opts->disassembler_style ?: "",
78f7defe 1675 map__rip_2objdump(map, sym->start),
2c241bd3 1676 map__rip_2objdump(map, sym->end),
1eddd9e4
ACM
1677 opts->show_asm_raw ? "" : "--no-show-raw",
1678 opts->annotate_src ? "-S" : "",
3caee094 1679 symfs_filename, symfs_filename);
78f7defe 1680
6810158d
ACM
1681 if (err < 0) {
1682 pr_err("Failure allocating memory for the command to run\n");
1683 goto out_remove_tmp;
1684 }
1685
78f7defe
ACM
1686 pr_debug("Executing: %s\n", command);
1687
9955d0be
ACM
1688 err = -1;
1689 if (pipe(stdout_fd) < 0) {
1690 pr_err("Failure creating the pipe to run %s\n", command);
6810158d 1691 goto out_free_command;
9955d0be
ACM
1692 }
1693
1694 pid = fork();
1695 if (pid < 0) {
1696 pr_err("Failure forking to run %s\n", command);
1697 goto out_close_stdout;
1698 }
1699
1700 if (pid == 0) {
1701 close(stdout_fd[0]);
1702 dup2(stdout_fd[1], 1);
1703 close(stdout_fd[1]);
1704 execl("/bin/sh", "sh", "-c", command, NULL);
1705 perror(command);
1706 exit(-1);
1707 }
1708
1709 close(stdout_fd[1]);
1710
1711 file = fdopen(stdout_fd[0], "r");
62ec9b3f 1712 if (!file) {
9955d0be 1713 pr_err("Failure creating FILE stream for %s\n", command);
62ec9b3f
AK
1714 /*
1715 * If we were using debug info should retry with
1716 * original binary.
1717 */
6810158d 1718 goto out_free_command;
62ec9b3f 1719 }
78f7defe 1720
62ec9b3f
AK
1721 nline = 0;
1722 while (!feof(file)) {
ed7b339f
ACM
1723 /*
1724 * The source code line number (lineno) needs to be kept in
1725 * accross calls to symbol__parse_objdump_line(), so that it
1726 * can associate it with the instructions till the next one.
1727 * See disasm_line__new() and struct disasm_line::line_nr.
1728 */
1a04db70 1729 if (symbol__parse_objdump_line(sym, file, args, &lineno) < 0)
78f7defe 1730 break;
62ec9b3f
AK
1731 nline++;
1732 }
1733
1734 if (nline == 0)
1735 pr_err("No output from %s\n", command);
78f7defe 1736
484a5e74
AH
1737 /*
1738 * kallsyms does not have symbol sizes so there may a nop at the end.
1739 * Remove it.
1740 */
1741 if (dso__is_kcore(dso))
1742 delete_last_nop(sym);
1743
9955d0be
ACM
1744 fclose(file);
1745 err = 0;
6810158d
ACM
1746out_free_command:
1747 free(command);
2c7da8c5 1748out_remove_tmp:
9955d0be
ACM
1749 close(stdout_fd[0]);
1750
2c7da8c5
JO
1751 if (dso__needs_decompress(dso))
1752 unlink(symfs_filename);
3caee094 1753
afba19d9
AH
1754 if (delete_extract)
1755 kcore_extract__delete(&kce);
c12944f7 1756out:
78f7defe 1757 return err;
9955d0be
ACM
1758
1759out_close_stdout:
1760 close(stdout_fd[1]);
6810158d 1761 goto out_free_command;
78f7defe
ACM
1762}
1763
48a1e4f2 1764static void calc_percent(struct sym_hist *sym_hist,
75a8c1ff 1765 struct hists *hists,
0440af74 1766 struct annotation_data *data,
073ae601
JO
1767 s64 offset, s64 end)
1768{
1769 unsigned int hits = 0;
1770 u64 period = 0;
1771
1772 while (offset < end) {
48a1e4f2
JO
1773 hits += sym_hist->addr[offset].nr_samples;
1774 period += sym_hist->addr[offset].period;
073ae601
JO
1775 ++offset;
1776 }
1777
48a1e4f2 1778 if (sym_hist->nr_samples) {
0440af74
JO
1779 data->he.period = period;
1780 data->he.nr_samples = hits;
6d9f0c2d 1781 data->percent[PERCENT_HITS_LOCAL] = 100.0 * hits / sym_hist->nr_samples;
073ae601 1782 }
75a8c1ff
JO
1783
1784 if (hists->stats.nr_non_filtered_samples)
1785 data->percent[PERCENT_HITS_GLOBAL] = 100.0 * hits / hists->stats.nr_non_filtered_samples;
1786
ab371169
JO
1787 if (sym_hist->period)
1788 data->percent[PERCENT_PERIOD_LOCAL] = 100.0 * period / sym_hist->period;
e58684df
JO
1789
1790 if (hists->stats.total_period)
1791 data->percent[PERCENT_PERIOD_GLOBAL] = 100.0 * period / hists->stats.total_period;
073ae601
JO
1792}
1793
9e4e0a9d 1794static void annotation__calc_percent(struct annotation *notes,
2bcf7306 1795 struct perf_evsel *leader, s64 len)
073ae601
JO
1796{
1797 struct annotation_line *al, *next;
2bcf7306 1798 struct perf_evsel *evsel;
073ae601
JO
1799
1800 list_for_each_entry(al, &notes->src->source, node) {
1801 s64 end;
2bcf7306 1802 int i = 0;
073ae601
JO
1803
1804 if (al->offset == -1)
1805 continue;
1806
1807 next = annotation_line__next(al, &notes->src->source);
1808 end = next ? next->offset : len;
1809
2bcf7306 1810 for_each_group_evsel(evsel, leader) {
75a8c1ff 1811 struct hists *hists = evsel__hists(evsel);
0440af74 1812 struct annotation_data *data;
48a1e4f2 1813 struct sym_hist *sym_hist;
073ae601 1814
2bcf7306
JO
1815 BUG_ON(i >= al->data_nr);
1816
1817 sym_hist = annotation__histogram(notes, evsel->idx);
1818 data = &al->data[i++];
073ae601 1819
75a8c1ff 1820 calc_percent(sym_hist, hists, data, al->offset, end);
073ae601
JO
1821 }
1822 }
073ae601
JO
1823}
1824
9e4e0a9d 1825void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel)
073ae601
JO
1826{
1827 struct annotation *notes = symbol__annotation(sym);
1828
9e4e0a9d 1829 annotation__calc_percent(notes, evsel, symbol__size(sym));
073ae601
JO
1830}
1831
c34df25b 1832int symbol__annotate(struct symbol *sym, struct map *map,
d03a686e 1833 struct perf_evsel *evsel, size_t privsize,
380195e2 1834 struct annotation_options *options,
5449f13c 1835 struct arch **parch)
c34df25b 1836{
ea07c5aa
JO
1837 struct annotate_args args = {
1838 .privsize = privsize,
d03a686e 1839 .evsel = evsel,
380195e2 1840 .options = options,
ea07c5aa 1841 };
5449f13c 1842 struct perf_env *env = perf_evsel__env(evsel);
3285deba 1843 const char *arch_name = perf_env__arch(env);
c34df25b
JO
1844 struct arch *arch;
1845 int err;
1846
c34df25b
JO
1847 if (!arch_name)
1848 return -1;
1849
24fe7b88 1850 args.arch = arch = arch__find(arch_name);
c34df25b
JO
1851 if (arch == NULL)
1852 return -ENOTSUP;
1853
1854 if (parch)
1855 *parch = arch;
1856
1857 if (arch->init) {
5449f13c 1858 err = arch->init(arch, env ? env->cpuid : NULL);
c34df25b
JO
1859 if (err) {
1860 pr_err("%s: failed to initialize %s arch priv area\n", __func__, arch->name);
1861 return err;
1862 }
1863 }
1864
85a84e4f
ACM
1865 args.ms.map = map;
1866 args.ms.sym = sym;
1867
05d3f1a1 1868 return symbol__disassemble(sym, &args);
c34df25b
JO
1869}
1870
c849c12c
JO
1871static void insert_source_line(struct rb_root *root, struct annotation_line *al,
1872 struct annotation_options *opts)
78f7defe 1873{
8b4c74dc 1874 struct annotation_line *iter;
78f7defe
ACM
1875 struct rb_node **p = &root->rb_node;
1876 struct rb_node *parent = NULL;
1491c22a 1877 int i, ret;
78f7defe
ACM
1878
1879 while (*p != NULL) {
1880 parent = *p;
8b4c74dc 1881 iter = rb_entry(parent, struct annotation_line, rb_node);
78f7defe 1882
8b4c74dc 1883 ret = strcmp(iter->path, al->path);
41127965 1884 if (ret == 0) {
6d9f0c2d
JO
1885 for (i = 0; i < al->data_nr; i++) {
1886 iter->data[i].percent_sum += annotation_data__percent(&al->data[i],
c849c12c 1887 opts->percent_type);
6d9f0c2d 1888 }
41127965
NK
1889 return;
1890 }
1891
1892 if (ret < 0)
1893 p = &(*p)->rb_left;
1894 else
1895 p = &(*p)->rb_right;
1896 }
1897
6d9f0c2d
JO
1898 for (i = 0; i < al->data_nr; i++) {
1899 al->data[i].percent_sum = annotation_data__percent(&al->data[i],
c849c12c 1900 opts->percent_type);
6d9f0c2d 1901 }
41127965 1902
8b4c74dc
JO
1903 rb_link_node(&al->rb_node, parent, p);
1904 rb_insert_color(&al->rb_node, root);
41127965
NK
1905}
1906
8b4c74dc 1907static int cmp_source_line(struct annotation_line *a, struct annotation_line *b)
1491c22a
NK
1908{
1909 int i;
1910
c2f938ba
JO
1911 for (i = 0; i < a->data_nr; i++) {
1912 if (a->data[i].percent_sum == b->data[i].percent_sum)
1491c22a 1913 continue;
c2f938ba 1914 return a->data[i].percent_sum > b->data[i].percent_sum;
1491c22a
NK
1915 }
1916
1917 return 0;
1918}
1919
8b4c74dc 1920static void __resort_source_line(struct rb_root *root, struct annotation_line *al)
41127965 1921{
8b4c74dc 1922 struct annotation_line *iter;
41127965
NK
1923 struct rb_node **p = &root->rb_node;
1924 struct rb_node *parent = NULL;
1925
1926 while (*p != NULL) {
1927 parent = *p;
8b4c74dc 1928 iter = rb_entry(parent, struct annotation_line, rb_node);
41127965 1929
8b4c74dc 1930 if (cmp_source_line(al, iter))
78f7defe
ACM
1931 p = &(*p)->rb_left;
1932 else
1933 p = &(*p)->rb_right;
1934 }
1935
8b4c74dc
JO
1936 rb_link_node(&al->rb_node, parent, p);
1937 rb_insert_color(&al->rb_node, root);
78f7defe
ACM
1938}
1939
41127965
NK
1940static void resort_source_line(struct rb_root *dest_root, struct rb_root *src_root)
1941{
8b4c74dc 1942 struct annotation_line *al;
41127965
NK
1943 struct rb_node *node;
1944
1945 node = rb_first(src_root);
1946 while (node) {
1947 struct rb_node *next;
1948
8b4c74dc 1949 al = rb_entry(node, struct annotation_line, rb_node);
41127965
NK
1950 next = rb_next(node);
1951 rb_erase(node, src_root);
1952
8b4c74dc 1953 __resort_source_line(dest_root, al);
41127965
NK
1954 node = next;
1955 }
1956}
1957
78f7defe
ACM
1958static void print_summary(struct rb_root *root, const char *filename)
1959{
8b4c74dc 1960 struct annotation_line *al;
78f7defe
ACM
1961 struct rb_node *node;
1962
1963 printf("\nSorted summary for file %s\n", filename);
1964 printf("----------------------------------------------\n\n");
1965
1966 if (RB_EMPTY_ROOT(root)) {
1967 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
1968 return;
1969 }
1970
1971 node = rb_first(root);
1972 while (node) {
1491c22a 1973 double percent, percent_max = 0.0;
78f7defe
ACM
1974 const char *color;
1975 char *path;
1491c22a 1976 int i;
78f7defe 1977
8b4c74dc 1978 al = rb_entry(node, struct annotation_line, rb_node);
c2f938ba
JO
1979 for (i = 0; i < al->data_nr; i++) {
1980 percent = al->data[i].percent_sum;
1491c22a
NK
1981 color = get_percent_color(percent);
1982 color_fprintf(stdout, color, " %7.2f", percent);
1983
1984 if (percent > percent_max)
1985 percent_max = percent;
1986 }
1987
8b4c74dc 1988 path = al->path;
1491c22a 1989 color = get_percent_color(percent_max);
f048d548 1990 color_fprintf(stdout, color, " %s\n", path);
78f7defe 1991
78f7defe
ACM
1992 node = rb_next(node);
1993 }
1994}
1995
db8fd07a 1996static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
78f7defe
ACM
1997{
1998 struct annotation *notes = symbol__annotation(sym);
db8fd07a 1999 struct sym_hist *h = annotation__histogram(notes, evsel->idx);
1b2e2df4 2000 u64 len = symbol__size(sym), offset;
78f7defe
ACM
2001
2002 for (offset = 0; offset < len; ++offset)
896bccd3 2003 if (h->addr[offset].nr_samples != 0)
78f7defe 2004 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
896bccd3 2005 sym->start + offset, h->addr[offset].nr_samples);
8158683d 2006 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->nr_samples", h->nr_samples);
78f7defe
ACM
2007}
2008
f48e7c40
JO
2009static int annotated_source__addr_fmt_width(struct list_head *lines, u64 start)
2010{
2011 char bf[32];
2012 struct annotation_line *line;
2013
2014 list_for_each_entry_reverse(line, lines, node) {
2015 if (line->offset != -1)
2016 return scnprintf(bf, sizeof(bf), "%" PRIx64, start + line->offset);
2017 }
2018
2019 return 0;
2020}
2021
db8fd07a 2022int symbol__annotate_printf(struct symbol *sym, struct map *map,
982d410b
ACM
2023 struct perf_evsel *evsel,
2024 struct annotation_options *opts)
78f7defe
ACM
2025{
2026 struct dso *dso = map->dso;
bfd14b9a
DA
2027 char *filename;
2028 const char *d_filename;
9cdbadce 2029 const char *evsel_name = perf_evsel__name(evsel);
ce6f4fab 2030 struct annotation *notes = symbol__annotation(sym);
135cce1b 2031 struct sym_hist *h = annotation__histogram(notes, evsel->idx);
8f25b819 2032 struct annotation_line *pos, *queue = NULL;
058b4cc9 2033 u64 start = map__rip_2objdump(map, sym->start);
f48e7c40 2034 int printed = 2, queue_len = 0, addr_fmt_width;
36532461 2035 int more = 0;
982d410b 2036 bool context = opts->context;
78f7defe 2037 u64 len;
ce9ee4a2 2038 int width = symbol_conf.show_total_period ? 12 : 8;
53dd9b5f 2039 int graph_dotted_len;
787e4da9 2040 char buf[512];
78f7defe 2041
bfd14b9a
DA
2042 filename = strdup(dso->long_name);
2043 if (!filename)
2044 return -ENOMEM;
2045
982d410b 2046 if (opts->full_path)
78f7defe
ACM
2047 d_filename = filename;
2048 else
2049 d_filename = basename(filename);
2050
1b2e2df4 2051 len = symbol__size(sym);
b1dd4432 2052
787e4da9 2053 if (perf_evsel__is_group_event(evsel)) {
b1dd4432 2054 width *= evsel->nr_members;
787e4da9
JY
2055 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2056 evsel_name = buf;
2057 }
78f7defe 2058
135cce1b 2059 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n",
1ac39372
TS
2060 width, width, symbol_conf.show_total_period ? "Period" :
2061 symbol_conf.show_nr_samples ? "Samples" : "Percent",
38d2dcd0 2062 d_filename, evsel_name, h->nr_samples);
9cdbadce 2063
53dd9b5f 2064 printf("%-*.*s----\n",
9cdbadce 2065 graph_dotted_len, graph_dotted_len, graph_dotted_line);
78f7defe 2066
bb963e16 2067 if (verbose > 0)
db8fd07a 2068 symbol__annotate_hits(sym, evsel);
78f7defe 2069
f48e7c40
JO
2070 addr_fmt_width = annotated_source__addr_fmt_width(&notes->src->source, start);
2071
8f25b819
JO
2072 list_for_each_entry(pos, &notes->src->source, node) {
2073 int err;
2074
d5e3d747
ACM
2075 if (context && queue == NULL) {
2076 queue = pos;
2077 queue_len = 0;
2078 }
2079
8f25b819 2080 err = annotation_line__print(pos, sym, start, evsel, len,
982d410b 2081 opts->min_pcnt, printed, opts->max_lines,
796ca33d 2082 queue, addr_fmt_width, opts->percent_type);
8f25b819
JO
2083
2084 switch (err) {
36532461
ACM
2085 case 0:
2086 ++printed;
d5e3d747
ACM
2087 if (context) {
2088 printed += queue_len;
2089 queue = NULL;
2090 queue_len = 0;
2091 }
36532461
ACM
2092 break;
2093 case 1:
2094 /* filtered by max_lines */
2095 ++more;
d040bd36 2096 break;
36532461
ACM
2097 case -1:
2098 default:
d5e3d747
ACM
2099 /*
2100 * Filtered by min_pcnt or non IP lines when
2101 * context != 0
2102 */
2103 if (!context)
2104 break;
2105 if (queue_len == context)
8f25b819 2106 queue = list_entry(queue->node.next, typeof(*queue), node);
d5e3d747
ACM
2107 else
2108 ++queue_len;
36532461
ACM
2109 break;
2110 }
2111 }
2112
bfd14b9a
DA
2113 free(filename);
2114
36532461
ACM
2115 return more;
2116}
f1e2701d 2117
befd2a38
ACM
2118static void FILE__set_percent_color(void *fp __maybe_unused,
2119 double percent __maybe_unused,
2120 bool current __maybe_unused)
2121{
2122}
2123
2124static int FILE__set_jumps_percent_color(void *fp __maybe_unused,
2125 int nr __maybe_unused, bool current __maybe_unused)
2126{
2127 return 0;
2128}
2129
2130static int FILE__set_color(void *fp __maybe_unused, int color __maybe_unused)
2131{
2132 return 0;
2133}
2134
2135static void FILE__printf(void *fp, const char *fmt, ...)
2136{
2137 va_list args;
2138
2139 va_start(args, fmt);
2140 vfprintf(fp, fmt, args);
2141 va_end(args);
2142}
2143
2144static void FILE__write_graph(void *fp, int graph)
2145{
2146 const char *s;
2147 switch (graph) {
2148
2149 case DARROW_CHAR: s = "↓"; break;
2150 case UARROW_CHAR: s = "↑"; break;
2151 case LARROW_CHAR: s = "←"; break;
2152 case RARROW_CHAR: s = "→"; break;
2153 default: s = "?"; break;
2154 }
2155
2156 fputs(s, fp);
2157}
2158
4c650ddc
JO
2159static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp,
2160 struct annotation_options *opts)
befd2a38
ACM
2161{
2162 struct annotation *notes = symbol__annotation(sym);
4c650ddc 2163 struct annotation_write_ops wops = {
befd2a38
ACM
2164 .first_line = true,
2165 .obj = fp,
2166 .set_color = FILE__set_color,
2167 .set_percent_color = FILE__set_percent_color,
2168 .set_jumps_percent_color = FILE__set_jumps_percent_color,
2169 .printf = FILE__printf,
2170 .write_graph = FILE__write_graph,
2171 };
2172 struct annotation_line *al;
2173
2174 list_for_each_entry(al, &notes->src->source, node) {
2175 if (annotation_line__filter(al, notes))
2176 continue;
4c650ddc 2177 annotation_line__write(al, notes, &wops, opts);
befd2a38 2178 fputc('\n', fp);
4c650ddc 2179 wops.first_line = false;
befd2a38
ACM
2180 }
2181
2182 return 0;
2183}
2184
4c650ddc
JO
2185int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel,
2186 struct annotation_options *opts)
d9bd7665
ACM
2187{
2188 const char *ev_name = perf_evsel__name(evsel);
2189 char buf[1024];
2190 char *filename;
2191 int err = -1;
2192 FILE *fp;
2193
2194 if (asprintf(&filename, "%s.annotation", ms->sym->name) < 0)
2195 return -1;
2196
2197 fp = fopen(filename, "w");
2198 if (fp == NULL)
2199 goto out_free_filename;
2200
2201 if (perf_evsel__is_group_event(evsel)) {
2202 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2203 ev_name = buf;
2204 }
2205
2206 fprintf(fp, "%s() %s\nEvent: %s\n\n",
2207 ms->sym->name, ms->map->dso->long_name, ev_name);
4c650ddc 2208 symbol__annotate_fprintf2(ms->sym, fp, opts);
d9bd7665
ACM
2209
2210 fclose(fp);
2211 err = 0;
2212out_free_filename:
2213 free(filename);
2214 return err;
2215}
2216
36532461
ACM
2217void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
2218{
2219 struct annotation *notes = symbol__annotation(sym);
2220 struct sym_hist *h = annotation__histogram(notes, evidx);
2221
ce6f4fab 2222 memset(h, 0, notes->src->sizeof_sym_hist);
36532461
ACM
2223}
2224
ce6f4fab 2225void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
36532461
ACM
2226{
2227 struct annotation *notes = symbol__annotation(sym);
2228 struct sym_hist *h = annotation__histogram(notes, evidx);
1b2e2df4 2229 int len = symbol__size(sym), offset;
36532461 2230
8158683d 2231 h->nr_samples = 0;
8b84a568 2232 for (offset = 0; offset < len; ++offset) {
896bccd3 2233 h->addr[offset].nr_samples = h->addr[offset].nr_samples * 7 / 8;
8158683d 2234 h->nr_samples += h->addr[offset].nr_samples;
f1e2701d
ACM
2235 }
2236}
2237
f8eb37bd 2238void annotated_source__purge(struct annotated_source *as)
f1e2701d 2239{
f8eb37bd 2240 struct annotation_line *al, *n;
f1e2701d 2241
f8eb37bd
JO
2242 list_for_each_entry_safe(al, n, &as->source, node) {
2243 list_del(&al->node);
2244 disasm_line__free(disasm_line(al));
f1e2701d
ACM
2245 }
2246}
2247
5145418b
ACM
2248static size_t disasm_line__fprintf(struct disasm_line *dl, FILE *fp)
2249{
2250 size_t printed;
2251
d5490b96
JO
2252 if (dl->al.offset == -1)
2253 return fprintf(fp, "%s\n", dl->al.line);
5145418b 2254
d5490b96 2255 printed = fprintf(fp, "%#" PRIx64 " %s", dl->al.offset, dl->ins.name);
5145418b 2256
c7e6ead7 2257 if (dl->ops.raw[0] != '\0') {
5145418b 2258 printed += fprintf(fp, "%.*s %s\n", 6 - (int)printed, " ",
c7e6ead7 2259 dl->ops.raw);
5145418b
ACM
2260 }
2261
2262 return printed + fprintf(fp, "\n");
2263}
2264
2265size_t disasm__fprintf(struct list_head *head, FILE *fp)
2266{
2267 struct disasm_line *pos;
2268 size_t printed = 0;
2269
a17c4ca0 2270 list_for_each_entry(pos, head, al.node)
5145418b
ACM
2271 printed += disasm_line__fprintf(pos, fp);
2272
2273 return printed;
2274}
2275
2eff0611 2276bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym)
0db45bcf
ACM
2277{
2278 if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) ||
2eff0611 2279 !disasm_line__has_local_offset(dl) || dl->ops.target.offset < 0 ||
0db45bcf
ACM
2280 dl->ops.target.offset >= (s64)symbol__size(sym))
2281 return false;
2282
2283 return true;
2284}
2285
2286void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym)
2287{
2288 u64 offset, size = symbol__size(sym);
2289
2290 /* PLT symbols contain external offsets */
2291 if (strstr(sym->name, "@plt"))
2292 return;
2293
2294 for (offset = 0; offset < size; ++offset) {
2295 struct annotation_line *al = notes->offsets[offset];
2296 struct disasm_line *dl;
2297
2298 dl = disasm_line(al);
2299
2eff0611 2300 if (!disasm_line__is_valid_local_jump(dl, sym))
0db45bcf
ACM
2301 continue;
2302
2303 al = notes->offsets[dl->ops.target.offset];
2304
2305 /*
2306 * FIXME: Oops, no jump target? Buggy disassembler? Or do we
2307 * have to adjust to the previous offset?
2308 */
2309 if (al == NULL)
2310 continue;
2311
2312 if (++al->jump_sources > notes->max_jump_sources)
2313 notes->max_jump_sources = al->jump_sources;
2314
2315 ++notes->nr_jumps;
2316 }
2317}
2318
5bc49f61
ACM
2319void annotation__set_offsets(struct annotation *notes, s64 size)
2320{
2321 struct annotation_line *al;
2322
2323 notes->max_line_len = 0;
2324
2325 list_for_each_entry(al, &notes->src->source, node) {
2326 size_t line_len = strlen(al->line);
2327
2328 if (notes->max_line_len < line_len)
2329 notes->max_line_len = line_len;
2330 al->idx = notes->nr_entries++;
2331 if (al->offset != -1) {
2332 al->idx_asm = notes->nr_asm_entries++;
2333 /*
2334 * FIXME: short term bandaid to cope with assembly
2335 * routines that comes with labels in the same column
2336 * as the address in objdump, sigh.
2337 *
2338 * E.g. copy_user_generic_unrolled
2339 */
2340 if (al->offset < size)
2341 notes->offsets[al->offset] = al;
2342 } else
2343 al->idx_asm = -1;
2344 }
2345}
2346
b8b0d819
ACM
2347static inline int width_jumps(int n)
2348{
2349 if (n >= 100)
2350 return 5;
2351 if (n / 10)
2352 return 2;
2353 return 1;
2354}
2355
2356void annotation__init_column_widths(struct annotation *notes, struct symbol *sym)
2357{
2358 notes->widths.addr = notes->widths.target =
2359 notes->widths.min_addr = hex_width(symbol__size(sym));
2360 notes->widths.max_addr = hex_width(sym->end);
2361 notes->widths.jumps = width_jumps(notes->max_jump_sources);
2362}
2363
7232bf7a
ACM
2364void annotation__update_column_widths(struct annotation *notes)
2365{
2366 if (notes->options->use_offset)
2367 notes->widths.target = notes->widths.min_addr;
2368 else
2369 notes->widths.target = notes->widths.max_addr;
2370
2371 notes->widths.addr = notes->widths.target;
2372
2373 if (notes->options->show_nr_jumps)
2374 notes->widths.addr += notes->widths.jumps + 1;
2375}
2376
8b4c74dc 2377static void annotation__calc_lines(struct annotation *notes, struct map *map,
c849c12c
JO
2378 struct rb_root *root,
2379 struct annotation_options *opts)
8b4c74dc
JO
2380{
2381 struct annotation_line *al;
2382 struct rb_root tmp_root = RB_ROOT;
2383
2384 list_for_each_entry(al, &notes->src->source, node) {
2385 double percent_max = 0.0;
2386 int i;
2387
c2f938ba 2388 for (i = 0; i < al->data_nr; i++) {
6d9f0c2d 2389 double percent;
8b4c74dc 2390
6d9f0c2d 2391 percent = annotation_data__percent(&al->data[i],
c849c12c 2392 opts->percent_type);
8b4c74dc 2393
6d9f0c2d
JO
2394 if (percent > percent_max)
2395 percent_max = percent;
8b4c74dc
JO
2396 }
2397
2398 if (percent_max <= 0.5)
2399 continue;
2400
425859ff
ACM
2401 al->path = get_srcline(map->dso, notes->start + al->offset, NULL,
2402 false, true, notes->start + al->offset);
c849c12c 2403 insert_source_line(&tmp_root, al, opts);
8b4c74dc
JO
2404 }
2405
2406 resort_source_line(root, &tmp_root);
2407}
2408
2409static void symbol__calc_lines(struct symbol *sym, struct map *map,
c849c12c
JO
2410 struct rb_root *root,
2411 struct annotation_options *opts)
8b4c74dc
JO
2412{
2413 struct annotation *notes = symbol__annotation(sym);
8b4c74dc 2414
c849c12c 2415 annotation__calc_lines(notes, map, root, opts);
8b4c74dc
JO
2416}
2417
befd2a38 2418int symbol__tty_annotate2(struct symbol *sym, struct map *map,
982d410b
ACM
2419 struct perf_evsel *evsel,
2420 struct annotation_options *opts)
befd2a38
ACM
2421{
2422 struct dso *dso = map->dso;
2423 struct rb_root source_line = RB_ROOT;
0683d13c 2424 struct hists *hists = evsel__hists(evsel);
864298f2 2425 char buf[1024];
befd2a38 2426
982d410b 2427 if (symbol__annotate2(sym, map, evsel, opts, NULL) < 0)
befd2a38
ACM
2428 return -1;
2429
982d410b
ACM
2430 if (opts->print_lines) {
2431 srcline_full_filename = opts->full_path;
c849c12c 2432 symbol__calc_lines(sym, map, &source_line, opts);
befd2a38
ACM
2433 print_summary(&source_line, dso->long_name);
2434 }
2435
0683d13c 2436 hists__scnprintf_title(hists, buf, sizeof(buf));
520d3f01 2437 fprintf(stdout, "%s\n%s() %s\n", buf, sym->name, dso->long_name);
4c650ddc 2438 symbol__annotate_fprintf2(sym, stdout, opts);
befd2a38
ACM
2439
2440 annotated_source__purge(symbol__annotation(sym)->src);
2441
2442 return 0;
2443}
2444
db8fd07a 2445int symbol__tty_annotate(struct symbol *sym, struct map *map,
982d410b
ACM
2446 struct perf_evsel *evsel,
2447 struct annotation_options *opts)
f1e2701d
ACM
2448{
2449 struct dso *dso = map->dso;
f1e2701d 2450 struct rb_root source_line = RB_ROOT;
f1e2701d 2451
380195e2 2452 if (symbol__annotate(sym, map, evsel, 0, opts, NULL) < 0)
f1e2701d
ACM
2453 return -1;
2454
05d3f1a1
JO
2455 symbol__calc_percent(sym, evsel);
2456
982d410b
ACM
2457 if (opts->print_lines) {
2458 srcline_full_filename = opts->full_path;
c849c12c 2459 symbol__calc_lines(sym, map, &source_line, opts);
86c98cab 2460 print_summary(&source_line, dso->long_name);
78f7defe
ACM
2461 }
2462
982d410b 2463 symbol__annotate_printf(sym, map, evsel, opts);
78f7defe 2464
f8eb37bd 2465 annotated_source__purge(symbol__annotation(sym)->src);
f1e2701d 2466
78f7defe
ACM
2467 return 0;
2468}
f626adff 2469
48c65bda
NK
2470bool ui__has_annotation(void)
2471{
2e0453af 2472 return use_browser == 1 && perf_hpp_list.sym;
48c65bda 2473}
ecda45bd 2474
2f025ea0 2475
5ecf7d30 2476static double annotation_line__max_percent(struct annotation_line *al,
4c650ddc
JO
2477 struct annotation *notes,
2478 unsigned int percent_type)
2f025ea0
ACM
2479{
2480 double percent_max = 0.0;
2481 int i;
2482
2483 for (i = 0; i < notes->nr_events; i++) {
6d9f0c2d
JO
2484 double percent;
2485
2486 percent = annotation_data__percent(&al->data[i],
4c650ddc 2487 percent_type);
6d9f0c2d
JO
2488
2489 if (percent > percent_max)
2490 percent_max = percent;
2f025ea0
ACM
2491 }
2492
2493 return percent_max;
2494}
2495
a1e9b74c
ACM
2496static void disasm_line__write(struct disasm_line *dl, struct annotation *notes,
2497 void *obj, char *bf, size_t size,
2498 void (*obj__printf)(void *obj, const char *fmt, ...),
2499 void (*obj__write_graph)(void *obj, int graph))
2500{
2501 if (dl->ins.ops && dl->ins.ops->scnprintf) {
2502 if (ins__is_jump(&dl->ins)) {
751b1783 2503 bool fwd;
a1e9b74c 2504
751b1783
ACM
2505 if (dl->ops.target.outside)
2506 goto call_like;
2507 fwd = dl->ops.target.offset > dl->al.offset;
a1e9b74c
ACM
2508 obj__write_graph(obj, fwd ? DARROW_CHAR : UARROW_CHAR);
2509 obj__printf(obj, " ");
2510 } else if (ins__is_call(&dl->ins)) {
751b1783 2511call_like:
a1e9b74c
ACM
2512 obj__write_graph(obj, RARROW_CHAR);
2513 obj__printf(obj, " ");
2514 } else if (ins__is_ret(&dl->ins)) {
2515 obj__write_graph(obj, LARROW_CHAR);
2516 obj__printf(obj, " ");
2517 } else {
2518 obj__printf(obj, " ");
2519 }
2520 } else {
2521 obj__printf(obj, " ");
2522 }
2523
2524 disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset);
2525}
2526
c298304b
ACM
2527static void __annotation_line__write(struct annotation_line *al, struct annotation *notes,
2528 bool first_line, bool current_entry, bool change_color, int width,
4c650ddc 2529 void *obj, unsigned int percent_type,
c298304b
ACM
2530 int (*obj__set_color)(void *obj, int color),
2531 void (*obj__set_percent_color)(void *obj, double percent, bool current),
2532 int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current),
2533 void (*obj__printf)(void *obj, const char *fmt, ...),
2534 void (*obj__write_graph)(void *obj, int graph))
2535
2ba5eca1 2536{
4c650ddc 2537 double percent_max = annotation_line__max_percent(al, notes, percent_type);
a1e9b74c
ACM
2538 int pcnt_width = annotation__pcnt_width(notes),
2539 cycles_width = annotation__cycles_width(notes);
2ba5eca1 2540 bool show_title = false;
a1e9b74c
ACM
2541 char bf[256];
2542 int printed;
2ba5eca1
ACM
2543
2544 if (first_line && (al->offset == -1 || percent_max == 0.0)) {
2545 if (notes->have_cycles) {
2546 if (al->ipc == 0.0 && al->cycles == 0)
2547 show_title = true;
2548 } else
2549 show_title = true;
2550 }
2551
2ba5eca1
ACM
2552 if (al->offset != -1 && percent_max != 0.0) {
2553 int i;
2554
2555 for (i = 0; i < notes->nr_events; i++) {
6d9f0c2d
JO
2556 double percent;
2557
4c650ddc 2558 percent = annotation_data__percent(&al->data[i], percent_type);
6d9f0c2d
JO
2559
2560 obj__set_percent_color(obj, percent, current_entry);
2ba5eca1 2561 if (notes->options->show_total_period) {
c2f938ba 2562 obj__printf(obj, "%11" PRIu64 " ", al->data[i].he.period);
2ba5eca1
ACM
2563 } else if (notes->options->show_nr_samples) {
2564 obj__printf(obj, "%6" PRIu64 " ",
c2f938ba 2565 al->data[i].he.nr_samples);
2ba5eca1 2566 } else {
6d9f0c2d 2567 obj__printf(obj, "%6.2f ", percent);
2ba5eca1
ACM
2568 }
2569 }
2570 } else {
2ba5eca1
ACM
2571 obj__set_percent_color(obj, 0, current_entry);
2572
2573 if (!show_title)
a1e9b74c 2574 obj__printf(obj, "%-*s", pcnt_width, " ");
2ba5eca1 2575 else {
a1e9b74c 2576 obj__printf(obj, "%-*s", pcnt_width,
2ba5eca1
ACM
2577 notes->options->show_total_period ? "Period" :
2578 notes->options->show_nr_samples ? "Samples" : "Percent");
2579 }
2580 }
2581
2582 if (notes->have_cycles) {
2583 if (al->ipc)
2584 obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc);
2585 else if (!show_title)
2586 obj__printf(obj, "%*s", ANNOTATION__IPC_WIDTH, " ");
2587 else
2588 obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
2589
3e71fc03
JY
2590 if (!notes->options->show_minmax_cycle) {
2591 if (al->cycles)
2592 obj__printf(obj, "%*" PRIu64 " ",
2ba5eca1 2593 ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
3e71fc03
JY
2594 else if (!show_title)
2595 obj__printf(obj, "%*s",
2596 ANNOTATION__CYCLES_WIDTH, " ");
2597 else
2598 obj__printf(obj, "%*s ",
2599 ANNOTATION__CYCLES_WIDTH - 1,
2600 "Cycle");
2601 } else {
2602 if (al->cycles) {
2603 char str[32];
2604
2605 scnprintf(str, sizeof(str),
2606 "%" PRIu64 "(%" PRIu64 "/%" PRIu64 ")",
2607 al->cycles, al->cycles_min,
2608 al->cycles_max);
2609
2610 obj__printf(obj, "%*s ",
2611 ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
2612 str);
2613 } else if (!show_title)
2614 obj__printf(obj, "%*s",
2615 ANNOTATION__MINMAX_CYCLES_WIDTH,
2616 " ");
2617 else
2618 obj__printf(obj, "%*s ",
2619 ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
2620 "Cycle(min/max)");
2621 }
2ba5eca1
ACM
2622 }
2623
2624 obj__printf(obj, " ");
a1e9b74c
ACM
2625
2626 if (!*al->line)
2627 obj__printf(obj, "%-*s", width - pcnt_width - cycles_width, " ");
2628 else if (al->offset == -1) {
2629 if (al->line_nr && notes->options->show_linenr)
2630 printed = scnprintf(bf, sizeof(bf), "%-*d ", notes->widths.addr + 1, al->line_nr);
2631 else
2632 printed = scnprintf(bf, sizeof(bf), "%-*s ", notes->widths.addr, " ");
2633 obj__printf(obj, bf);
2634 obj__printf(obj, "%-*s", width - printed - pcnt_width - cycles_width + 1, al->line);
2635 } else {
2636 u64 addr = al->offset;
2637 int color = -1;
2638
2639 if (!notes->options->use_offset)
2640 addr += notes->start;
2641
2642 if (!notes->options->use_offset) {
2643 printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
2644 } else {
592c10e2
ACM
2645 if (al->jump_sources &&
2646 notes->options->offset_level >= ANNOTATION__OFFSET_JUMP_TARGETS) {
a1e9b74c
ACM
2647 if (notes->options->show_nr_jumps) {
2648 int prev;
2649 printed = scnprintf(bf, sizeof(bf), "%*d ",
2650 notes->widths.jumps,
2651 al->jump_sources);
2652 prev = obj__set_jumps_percent_color(obj, al->jump_sources,
2653 current_entry);
2654 obj__printf(obj, bf);
2655 obj__set_color(obj, prev);
2656 }
592c10e2 2657print_addr:
a1e9b74c
ACM
2658 printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
2659 notes->widths.target, addr);
592c10e2
ACM
2660 } else if (ins__is_call(&disasm_line(al)->ins) &&
2661 notes->options->offset_level >= ANNOTATION__OFFSET_CALL) {
2662 goto print_addr;
2663 } else if (notes->options->offset_level == ANNOTATION__MAX_OFFSET_LEVEL) {
2664 goto print_addr;
a1e9b74c
ACM
2665 } else {
2666 printed = scnprintf(bf, sizeof(bf), "%-*s ",
2667 notes->widths.addr, " ");
2668 }
2669 }
2670
2671 if (change_color)
2672 color = obj__set_color(obj, HE_COLORSET_ADDR);
2673 obj__printf(obj, bf);
2674 if (change_color)
2675 obj__set_color(obj, color);
2676
2677 disasm_line__write(disasm_line(al), notes, obj, bf, sizeof(bf), obj__printf, obj__write_graph);
2678
2679 obj__printf(obj, "%-*s", width - pcnt_width - cycles_width - 3 - printed, bf);
2680 }
2681
2ba5eca1
ACM
2682}
2683
c298304b 2684void annotation_line__write(struct annotation_line *al, struct annotation *notes,
4c650ddc
JO
2685 struct annotation_write_ops *wops,
2686 struct annotation_options *opts)
c298304b 2687{
4c650ddc
JO
2688 __annotation_line__write(al, notes, wops->first_line, wops->current_entry,
2689 wops->change_color, wops->width, wops->obj,
2690 opts->percent_type,
2691 wops->set_color, wops->set_percent_color,
2692 wops->set_jumps_percent_color, wops->printf,
2693 wops->write_graph);
c298304b
ACM
2694}
2695
ecda45bd
ACM
2696int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel,
2697 struct annotation_options *options, struct arch **parch)
2698{
2699 struct annotation *notes = symbol__annotation(sym);
2700 size_t size = symbol__size(sym);
2701 int nr_pcnt = 1, err;
2702
2703 notes->offsets = zalloc(size * sizeof(struct annotation_line *));
2704 if (notes->offsets == NULL)
2705 return -1;
2706
2707 if (perf_evsel__is_group_event(evsel))
2708 nr_pcnt = evsel->nr_members;
2709
380195e2 2710 err = symbol__annotate(sym, map, evsel, 0, options, parch);
ecda45bd
ACM
2711 if (err)
2712 goto out_free_offsets;
2713
2714 notes->options = options;
2715
2716 symbol__calc_percent(sym, evsel);
2717
2718 notes->start = map__rip_2objdump(map, sym->start);
2719
2720 annotation__set_offsets(notes, size);
2721 annotation__mark_jump_targets(notes, sym);
2722 annotation__compute_ipc(notes, size);
2723 annotation__init_column_widths(notes, sym);
2724 notes->nr_events = nr_pcnt;
2725
2726 annotation__update_column_widths(notes);
2727
2728 return 0;
2729
2730out_free_offsets:
2731 zfree(&notes->offsets);
2732 return -1;
2733}
7f0b6fde
ACM
2734
2735#define ANNOTATION__CFG(n) \
2736 { .name = #n, .value = &annotation__default_options.n, }
2737
2738/*
2739 * Keep the entries sorted, they are bsearch'ed
2740 */
2741static struct annotation_config {
2742 const char *name;
43c40231 2743 void *value;
7f0b6fde
ACM
2744} annotation__configs[] = {
2745 ANNOTATION__CFG(hide_src_code),
2746 ANNOTATION__CFG(jump_arrows),
43c40231 2747 ANNOTATION__CFG(offset_level),
7f0b6fde
ACM
2748 ANNOTATION__CFG(show_linenr),
2749 ANNOTATION__CFG(show_nr_jumps),
2750 ANNOTATION__CFG(show_nr_samples),
2751 ANNOTATION__CFG(show_total_period),
2752 ANNOTATION__CFG(use_offset),
2753};
2754
2755#undef ANNOTATION__CFG
2756
2757static int annotation_config__cmp(const void *name, const void *cfgp)
2758{
2759 const struct annotation_config *cfg = cfgp;
2760
2761 return strcmp(name, cfg->name);
2762}
2763
2764static int annotation__config(const char *var, const char *value,
2765 void *data __maybe_unused)
2766{
2767 struct annotation_config *cfg;
2768 const char *name;
2769
2770 if (!strstarts(var, "annotate."))
2771 return 0;
2772
2773 name = var + 9;
2774 cfg = bsearch(name, annotation__configs, ARRAY_SIZE(annotation__configs),
2775 sizeof(struct annotation_config), annotation_config__cmp);
2776
2777 if (cfg == NULL)
2778 pr_debug("%s variable unknown, ignoring...", var);
43c40231
ACM
2779 else if (strcmp(var, "annotate.offset_level") == 0) {
2780 perf_config_int(cfg->value, name, value);
2781
2782 if (*(int *)cfg->value > ANNOTATION__MAX_OFFSET_LEVEL)
2783 *(int *)cfg->value = ANNOTATION__MAX_OFFSET_LEVEL;
2784 else if (*(int *)cfg->value < ANNOTATION__MIN_OFFSET_LEVEL)
2785 *(int *)cfg->value = ANNOTATION__MIN_OFFSET_LEVEL;
2786 } else {
2787 *(bool *)cfg->value = perf_config_bool(name, value);
2788 }
7f0b6fde
ACM
2789 return 0;
2790}
2791
2792void annotation_config__init(void)
2793{
2794 perf_config(annotation__config, NULL);
2795
2796 annotation__default_options.show_total_period = symbol_conf.show_total_period;
2797 annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples;
2798}