]> git.ipfire.org Git - thirdparty/linux.git/blame - tools/perf/util/annotate.c
perf annotate: Stop using symbol_conf.nr_events global in symbol__hists()
[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,
592c10e2 50 .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS,
7f0b6fde
ACM
51};
52
f69b64f7 53const char *disassembler_style;
7a4ec938 54const char *objdump_path;
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
692static void annotated_source__delete(struct annotated_source *src)
693{
694 if (src == NULL)
695 return;
696 zfree(&src->histograms);
697 zfree(&src->cycles_hist);
698 free(src);
699}
700
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
732int symbol__alloc_hist(struct symbol *sym)
733{
734 size_t size = symbol__size(sym);
735 struct annotation *notes = symbol__annotation(sym);
736
ca396503 737 notes->src = annotated_source__new();
ce6f4fab
ACM
738 if (notes->src == NULL)
739 return -1;
be3e26d9
ACM
740
741 if (annotated_source__alloc_histograms(notes->src, size, symbol_conf.nr_events) < 0) {
ca396503
ACM
742 annotated_source__delete(notes->src);
743 notes->src = NULL;
116c626b
ACM
744 return -1;
745 }
ce6f4fab 746 return 0;
78f7defe
ACM
747}
748
d4957633
AK
749/* The cycles histogram is lazily allocated. */
750static int symbol__alloc_hist_cycles(struct symbol *sym)
751{
752 struct annotation *notes = symbol__annotation(sym);
753 const size_t size = symbol__size(sym);
754
755 notes->src->cycles_hist = calloc(size, sizeof(struct cyc_hist));
756 if (notes->src->cycles_hist == NULL)
757 return -1;
758 return 0;
759}
760
36532461
ACM
761void symbol__annotate_zero_histograms(struct symbol *sym)
762{
763 struct annotation *notes = symbol__annotation(sym);
764
ce6f4fab 765 pthread_mutex_lock(&notes->lock);
d4957633 766 if (notes->src != NULL) {
ce6f4fab
ACM
767 memset(notes->src->histograms, 0,
768 notes->src->nr_histograms * notes->src->sizeof_sym_hist);
d4957633
AK
769 if (notes->src->cycles_hist)
770 memset(notes->src->cycles_hist, 0,
771 symbol__size(sym) * sizeof(struct cyc_hist));
772 }
ce6f4fab 773 pthread_mutex_unlock(&notes->lock);
36532461
ACM
774}
775
f40dd6d1 776static int __symbol__account_cycles(struct cyc_hist *ch,
d4957633
AK
777 u64 start,
778 unsigned offset, unsigned cycles,
779 unsigned have_start)
780{
d4957633
AK
781 /*
782 * For now we can only account one basic block per
783 * final jump. But multiple could be overlapping.
784 * Always account the longest one. So when
785 * a shorter one has been already seen throw it away.
786 *
787 * We separately always account the full cycles.
788 */
789 ch[offset].num_aggr++;
790 ch[offset].cycles_aggr += cycles;
791
48659ebf
JY
792 if (cycles > ch[offset].cycles_max)
793 ch[offset].cycles_max = cycles;
794
795 if (ch[offset].cycles_min) {
796 if (cycles && cycles < ch[offset].cycles_min)
797 ch[offset].cycles_min = cycles;
798 } else
799 ch[offset].cycles_min = cycles;
800
d4957633
AK
801 if (!have_start && ch[offset].have_start)
802 return 0;
803 if (ch[offset].num) {
804 if (have_start && (!ch[offset].have_start ||
805 ch[offset].start > start)) {
806 ch[offset].have_start = 0;
807 ch[offset].cycles = 0;
808 ch[offset].num = 0;
809 if (ch[offset].reset < 0xffff)
810 ch[offset].reset++;
811 } else if (have_start &&
812 ch[offset].start < start)
813 return 0;
814 }
815 ch[offset].have_start = have_start;
816 ch[offset].start = start;
817 ch[offset].cycles += cycles;
818 ch[offset].num++;
819 return 0;
820}
821
b66d8c0c 822static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
e1a91a83 823 struct annotated_source *src, int evidx, u64 addr,
461c17f0 824 struct perf_sample *sample)
78f7defe 825{
2f525d01 826 unsigned offset;
78f7defe
ACM
827 struct sym_hist *h;
828
78f7defe
ACM
829 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
830
edee44be
RB
831 if ((addr < sym->start || addr >= sym->end) &&
832 (addr != sym->end || sym->start != sym->end)) {
e3d006ce
ACM
833 pr_debug("%s(%d): ERANGE! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 "\n",
834 __func__, __LINE__, sym->name, sym->start, addr, sym->end);
31d68e7b 835 return -ERANGE;
e3d006ce 836 }
78f7defe 837
2f525d01 838 offset = addr - sym->start;
e1a91a83 839 h = annotated_source__histogram(src, evidx);
8158683d 840 h->nr_samples++;
896bccd3 841 h->addr[offset].nr_samples++;
461c17f0
TS
842 h->period += sample->period;
843 h->addr[offset].period += sample->period;
78f7defe
ACM
844
845 pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
461c17f0
TS
846 ", evidx=%d] => nr_samples: %" PRIu64 ", period: %" PRIu64 "\n",
847 sym->start, sym->name, addr, addr - sym->start, evidx,
848 h->addr[offset].nr_samples, h->addr[offset].period);
78f7defe
ACM
849 return 0;
850}
851
c6b635ee 852static struct cyc_hist *symbol__cycles_hist(struct symbol *sym)
83be34a7
AK
853{
854 struct annotation *notes = symbol__annotation(sym);
855
856 if (notes->src == NULL) {
c6b635ee
ACM
857 notes->src = annotated_source__new();
858 if (notes->src == NULL)
83be34a7 859 return NULL;
c6b635ee 860 goto alloc_cycles_hist;
83be34a7 861 }
c6b635ee
ACM
862
863 if (!notes->src->cycles_hist) {
864alloc_cycles_hist:
865 symbol__alloc_hist_cycles(sym);
d4957633 866 }
c6b635ee
ACM
867
868 return notes->src->cycles_hist;
83be34a7
AK
869}
870
0693f758 871static struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists)
e8ea922a
ACM
872{
873 struct annotation *notes = symbol__annotation(sym);
874
875 if (notes->src == NULL) {
876 notes->src = annotated_source__new();
877 if (notes->src == NULL)
878 return NULL;
879 goto alloc_histograms;
880 }
881
882 if (notes->src->histograms == NULL) {
883alloc_histograms:
884 annotated_source__alloc_histograms(notes->src, symbol__size(sym),
0693f758 885 nr_hists);
e8ea922a
ACM
886 }
887
888 return notes->src;
889}
890
44e83039 891static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
e345f3bd 892 struct perf_evsel *evsel, u64 addr,
bab89f6a 893 struct perf_sample *sample)
b66d8c0c 894{
e8ea922a 895 struct annotated_source *src;
b66d8c0c 896
48c65bda 897 if (sym == NULL)
b66d8c0c 898 return 0;
0693f758 899 src = symbol__hists(sym, evsel->evlist->nr_entries);
e8ea922a 900 if (src == NULL)
83be34a7 901 return -ENOMEM;
e8ea922a 902 return __symbol__inc_addr_samples(sym, map, src, evsel->idx, addr, sample);
b66d8c0c
ACM
903}
904
d4957633
AK
905static int symbol__account_cycles(u64 addr, u64 start,
906 struct symbol *sym, unsigned cycles)
907{
c6b635ee 908 struct cyc_hist *cycles_hist;
d4957633
AK
909 unsigned offset;
910
911 if (sym == NULL)
912 return 0;
c6b635ee
ACM
913 cycles_hist = symbol__cycles_hist(sym);
914 if (cycles_hist == NULL)
d4957633
AK
915 return -ENOMEM;
916 if (addr < sym->start || addr >= sym->end)
917 return -ERANGE;
918
919 if (start) {
920 if (start < sym->start || start >= sym->end)
921 return -ERANGE;
922 if (start >= addr)
923 start = 0;
924 }
925 offset = addr - sym->start;
c6b635ee 926 return __symbol__account_cycles(cycles_hist,
d4957633
AK
927 start ? start - sym->start : 0,
928 offset, cycles,
929 !!start);
930}
931
932int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
933 struct addr_map_symbol *start,
934 unsigned cycles)
935{
3d7245b0 936 u64 saddr = 0;
d4957633
AK
937 int err;
938
939 if (!cycles)
940 return 0;
941
942 /*
943 * Only set start when IPC can be computed. We can only
944 * compute it when the basic block is completely in a single
945 * function.
946 * Special case the case when the jump is elsewhere, but
947 * it starts on the function start.
948 */
949 if (start &&
950 (start->sym == ams->sym ||
951 (ams->sym &&
952 start->addr == ams->sym->start + ams->map->start)))
953 saddr = start->al_addr;
954 if (saddr == 0)
3d7245b0 955 pr_debug2("BB with bad start: addr %"PRIx64" start %"PRIx64" sym %"PRIx64" saddr %"PRIx64"\n",
d4957633
AK
956 ams->addr,
957 start ? start->addr : 0,
958 ams->sym ? ams->sym->start + ams->map->start : 0,
959 saddr);
960 err = symbol__account_cycles(ams->al_addr, saddr, ams->sym, cycles);
961 if (err)
962 pr_debug2("account_cycles failed %d\n", err);
963 return err;
964}
965
f56c083b
ACM
966static unsigned annotation__count_insn(struct annotation *notes, u64 start, u64 end)
967{
968 unsigned n_insn = 0;
969 u64 offset;
970
971 for (offset = start; offset <= end; offset++) {
972 if (notes->offsets[offset])
973 n_insn++;
974 }
975 return n_insn;
976}
977
978static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 end, struct cyc_hist *ch)
979{
980 unsigned n_insn;
981 u64 offset;
982
983 n_insn = annotation__count_insn(notes, start, end);
984 if (n_insn && ch->num && ch->cycles) {
985 float ipc = n_insn / ((double)ch->cycles / (double)ch->num);
986
987 /* Hide data when there are too many overlaps. */
988 if (ch->reset >= 0x7fff || ch->reset >= ch->num / 2)
989 return;
990
991 for (offset = start; offset <= end; offset++) {
992 struct annotation_line *al = notes->offsets[offset];
993
994 if (al)
995 al->ipc = ipc;
996 }
997 }
998}
999
1000void annotation__compute_ipc(struct annotation *notes, size_t size)
1001{
1002 u64 offset;
1003
1004 if (!notes->src || !notes->src->cycles_hist)
1005 return;
1006
1007 pthread_mutex_lock(&notes->lock);
1008 for (offset = 0; offset < size; ++offset) {
1009 struct cyc_hist *ch;
1010
1011 ch = &notes->src->cycles_hist[offset];
1012 if (ch && ch->cycles) {
1013 struct annotation_line *al;
1014
1015 if (ch->have_start)
1016 annotation__count_and_fill(notes, ch->start, offset, ch);
1017 al = notes->offsets[offset];
48659ebf 1018 if (al && ch->num_aggr) {
f56c083b 1019 al->cycles = ch->cycles_aggr / ch->num_aggr;
48659ebf
JY
1020 al->cycles_max = ch->cycles_max;
1021 al->cycles_min = ch->cycles_min;
1022 }
f56c083b
ACM
1023 notes->have_cycles = true;
1024 }
1025 }
1026 pthread_mutex_unlock(&notes->lock);
1027}
1028
bab89f6a 1029int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
e345f3bd 1030 struct perf_evsel *evsel)
0f4e7a24 1031{
e345f3bd 1032 return symbol__inc_addr_samples(ams->sym, ams->map, evsel, ams->al_addr, sample);
0f4e7a24
ACM
1033}
1034
bab89f6a 1035int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
e345f3bd 1036 struct perf_evsel *evsel, u64 ip)
f626adff 1037{
e345f3bd 1038 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evsel, ip, sample);
f626adff
ACM
1039}
1040
85a84e4f 1041static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms)
4f9d0325 1042{
75b49202 1043 dl->ins.ops = ins__find(arch, dl->ins.name);
4f9d0325 1044
75b49202 1045 if (!dl->ins.ops)
4f9d0325
ACM
1046 return;
1047
85a84e4f 1048 if (dl->ins.ops->parse && dl->ins.ops->parse(arch, &dl->ops, ms) < 0)
75b49202 1049 dl->ins.ops = NULL;
4f9d0325
ACM
1050}
1051
75b49202 1052static int disasm_line__parse(char *line, const char **namep, char **rawp)
7a997fe4 1053{
4597cf06 1054 char tmp, *name = ltrim(line);
7a997fe4
ACM
1055
1056 if (name[0] == '\0')
1057 return -1;
1058
1059 *rawp = name + 1;
1060
1061 while ((*rawp)[0] != '\0' && !isspace((*rawp)[0]))
1062 ++*rawp;
1063
1064 tmp = (*rawp)[0];
1065 (*rawp)[0] = '\0';
1066 *namep = strdup(name);
1067
1068 if (*namep == NULL)
1069 goto out_free_name;
1070
1071 (*rawp)[0] = tmp;
4597cf06 1072 *rawp = ltrim(*rawp);
7a997fe4
ACM
1073
1074 return 0;
1075
1076out_free_name:
75b49202
ACM
1077 free((void *)namep);
1078 *namep = NULL;
7a997fe4
ACM
1079 return -1;
1080}
1081
ea07c5aa
JO
1082struct annotate_args {
1083 size_t privsize;
24fe7b88 1084 struct arch *arch;
85a84e4f 1085 struct map_symbol ms;
d03a686e 1086 struct perf_evsel *evsel;
4748834f
JO
1087 s64 offset;
1088 char *line;
1089 int line_nr;
ea07c5aa
JO
1090};
1091
c835e191
JO
1092static void annotation_line__delete(struct annotation_line *al)
1093{
1094 void *ptr = (void *) al - al->privsize;
1095
8b4c74dc 1096 free_srcline(al->path);
c835e191
JO
1097 zfree(&al->line);
1098 free(ptr);
1099}
1100
1101/*
1102 * Allocating the annotation line data with following
1103 * structure:
1104 *
1105 * --------------------------------------
1106 * private space | struct annotation_line
1107 * --------------------------------------
1108 *
1109 * Size of the private space is stored in 'struct annotation_line'.
1110 *
1111 */
1112static struct annotation_line *
1113annotation_line__new(struct annotate_args *args, size_t privsize)
1114{
1115 struct annotation_line *al;
7e304557 1116 struct perf_evsel *evsel = args->evsel;
c835e191 1117 size_t size = privsize + sizeof(*al);
7e304557
JO
1118 int nr = 1;
1119
1120 if (perf_evsel__is_group_event(evsel))
1121 nr = evsel->nr_members;
1122
1123 size += sizeof(al->samples[0]) * nr;
c835e191
JO
1124
1125 al = zalloc(size);
1126 if (al) {
1127 al = (void *) al + privsize;
1128 al->privsize = privsize;
1129 al->offset = args->offset;
1130 al->line = strdup(args->line);
1131 al->line_nr = args->line_nr;
7e304557 1132 al->samples_nr = nr;
c835e191
JO
1133 }
1134
1135 return al;
1136}
1137
1138/*
1139 * Allocating the disasm annotation line data with
1140 * following structure:
1141 *
1142 * ------------------------------------------------------------
1143 * privsize space | struct disasm_line | struct annotation_line
1144 * ------------------------------------------------------------
1145 *
1146 * We have 'struct annotation_line' member as last member
1147 * of 'struct disasm_line' to have an easy access.
1148 *
1149 */
4748834f 1150static struct disasm_line *disasm_line__new(struct annotate_args *args)
78f7defe 1151{
c835e191
JO
1152 struct disasm_line *dl = NULL;
1153 struct annotation_line *al;
1154 size_t privsize = args->privsize + offsetof(struct disasm_line, al);
78f7defe 1155
c835e191
JO
1156 al = annotation_line__new(args, privsize);
1157 if (al != NULL) {
1158 dl = disasm_line(al);
d5490b96
JO
1159
1160 if (dl->al.line == NULL)
058b4cc9 1161 goto out_delete;
5145418b 1162
4748834f 1163 if (args->offset != -1) {
d5490b96 1164 if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
5145418b
ACM
1165 goto out_free_line;
1166
85a84e4f 1167 disasm_line__init_ins(dl, args->arch, &args->ms);
5145418b 1168 }
78f7defe
ACM
1169 }
1170
29ed6e76 1171 return dl;
5145418b
ACM
1172
1173out_free_line:
d5490b96 1174 zfree(&dl->al.line);
058b4cc9 1175out_delete:
29ed6e76 1176 free(dl);
058b4cc9 1177 return NULL;
78f7defe
ACM
1178}
1179
29ed6e76 1180void disasm_line__free(struct disasm_line *dl)
78f7defe 1181{
75b49202
ACM
1182 if (dl->ins.ops && dl->ins.ops->free)
1183 dl->ins.ops->free(&dl->ops);
c46219ac
ACM
1184 else
1185 ins__delete(&dl->ops);
75b49202
ACM
1186 free((void *)dl->ins.name);
1187 dl->ins.name = NULL;
c835e191 1188 annotation_line__delete(&dl->al);
78f7defe
ACM
1189}
1190
5417072b
ACM
1191int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw)
1192{
75b49202 1193 if (raw || !dl->ins.ops)
648388ae 1194 return scnprintf(bf, size, "%-6s %s", dl->ins.name, dl->ops.raw);
5417072b 1195
75b49202 1196 return ins__scnprintf(&dl->ins, bf, size, &dl->ops);
5417072b
ACM
1197}
1198
82b9d7ff 1199static void annotation_line__add(struct annotation_line *al, struct list_head *head)
78f7defe 1200{
82b9d7ff 1201 list_add_tail(&al->node, head);
78f7defe
ACM
1202}
1203
c4c72436
JO
1204struct annotation_line *
1205annotation_line__next(struct annotation_line *pos, struct list_head *head)
78f7defe 1206{
c4c72436
JO
1207 list_for_each_entry_continue(pos, head, node)
1208 if (pos->offset >= 0)
78f7defe
ACM
1209 return pos;
1210
1211 return NULL;
1212}
1213
70fbe057
PZ
1214static const char *annotate__address_color(struct block_range *br)
1215{
1216 double cov = block_range__coverage(br);
1217
1218 if (cov >= 0) {
1219 /* mark red for >75% coverage */
1220 if (cov > 0.75)
1221 return PERF_COLOR_RED;
1222
1223 /* mark dull for <1% coverage */
1224 if (cov < 0.01)
1225 return PERF_COLOR_NORMAL;
1226 }
1227
1228 return PERF_COLOR_MAGENTA;
1229}
1230
1231static const char *annotate__asm_color(struct block_range *br)
1232{
1233 double cov = block_range__coverage(br);
1234
1235 if (cov >= 0) {
1236 /* mark dull for <1% coverage */
1237 if (cov < 0.01)
1238 return PERF_COLOR_NORMAL;
1239 }
1240
1241 return PERF_COLOR_BLUE;
1242}
1243
1244static void annotate__branch_printf(struct block_range *br, u64 addr)
1245{
1246 bool emit_comment = true;
1247
1248 if (!br)
1249 return;
1250
1251#if 1
1252 if (br->is_target && br->start == addr) {
1253 struct block_range *branch = br;
1254 double p;
1255
1256 /*
1257 * Find matching branch to our target.
1258 */
1259 while (!branch->is_branch)
1260 branch = block_range__next(branch);
1261
1262 p = 100 *(double)br->entry / branch->coverage;
1263
1264 if (p > 0.1) {
1265 if (emit_comment) {
1266 emit_comment = false;
1267 printf("\t#");
1268 }
1269
1270 /*
1271 * The percentage of coverage joined at this target in relation
1272 * to the next branch.
1273 */
1274 printf(" +%.2f%%", p);
1275 }
1276 }
1277#endif
1278 if (br->is_branch && br->end == addr) {
1279 double p = 100*(double)br->taken / br->coverage;
1280
1281 if (p > 0.1) {
1282 if (emit_comment) {
1283 emit_comment = false;
1284 printf("\t#");
1285 }
1286
1287 /*
1288 * The percentage of coverage leaving at this branch, and
1289 * its prediction ratio.
1290 */
1291 printf(" -%.2f%% (p:%.2f%%)", p, 100*(double)br->pred / br->taken);
1292 }
1293 }
1294}
1295
f48e7c40 1296static int disasm_line__print(struct disasm_line *dl, u64 start, int addr_fmt_width)
78f7defe 1297{
29971f9a
JO
1298 s64 offset = dl->al.offset;
1299 const u64 addr = start + offset;
1300 struct block_range *br;
1301
1302 br = block_range__find(addr);
f48e7c40 1303 color_fprintf(stdout, annotate__address_color(br), " %*" PRIx64 ":", addr_fmt_width, addr);
29971f9a
JO
1304 color_fprintf(stdout, annotate__asm_color(br), "%s", dl->al.line);
1305 annotate__branch_printf(br, addr);
1306 return 0;
1307}
1308
1309static int
1310annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start,
1311 struct perf_evsel *evsel, u64 len, int min_pcnt, int printed,
f48e7c40 1312 int max_lines, struct annotation_line *queue, int addr_fmt_width)
29971f9a
JO
1313{
1314 struct disasm_line *dl = container_of(al, struct disasm_line, al);
78f7defe
ACM
1315 static const char *prev_line;
1316 static const char *prev_color;
1317
29971f9a 1318 if (al->offset != -1) {
f681d593 1319 double max_percent = 0.0;
b1dd4432 1320 int i, nr_percent = 1;
78f7defe
ACM
1321 const char *color;
1322 struct annotation *notes = symbol__annotation(sym);
ce6f4fab 1323
29971f9a
JO
1324 for (i = 0; i < al->samples_nr; i++) {
1325 struct annotation_data *sample = &al->samples[i];
78f7defe 1326
f681d593
JO
1327 if (sample->percent > max_percent)
1328 max_percent = sample->percent;
b1dd4432
NK
1329 }
1330
04d2600a
JY
1331 if (al->samples_nr > nr_percent)
1332 nr_percent = al->samples_nr;
1333
b1dd4432 1334 if (max_percent < min_pcnt)
36532461
ACM
1335 return -1;
1336
e3087b80 1337 if (max_lines && printed >= max_lines)
36532461 1338 return 1;
d040bd36 1339
d5e3d747 1340 if (queue != NULL) {
29971f9a
JO
1341 list_for_each_entry_from(queue, &notes->src->source, node) {
1342 if (queue == al)
d5e3d747 1343 break;
29971f9a 1344 annotation_line__print(queue, sym, start, evsel, len,
f48e7c40 1345 0, 0, 1, NULL, addr_fmt_width);
d5e3d747
ACM
1346 }
1347 }
1348
b1dd4432 1349 color = get_percent_color(max_percent);
78f7defe
ACM
1350
1351 /*
1352 * Also color the filename and line if needed, with
1353 * the same color than the percentage. Don't print it
1354 * twice for close colored addr with the same filename:line
1355 */
29971f9a
JO
1356 if (al->path) {
1357 if (!prev_line || strcmp(prev_line, al->path)
78f7defe 1358 || color != prev_color) {
29971f9a
JO
1359 color_fprintf(stdout, color, " %s", al->path);
1360 prev_line = al->path;
78f7defe
ACM
1361 prev_color = color;
1362 }
1363 }
1364
b1dd4432 1365 for (i = 0; i < nr_percent; i++) {
29971f9a 1366 struct annotation_data *sample = &al->samples[i];
f681d593
JO
1367
1368 color = get_percent_color(sample->percent);
0c4a5bce
ML
1369
1370 if (symbol_conf.show_total_period)
ce9ee4a2 1371 color_fprintf(stdout, color, " %11" PRIu64,
f681d593 1372 sample->he.period);
1ac39372
TS
1373 else if (symbol_conf.show_nr_samples)
1374 color_fprintf(stdout, color, " %7" PRIu64,
f681d593 1375 sample->he.nr_samples);
0c4a5bce 1376 else
f681d593 1377 color_fprintf(stdout, color, " %7.2f", sample->percent);
b1dd4432
NK
1378 }
1379
f48e7c40 1380 printf(" : ");
70fbe057 1381
f48e7c40 1382 disasm_line__print(dl, start, addr_fmt_width);
70fbe057 1383 printf("\n");
e3087b80 1384 } else if (max_lines && printed >= max_lines)
36532461
ACM
1385 return 1;
1386 else {
ce9ee4a2 1387 int width = symbol_conf.show_total_period ? 12 : 8;
b1dd4432 1388
d5e3d747
ACM
1389 if (queue)
1390 return -1;
1391
759ff497 1392 if (perf_evsel__is_group_event(evsel))
b1dd4432
NK
1393 width *= evsel->nr_members;
1394
29971f9a 1395 if (!*al->line)
b1dd4432 1396 printf(" %*s:\n", width, " ");
78f7defe 1397 else
f48e7c40 1398 printf(" %*s: %*s %s\n", width, " ", addr_fmt_width, " ", al->line);
78f7defe 1399 }
36532461
ACM
1400
1401 return 0;
78f7defe
ACM
1402}
1403
3aec150a
NK
1404/*
1405 * symbol__parse_objdump_line() parses objdump output (with -d --no-show-raw)
1406 * which looks like following
1407 *
1408 * 0000000000415500 <_init>:
1409 * 415500: sub $0x8,%rsp
1410 * 415504: mov 0x2f5ad5(%rip),%rax # 70afe0 <_DYNAMIC+0x2f8>
1411 * 41550b: test %rax,%rax
1412 * 41550e: je 415515 <_init+0x15>
1413 * 415510: callq 416e70 <__gmon_start__@plt>
1414 * 415515: add $0x8,%rsp
1415 * 415519: retq
1416 *
1417 * it will be parsed and saved into struct disasm_line as
1418 * <offset> <name> <ops.raw>
1419 *
1420 * The offset will be a relative offset from the start of the symbol and -1
1421 * means that it's not a disassembly line so should be treated differently.
1422 * The ops.raw part will be parsed further according to type of the instruction.
1423 */
1a04db70 1424static int symbol__parse_objdump_line(struct symbol *sym, FILE *file,
ea07c5aa 1425 struct annotate_args *args,
e592488c 1426 int *line_nr)
78f7defe 1427{
85a84e4f 1428 struct map *map = args->ms.map;
ce6f4fab 1429 struct annotation *notes = symbol__annotation(sym);
29ed6e76 1430 struct disasm_line *dl;
4597cf06 1431 char *line = NULL, *parsed_line, *tmp, *tmp2;
78f7defe
ACM
1432 size_t line_len;
1433 s64 line_ip, offset = -1;
e592488c 1434 regmatch_t match[2];
78f7defe
ACM
1435
1436 if (getline(&line, &line_len, file) < 0)
1437 return -1;
1438
1439 if (!line)
1440 return -1;
1441
78f7defe 1442 line_ip = -1;
4597cf06 1443 parsed_line = rtrim(line);
78f7defe 1444
e592488c 1445 /* /filename:linenr ? Save line number and ignore. */
986a5bc0
TS
1446 if (regexec(&file_lineno, parsed_line, 2, match, 0) == 0) {
1447 *line_nr = atoi(parsed_line + match[1].rm_so);
e592488c
AK
1448 return 0;
1449 }
1450
4597cf06 1451 tmp = ltrim(parsed_line);
78f7defe
ACM
1452 if (*tmp) {
1453 /*
1454 * Parse hexa addresses followed by ':'
1455 */
1456 line_ip = strtoull(tmp, &tmp2, 16);
1457 if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0')
1458 line_ip = -1;
1459 }
1460
1461 if (line_ip != -1) {
1462 u64 start = map__rip_2objdump(map, sym->start),
1463 end = map__rip_2objdump(map, sym->end);
1464
1465 offset = line_ip - start;
2c241bd3 1466 if ((u64)line_ip < start || (u64)line_ip >= end)
78f7defe 1467 offset = -1;
058b4cc9
ACM
1468 else
1469 parsed_line = tmp2 + 1;
a31b7cc0 1470 }
78f7defe 1471
4748834f
JO
1472 args->offset = offset;
1473 args->line = parsed_line;
1474 args->line_nr = *line_nr;
85a84e4f 1475 args->ms.sym = sym;
4748834f
JO
1476
1477 dl = disasm_line__new(args);
058b4cc9 1478 free(line);
e592488c 1479 (*line_nr)++;
058b4cc9 1480
29ed6e76 1481 if (dl == NULL)
78f7defe 1482 return -1;
058b4cc9 1483
2eff0611 1484 if (!disasm_line__has_local_offset(dl)) {
bbb7f846
AH
1485 dl->ops.target.offset = dl->ops.target.addr -
1486 map__rip_2objdump(map, sym->start);
e216874c
RB
1487 dl->ops.target.offset_avail = true;
1488 }
bbb7f846 1489
696703af
ACM
1490 /* kcore has no symbols, so add the call target symbol */
1491 if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.sym) {
6e427ab0
AH
1492 struct addr_map_symbol target = {
1493 .map = map,
1494 .addr = dl->ops.target.addr,
1495 };
1496
be39db9f 1497 if (!map_groups__find_ams(&target) &&
6e427ab0 1498 target.sym->start == target.al_addr)
696703af 1499 dl->ops.target.sym = target.sym;
b178170a
AH
1500 }
1501
82b9d7ff 1502 annotation_line__add(&dl->al, &notes->src->source);
78f7defe
ACM
1503
1504 return 0;
1505}
1506
e592488c
AK
1507static __attribute__((constructor)) void symbol__init_regexpr(void)
1508{
1509 regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED);
1510}
1511
484a5e74
AH
1512static void delete_last_nop(struct symbol *sym)
1513{
1514 struct annotation *notes = symbol__annotation(sym);
1515 struct list_head *list = &notes->src->source;
1516 struct disasm_line *dl;
1517
1518 while (!list_empty(list)) {
a17c4ca0 1519 dl = list_entry(list->prev, struct disasm_line, al.node);
484a5e74 1520
75b49202
ACM
1521 if (dl->ins.ops) {
1522 if (dl->ins.ops != &nop_ops)
484a5e74
AH
1523 return;
1524 } else {
d5490b96
JO
1525 if (!strstr(dl->al.line, " nop ") &&
1526 !strstr(dl->al.line, " nopl ") &&
1527 !strstr(dl->al.line, " nopw "))
484a5e74
AH
1528 return;
1529 }
1530
a17c4ca0 1531 list_del(&dl->al.node);
484a5e74
AH
1532 disasm_line__free(dl);
1533 }
1534}
1535
ee51d851
ACM
1536int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map,
1537 int errnum, char *buf, size_t buflen)
1538{
1539 struct dso *dso = map->dso;
1540
1541 BUG_ON(buflen == 0);
1542
1543 if (errnum >= 0) {
1544 str_error_r(errnum, buf, buflen);
1545 return 0;
1546 }
1547
1548 switch (errnum) {
1549 case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: {
1550 char bf[SBUILD_ID_SIZE + 15] = " with build id ";
1551 char *build_id_msg = NULL;
1552
1553 if (dso->has_build_id) {
1554 build_id__sprintf(dso->build_id,
1555 sizeof(dso->build_id), bf + 15);
1556 build_id_msg = bf;
1557 }
1558 scnprintf(buf, buflen,
1559 "No vmlinux file%s\nwas found in the path.\n\n"
1560 "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"
1561 "Please use:\n\n"
1562 " perf buildid-cache -vu vmlinux\n\n"
1563 "or:\n\n"
1564 " --vmlinux vmlinux\n", build_id_msg ?: "");
1565 }
1566 break;
1567 default:
1568 scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum);
1569 break;
1570 }
1571
1572 return 0;
1573}
1574
05ed3ac9 1575static int dso__disassemble_filename(struct dso *dso, char *filename, size_t filename_size)
78f7defe 1576{
05ed3ac9
ACM
1577 char linkname[PATH_MAX];
1578 char *build_id_filename;
6ebd2547 1579 char *build_id_path = NULL;
3619ef76 1580 char *pos;
78f7defe 1581
c12944f7
ACM
1582 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1583 !dso__is_kcore(dso))
05ed3ac9 1584 return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
c12944f7 1585
d2396999 1586 build_id_filename = dso__build_id_filename(dso, NULL, 0, false);
05ed3ac9
ACM
1587 if (build_id_filename) {
1588 __symbol__join_symfs(filename, filename_size, build_id_filename);
1589 free(build_id_filename);
3caee094 1590 } else {
ee51d851
ACM
1591 if (dso->has_build_id)
1592 return ENOMEM;
78f7defe 1593 goto fallback;
3caee094
ACM
1594 }
1595
6ebd2547
TS
1596 build_id_path = strdup(filename);
1597 if (!build_id_path)
1598 return -1;
1599
3619ef76
NK
1600 /*
1601 * old style build-id cache has name of XX/XXXXXXX.. while
1602 * new style has XX/XXXXXXX../{elf,kallsyms,vdso}.
1603 * extract the build-id part of dirname in the new style only.
1604 */
1605 pos = strrchr(build_id_path, '/');
1606 if (pos && strlen(pos) < SBUILD_ID_SIZE - 2)
1607 dirname(build_id_path);
6ebd2547 1608
3caee094 1609 if (dso__is_kcore(dso) ||
6ebd2547 1610 readlink(build_id_path, linkname, sizeof(linkname)) < 0 ||
05ed3ac9
ACM
1611 strstr(linkname, DSO__NAME_KALLSYMS) ||
1612 access(filename, R_OK)) {
78f7defe
ACM
1613fallback:
1614 /*
1615 * If we don't have build-ids or the build-id file isn't in the
1616 * cache, or is just a kallsyms file, well, lets hope that this
1617 * DSO is the same as when 'perf record' ran.
1618 */
05ed3ac9 1619 __symbol__join_symfs(filename, filename_size, dso->long_name);
78f7defe
ACM
1620 }
1621
6ebd2547 1622 free(build_id_path);
05ed3ac9
ACM
1623 return 0;
1624}
1625
1a04db70 1626static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
05ed3ac9 1627{
85a84e4f 1628 struct map *map = args->ms.map;
05ed3ac9 1629 struct dso *dso = map->dso;
6810158d 1630 char *command;
05ed3ac9
ACM
1631 FILE *file;
1632 char symfs_filename[PATH_MAX];
1633 struct kcore_extract kce;
1634 bool delete_extract = false;
1635 int stdout_fd[2];
1636 int lineno = 0;
1637 int nline;
1638 pid_t pid;
1639 int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));
1640
1641 if (err)
1642 return err;
1643
78f7defe 1644 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
3caee094 1645 symfs_filename, sym->name, map->unmap_ip(map, sym->start),
78f7defe
ACM
1646 map->unmap_ip(map, sym->end));
1647
78f7defe
ACM
1648 pr_debug("annotating [%p] %30s : [%p] %30s\n",
1649 dso, dso->long_name, sym, sym->name);
1650
afba19d9
AH
1651 if (dso__is_kcore(dso)) {
1652 kce.kcore_filename = symfs_filename;
1653 kce.addr = map__rip_2objdump(map, sym->start);
1654 kce.offs = sym->start;
2c241bd3 1655 kce.len = sym->end - sym->start;
afba19d9
AH
1656 if (!kcore_extract__create(&kce)) {
1657 delete_extract = true;
1658 strlcpy(symfs_filename, kce.extract_filename,
1659 sizeof(symfs_filename));
afba19d9 1660 }
2c7da8c5 1661 } else if (dso__needs_decompress(dso)) {
3c84fd53 1662 char tmp[KMOD_DECOMP_LEN];
2c7da8c5 1663
3c84fd53
NK
1664 if (dso__decompress_kmodule_path(dso, symfs_filename,
1665 tmp, sizeof(tmp)) < 0)
3caee094 1666 goto out;
2c7da8c5
JO
1667
1668 strcpy(symfs_filename, tmp);
afba19d9
AH
1669 }
1670
6810158d 1671 err = asprintf(&command,
7a4ec938 1672 "%s %s%s --start-address=0x%016" PRIx64
3e6a2a7f 1673 " --stop-address=0x%016" PRIx64
7b4500bc 1674 " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
7a4ec938 1675 objdump_path ? objdump_path : "objdump",
f69b64f7
AK
1676 disassembler_style ? "-M " : "",
1677 disassembler_style ? disassembler_style : "",
78f7defe 1678 map__rip_2objdump(map, sym->start),
2c241bd3 1679 map__rip_2objdump(map, sym->end),
3e6a2a7f
SE
1680 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
1681 symbol_conf.annotate_src ? "-S" : "",
3caee094 1682 symfs_filename, symfs_filename);
78f7defe 1683
6810158d
ACM
1684 if (err < 0) {
1685 pr_err("Failure allocating memory for the command to run\n");
1686 goto out_remove_tmp;
1687 }
1688
78f7defe
ACM
1689 pr_debug("Executing: %s\n", command);
1690
9955d0be
ACM
1691 err = -1;
1692 if (pipe(stdout_fd) < 0) {
1693 pr_err("Failure creating the pipe to run %s\n", command);
6810158d 1694 goto out_free_command;
9955d0be
ACM
1695 }
1696
1697 pid = fork();
1698 if (pid < 0) {
1699 pr_err("Failure forking to run %s\n", command);
1700 goto out_close_stdout;
1701 }
1702
1703 if (pid == 0) {
1704 close(stdout_fd[0]);
1705 dup2(stdout_fd[1], 1);
1706 close(stdout_fd[1]);
1707 execl("/bin/sh", "sh", "-c", command, NULL);
1708 perror(command);
1709 exit(-1);
1710 }
1711
1712 close(stdout_fd[1]);
1713
1714 file = fdopen(stdout_fd[0], "r");
62ec9b3f 1715 if (!file) {
9955d0be 1716 pr_err("Failure creating FILE stream for %s\n", command);
62ec9b3f
AK
1717 /*
1718 * If we were using debug info should retry with
1719 * original binary.
1720 */
6810158d 1721 goto out_free_command;
62ec9b3f 1722 }
78f7defe 1723
62ec9b3f
AK
1724 nline = 0;
1725 while (!feof(file)) {
ed7b339f
ACM
1726 /*
1727 * The source code line number (lineno) needs to be kept in
1728 * accross calls to symbol__parse_objdump_line(), so that it
1729 * can associate it with the instructions till the next one.
1730 * See disasm_line__new() and struct disasm_line::line_nr.
1731 */
1a04db70 1732 if (symbol__parse_objdump_line(sym, file, args, &lineno) < 0)
78f7defe 1733 break;
62ec9b3f
AK
1734 nline++;
1735 }
1736
1737 if (nline == 0)
1738 pr_err("No output from %s\n", command);
78f7defe 1739
484a5e74
AH
1740 /*
1741 * kallsyms does not have symbol sizes so there may a nop at the end.
1742 * Remove it.
1743 */
1744 if (dso__is_kcore(dso))
1745 delete_last_nop(sym);
1746
9955d0be
ACM
1747 fclose(file);
1748 err = 0;
6810158d
ACM
1749out_free_command:
1750 free(command);
2c7da8c5 1751out_remove_tmp:
9955d0be
ACM
1752 close(stdout_fd[0]);
1753
2c7da8c5
JO
1754 if (dso__needs_decompress(dso))
1755 unlink(symfs_filename);
3caee094 1756
afba19d9
AH
1757 if (delete_extract)
1758 kcore_extract__delete(&kce);
c12944f7 1759out:
78f7defe 1760 return err;
9955d0be
ACM
1761
1762out_close_stdout:
1763 close(stdout_fd[1]);
6810158d 1764 goto out_free_command;
78f7defe
ACM
1765}
1766
073ae601
JO
1767static void calc_percent(struct sym_hist *hist,
1768 struct annotation_data *sample,
1769 s64 offset, s64 end)
1770{
1771 unsigned int hits = 0;
1772 u64 period = 0;
1773
1774 while (offset < end) {
1775 hits += hist->addr[offset].nr_samples;
1776 period += hist->addr[offset].period;
1777 ++offset;
1778 }
1779
1780 if (hist->nr_samples) {
1781 sample->he.period = period;
1782 sample->he.nr_samples = hits;
1783 sample->percent = 100.0 * hits / hist->nr_samples;
1784 }
1785}
1786
9e4e0a9d
JO
1787static void annotation__calc_percent(struct annotation *notes,
1788 struct perf_evsel *evsel, s64 len)
073ae601
JO
1789{
1790 struct annotation_line *al, *next;
1791
1792 list_for_each_entry(al, &notes->src->source, node) {
1793 s64 end;
1794 int i;
1795
1796 if (al->offset == -1)
1797 continue;
1798
1799 next = annotation_line__next(al, &notes->src->source);
1800 end = next ? next->offset : len;
1801
1802 for (i = 0; i < al->samples_nr; i++) {
1803 struct annotation_data *sample;
1804 struct sym_hist *hist;
1805
1806 hist = annotation__histogram(notes, evsel->idx + i);
1807 sample = &al->samples[i];
1808
1809 calc_percent(hist, sample, al->offset, end);
1810 }
1811 }
073ae601
JO
1812}
1813
9e4e0a9d 1814void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel)
073ae601
JO
1815{
1816 struct annotation *notes = symbol__annotation(sym);
1817
9e4e0a9d 1818 annotation__calc_percent(notes, evsel, symbol__size(sym));
073ae601
JO
1819}
1820
c34df25b 1821int symbol__annotate(struct symbol *sym, struct map *map,
d03a686e 1822 struct perf_evsel *evsel, size_t privsize,
5449f13c 1823 struct arch **parch)
c34df25b 1824{
ea07c5aa
JO
1825 struct annotate_args args = {
1826 .privsize = privsize,
d03a686e 1827 .evsel = evsel,
ea07c5aa 1828 };
5449f13c 1829 struct perf_env *env = perf_evsel__env(evsel);
3285deba 1830 const char *arch_name = perf_env__arch(env);
c34df25b
JO
1831 struct arch *arch;
1832 int err;
1833
c34df25b
JO
1834 if (!arch_name)
1835 return -1;
1836
24fe7b88 1837 args.arch = arch = arch__find(arch_name);
c34df25b
JO
1838 if (arch == NULL)
1839 return -ENOTSUP;
1840
1841 if (parch)
1842 *parch = arch;
1843
1844 if (arch->init) {
5449f13c 1845 err = arch->init(arch, env ? env->cpuid : NULL);
c34df25b
JO
1846 if (err) {
1847 pr_err("%s: failed to initialize %s arch priv area\n", __func__, arch->name);
1848 return err;
1849 }
1850 }
1851
85a84e4f
ACM
1852 args.ms.map = map;
1853 args.ms.sym = sym;
1854
05d3f1a1 1855 return symbol__disassemble(sym, &args);
c34df25b
JO
1856}
1857
8b4c74dc 1858static void insert_source_line(struct rb_root *root, struct annotation_line *al)
78f7defe 1859{
8b4c74dc 1860 struct annotation_line *iter;
78f7defe
ACM
1861 struct rb_node **p = &root->rb_node;
1862 struct rb_node *parent = NULL;
1491c22a 1863 int i, ret;
78f7defe
ACM
1864
1865 while (*p != NULL) {
1866 parent = *p;
8b4c74dc 1867 iter = rb_entry(parent, struct annotation_line, rb_node);
78f7defe 1868
8b4c74dc 1869 ret = strcmp(iter->path, al->path);
41127965 1870 if (ret == 0) {
8b4c74dc
JO
1871 for (i = 0; i < al->samples_nr; i++)
1872 iter->samples[i].percent_sum += al->samples[i].percent;
41127965
NK
1873 return;
1874 }
1875
1876 if (ret < 0)
1877 p = &(*p)->rb_left;
1878 else
1879 p = &(*p)->rb_right;
1880 }
1881
8b4c74dc
JO
1882 for (i = 0; i < al->samples_nr; i++)
1883 al->samples[i].percent_sum = al->samples[i].percent;
41127965 1884
8b4c74dc
JO
1885 rb_link_node(&al->rb_node, parent, p);
1886 rb_insert_color(&al->rb_node, root);
41127965
NK
1887}
1888
8b4c74dc 1889static int cmp_source_line(struct annotation_line *a, struct annotation_line *b)
1491c22a
NK
1890{
1891 int i;
1892
8b4c74dc 1893 for (i = 0; i < a->samples_nr; i++) {
276af92f 1894 if (a->samples[i].percent_sum == b->samples[i].percent_sum)
1491c22a 1895 continue;
276af92f 1896 return a->samples[i].percent_sum > b->samples[i].percent_sum;
1491c22a
NK
1897 }
1898
1899 return 0;
1900}
1901
8b4c74dc 1902static void __resort_source_line(struct rb_root *root, struct annotation_line *al)
41127965 1903{
8b4c74dc 1904 struct annotation_line *iter;
41127965
NK
1905 struct rb_node **p = &root->rb_node;
1906 struct rb_node *parent = NULL;
1907
1908 while (*p != NULL) {
1909 parent = *p;
8b4c74dc 1910 iter = rb_entry(parent, struct annotation_line, rb_node);
41127965 1911
8b4c74dc 1912 if (cmp_source_line(al, iter))
78f7defe
ACM
1913 p = &(*p)->rb_left;
1914 else
1915 p = &(*p)->rb_right;
1916 }
1917
8b4c74dc
JO
1918 rb_link_node(&al->rb_node, parent, p);
1919 rb_insert_color(&al->rb_node, root);
78f7defe
ACM
1920}
1921
41127965
NK
1922static void resort_source_line(struct rb_root *dest_root, struct rb_root *src_root)
1923{
8b4c74dc 1924 struct annotation_line *al;
41127965
NK
1925 struct rb_node *node;
1926
1927 node = rb_first(src_root);
1928 while (node) {
1929 struct rb_node *next;
1930
8b4c74dc 1931 al = rb_entry(node, struct annotation_line, rb_node);
41127965
NK
1932 next = rb_next(node);
1933 rb_erase(node, src_root);
1934
8b4c74dc 1935 __resort_source_line(dest_root, al);
41127965
NK
1936 node = next;
1937 }
1938}
1939
78f7defe
ACM
1940static void print_summary(struct rb_root *root, const char *filename)
1941{
8b4c74dc 1942 struct annotation_line *al;
78f7defe
ACM
1943 struct rb_node *node;
1944
1945 printf("\nSorted summary for file %s\n", filename);
1946 printf("----------------------------------------------\n\n");
1947
1948 if (RB_EMPTY_ROOT(root)) {
1949 printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
1950 return;
1951 }
1952
1953 node = rb_first(root);
1954 while (node) {
1491c22a 1955 double percent, percent_max = 0.0;
78f7defe
ACM
1956 const char *color;
1957 char *path;
1491c22a 1958 int i;
78f7defe 1959
8b4c74dc
JO
1960 al = rb_entry(node, struct annotation_line, rb_node);
1961 for (i = 0; i < al->samples_nr; i++) {
1962 percent = al->samples[i].percent_sum;
1491c22a
NK
1963 color = get_percent_color(percent);
1964 color_fprintf(stdout, color, " %7.2f", percent);
1965
1966 if (percent > percent_max)
1967 percent_max = percent;
1968 }
1969
8b4c74dc 1970 path = al->path;
1491c22a 1971 color = get_percent_color(percent_max);
f048d548 1972 color_fprintf(stdout, color, " %s\n", path);
78f7defe 1973
78f7defe
ACM
1974 node = rb_next(node);
1975 }
1976}
1977
db8fd07a 1978static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
78f7defe
ACM
1979{
1980 struct annotation *notes = symbol__annotation(sym);
db8fd07a 1981 struct sym_hist *h = annotation__histogram(notes, evsel->idx);
1b2e2df4 1982 u64 len = symbol__size(sym), offset;
78f7defe
ACM
1983
1984 for (offset = 0; offset < len; ++offset)
896bccd3 1985 if (h->addr[offset].nr_samples != 0)
78f7defe 1986 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
896bccd3 1987 sym->start + offset, h->addr[offset].nr_samples);
8158683d 1988 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->nr_samples", h->nr_samples);
78f7defe
ACM
1989}
1990
f48e7c40
JO
1991static int annotated_source__addr_fmt_width(struct list_head *lines, u64 start)
1992{
1993 char bf[32];
1994 struct annotation_line *line;
1995
1996 list_for_each_entry_reverse(line, lines, node) {
1997 if (line->offset != -1)
1998 return scnprintf(bf, sizeof(bf), "%" PRIx64, start + line->offset);
1999 }
2000
2001 return 0;
2002}
2003
db8fd07a
NK
2004int symbol__annotate_printf(struct symbol *sym, struct map *map,
2005 struct perf_evsel *evsel, bool full_paths,
2006 int min_pcnt, int max_lines, int context)
78f7defe
ACM
2007{
2008 struct dso *dso = map->dso;
bfd14b9a
DA
2009 char *filename;
2010 const char *d_filename;
9cdbadce 2011 const char *evsel_name = perf_evsel__name(evsel);
ce6f4fab 2012 struct annotation *notes = symbol__annotation(sym);
135cce1b 2013 struct sym_hist *h = annotation__histogram(notes, evsel->idx);
8f25b819 2014 struct annotation_line *pos, *queue = NULL;
058b4cc9 2015 u64 start = map__rip_2objdump(map, sym->start);
f48e7c40 2016 int printed = 2, queue_len = 0, addr_fmt_width;
36532461 2017 int more = 0;
78f7defe 2018 u64 len;
ce9ee4a2 2019 int width = symbol_conf.show_total_period ? 12 : 8;
53dd9b5f 2020 int graph_dotted_len;
787e4da9 2021 char buf[512];
78f7defe 2022
bfd14b9a
DA
2023 filename = strdup(dso->long_name);
2024 if (!filename)
2025 return -ENOMEM;
2026
78f7defe
ACM
2027 if (full_paths)
2028 d_filename = filename;
2029 else
2030 d_filename = basename(filename);
2031
1b2e2df4 2032 len = symbol__size(sym);
b1dd4432 2033
787e4da9 2034 if (perf_evsel__is_group_event(evsel)) {
b1dd4432 2035 width *= evsel->nr_members;
787e4da9
JY
2036 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2037 evsel_name = buf;
2038 }
78f7defe 2039
135cce1b 2040 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n",
1ac39372
TS
2041 width, width, symbol_conf.show_total_period ? "Period" :
2042 symbol_conf.show_nr_samples ? "Samples" : "Percent",
38d2dcd0 2043 d_filename, evsel_name, h->nr_samples);
9cdbadce 2044
53dd9b5f 2045 printf("%-*.*s----\n",
9cdbadce 2046 graph_dotted_len, graph_dotted_len, graph_dotted_line);
78f7defe 2047
bb963e16 2048 if (verbose > 0)
db8fd07a 2049 symbol__annotate_hits(sym, evsel);
78f7defe 2050
f48e7c40
JO
2051 addr_fmt_width = annotated_source__addr_fmt_width(&notes->src->source, start);
2052
8f25b819
JO
2053 list_for_each_entry(pos, &notes->src->source, node) {
2054 int err;
2055
d5e3d747
ACM
2056 if (context && queue == NULL) {
2057 queue = pos;
2058 queue_len = 0;
2059 }
2060
8f25b819
JO
2061 err = annotation_line__print(pos, sym, start, evsel, len,
2062 min_pcnt, printed, max_lines,
f48e7c40 2063 queue, addr_fmt_width);
8f25b819
JO
2064
2065 switch (err) {
36532461
ACM
2066 case 0:
2067 ++printed;
d5e3d747
ACM
2068 if (context) {
2069 printed += queue_len;
2070 queue = NULL;
2071 queue_len = 0;
2072 }
36532461
ACM
2073 break;
2074 case 1:
2075 /* filtered by max_lines */
2076 ++more;
d040bd36 2077 break;
36532461
ACM
2078 case -1:
2079 default:
d5e3d747
ACM
2080 /*
2081 * Filtered by min_pcnt or non IP lines when
2082 * context != 0
2083 */
2084 if (!context)
2085 break;
2086 if (queue_len == context)
8f25b819 2087 queue = list_entry(queue->node.next, typeof(*queue), node);
d5e3d747
ACM
2088 else
2089 ++queue_len;
36532461
ACM
2090 break;
2091 }
2092 }
2093
bfd14b9a
DA
2094 free(filename);
2095
36532461
ACM
2096 return more;
2097}
f1e2701d 2098
befd2a38
ACM
2099static void FILE__set_percent_color(void *fp __maybe_unused,
2100 double percent __maybe_unused,
2101 bool current __maybe_unused)
2102{
2103}
2104
2105static int FILE__set_jumps_percent_color(void *fp __maybe_unused,
2106 int nr __maybe_unused, bool current __maybe_unused)
2107{
2108 return 0;
2109}
2110
2111static int FILE__set_color(void *fp __maybe_unused, int color __maybe_unused)
2112{
2113 return 0;
2114}
2115
2116static void FILE__printf(void *fp, const char *fmt, ...)
2117{
2118 va_list args;
2119
2120 va_start(args, fmt);
2121 vfprintf(fp, fmt, args);
2122 va_end(args);
2123}
2124
2125static void FILE__write_graph(void *fp, int graph)
2126{
2127 const char *s;
2128 switch (graph) {
2129
2130 case DARROW_CHAR: s = "↓"; break;
2131 case UARROW_CHAR: s = "↑"; break;
2132 case LARROW_CHAR: s = "←"; break;
2133 case RARROW_CHAR: s = "→"; break;
2134 default: s = "?"; break;
2135 }
2136
2137 fputs(s, fp);
2138}
2139
2140int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp)
2141{
2142 struct annotation *notes = symbol__annotation(sym);
2143 struct annotation_write_ops ops = {
2144 .first_line = true,
2145 .obj = fp,
2146 .set_color = FILE__set_color,
2147 .set_percent_color = FILE__set_percent_color,
2148 .set_jumps_percent_color = FILE__set_jumps_percent_color,
2149 .printf = FILE__printf,
2150 .write_graph = FILE__write_graph,
2151 };
2152 struct annotation_line *al;
2153
2154 list_for_each_entry(al, &notes->src->source, node) {
2155 if (annotation_line__filter(al, notes))
2156 continue;
2157 annotation_line__write(al, notes, &ops);
2158 fputc('\n', fp);
2159 ops.first_line = false;
2160 }
2161
2162 return 0;
2163}
2164
d9bd7665
ACM
2165int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel)
2166{
2167 const char *ev_name = perf_evsel__name(evsel);
2168 char buf[1024];
2169 char *filename;
2170 int err = -1;
2171 FILE *fp;
2172
2173 if (asprintf(&filename, "%s.annotation", ms->sym->name) < 0)
2174 return -1;
2175
2176 fp = fopen(filename, "w");
2177 if (fp == NULL)
2178 goto out_free_filename;
2179
2180 if (perf_evsel__is_group_event(evsel)) {
2181 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2182 ev_name = buf;
2183 }
2184
2185 fprintf(fp, "%s() %s\nEvent: %s\n\n",
2186 ms->sym->name, ms->map->dso->long_name, ev_name);
2187 symbol__annotate_fprintf2(ms->sym, fp);
2188
2189 fclose(fp);
2190 err = 0;
2191out_free_filename:
2192 free(filename);
2193 return err;
2194}
2195
36532461
ACM
2196void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
2197{
2198 struct annotation *notes = symbol__annotation(sym);
2199 struct sym_hist *h = annotation__histogram(notes, evidx);
2200
ce6f4fab 2201 memset(h, 0, notes->src->sizeof_sym_hist);
36532461
ACM
2202}
2203
ce6f4fab 2204void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
36532461
ACM
2205{
2206 struct annotation *notes = symbol__annotation(sym);
2207 struct sym_hist *h = annotation__histogram(notes, evidx);
1b2e2df4 2208 int len = symbol__size(sym), offset;
36532461 2209
8158683d 2210 h->nr_samples = 0;
8b84a568 2211 for (offset = 0; offset < len; ++offset) {
896bccd3 2212 h->addr[offset].nr_samples = h->addr[offset].nr_samples * 7 / 8;
8158683d 2213 h->nr_samples += h->addr[offset].nr_samples;
f1e2701d
ACM
2214 }
2215}
2216
f8eb37bd 2217void annotated_source__purge(struct annotated_source *as)
f1e2701d 2218{
f8eb37bd 2219 struct annotation_line *al, *n;
f1e2701d 2220
f8eb37bd
JO
2221 list_for_each_entry_safe(al, n, &as->source, node) {
2222 list_del(&al->node);
2223 disasm_line__free(disasm_line(al));
f1e2701d
ACM
2224 }
2225}
2226
5145418b
ACM
2227static size_t disasm_line__fprintf(struct disasm_line *dl, FILE *fp)
2228{
2229 size_t printed;
2230
d5490b96
JO
2231 if (dl->al.offset == -1)
2232 return fprintf(fp, "%s\n", dl->al.line);
5145418b 2233
d5490b96 2234 printed = fprintf(fp, "%#" PRIx64 " %s", dl->al.offset, dl->ins.name);
5145418b 2235
c7e6ead7 2236 if (dl->ops.raw[0] != '\0') {
5145418b 2237 printed += fprintf(fp, "%.*s %s\n", 6 - (int)printed, " ",
c7e6ead7 2238 dl->ops.raw);
5145418b
ACM
2239 }
2240
2241 return printed + fprintf(fp, "\n");
2242}
2243
2244size_t disasm__fprintf(struct list_head *head, FILE *fp)
2245{
2246 struct disasm_line *pos;
2247 size_t printed = 0;
2248
a17c4ca0 2249 list_for_each_entry(pos, head, al.node)
5145418b
ACM
2250 printed += disasm_line__fprintf(pos, fp);
2251
2252 return printed;
2253}
2254
2eff0611 2255bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym)
0db45bcf
ACM
2256{
2257 if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) ||
2eff0611 2258 !disasm_line__has_local_offset(dl) || dl->ops.target.offset < 0 ||
0db45bcf
ACM
2259 dl->ops.target.offset >= (s64)symbol__size(sym))
2260 return false;
2261
2262 return true;
2263}
2264
2265void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym)
2266{
2267 u64 offset, size = symbol__size(sym);
2268
2269 /* PLT symbols contain external offsets */
2270 if (strstr(sym->name, "@plt"))
2271 return;
2272
2273 for (offset = 0; offset < size; ++offset) {
2274 struct annotation_line *al = notes->offsets[offset];
2275 struct disasm_line *dl;
2276
2277 dl = disasm_line(al);
2278
2eff0611 2279 if (!disasm_line__is_valid_local_jump(dl, sym))
0db45bcf
ACM
2280 continue;
2281
2282 al = notes->offsets[dl->ops.target.offset];
2283
2284 /*
2285 * FIXME: Oops, no jump target? Buggy disassembler? Or do we
2286 * have to adjust to the previous offset?
2287 */
2288 if (al == NULL)
2289 continue;
2290
2291 if (++al->jump_sources > notes->max_jump_sources)
2292 notes->max_jump_sources = al->jump_sources;
2293
2294 ++notes->nr_jumps;
2295 }
2296}
2297
5bc49f61
ACM
2298void annotation__set_offsets(struct annotation *notes, s64 size)
2299{
2300 struct annotation_line *al;
2301
2302 notes->max_line_len = 0;
2303
2304 list_for_each_entry(al, &notes->src->source, node) {
2305 size_t line_len = strlen(al->line);
2306
2307 if (notes->max_line_len < line_len)
2308 notes->max_line_len = line_len;
2309 al->idx = notes->nr_entries++;
2310 if (al->offset != -1) {
2311 al->idx_asm = notes->nr_asm_entries++;
2312 /*
2313 * FIXME: short term bandaid to cope with assembly
2314 * routines that comes with labels in the same column
2315 * as the address in objdump, sigh.
2316 *
2317 * E.g. copy_user_generic_unrolled
2318 */
2319 if (al->offset < size)
2320 notes->offsets[al->offset] = al;
2321 } else
2322 al->idx_asm = -1;
2323 }
2324}
2325
b8b0d819
ACM
2326static inline int width_jumps(int n)
2327{
2328 if (n >= 100)
2329 return 5;
2330 if (n / 10)
2331 return 2;
2332 return 1;
2333}
2334
2335void annotation__init_column_widths(struct annotation *notes, struct symbol *sym)
2336{
2337 notes->widths.addr = notes->widths.target =
2338 notes->widths.min_addr = hex_width(symbol__size(sym));
2339 notes->widths.max_addr = hex_width(sym->end);
2340 notes->widths.jumps = width_jumps(notes->max_jump_sources);
2341}
2342
7232bf7a
ACM
2343void annotation__update_column_widths(struct annotation *notes)
2344{
2345 if (notes->options->use_offset)
2346 notes->widths.target = notes->widths.min_addr;
2347 else
2348 notes->widths.target = notes->widths.max_addr;
2349
2350 notes->widths.addr = notes->widths.target;
2351
2352 if (notes->options->show_nr_jumps)
2353 notes->widths.addr += notes->widths.jumps + 1;
2354}
2355
8b4c74dc 2356static void annotation__calc_lines(struct annotation *notes, struct map *map,
425859ff 2357 struct rb_root *root)
8b4c74dc
JO
2358{
2359 struct annotation_line *al;
2360 struct rb_root tmp_root = RB_ROOT;
2361
2362 list_for_each_entry(al, &notes->src->source, node) {
2363 double percent_max = 0.0;
2364 int i;
2365
2366 for (i = 0; i < al->samples_nr; i++) {
2367 struct annotation_data *sample;
2368
2369 sample = &al->samples[i];
2370
2371 if (sample->percent > percent_max)
2372 percent_max = sample->percent;
2373 }
2374
2375 if (percent_max <= 0.5)
2376 continue;
2377
425859ff
ACM
2378 al->path = get_srcline(map->dso, notes->start + al->offset, NULL,
2379 false, true, notes->start + al->offset);
8b4c74dc
JO
2380 insert_source_line(&tmp_root, al);
2381 }
2382
2383 resort_source_line(root, &tmp_root);
2384}
2385
2386static void symbol__calc_lines(struct symbol *sym, struct map *map,
2387 struct rb_root *root)
2388{
2389 struct annotation *notes = symbol__annotation(sym);
8b4c74dc 2390
425859ff 2391 annotation__calc_lines(notes, map, root);
8b4c74dc
JO
2392}
2393
befd2a38
ACM
2394int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2395 struct perf_evsel *evsel, bool print_lines,
2396 bool full_paths)
2397{
2398 struct dso *dso = map->dso;
2399 struct rb_root source_line = RB_ROOT;
35632892 2400 struct annotation_options opts = annotation__default_options;
520d3f01 2401 struct annotation *notes = symbol__annotation(sym);
864298f2 2402 char buf[1024];
befd2a38
ACM
2403
2404 if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0)
2405 return -1;
2406
2407 if (print_lines) {
2408 srcline_full_filename = full_paths;
2409 symbol__calc_lines(sym, map, &source_line);
2410 print_summary(&source_line, dso->long_name);
2411 }
2412
520d3f01
ACM
2413 annotation__scnprintf_samples_period(notes, buf, sizeof(buf), evsel);
2414 fprintf(stdout, "%s\n%s() %s\n", buf, sym->name, dso->long_name);
befd2a38
ACM
2415 symbol__annotate_fprintf2(sym, stdout);
2416
2417 annotated_source__purge(symbol__annotation(sym)->src);
2418
2419 return 0;
2420}
2421
db8fd07a
NK
2422int symbol__tty_annotate(struct symbol *sym, struct map *map,
2423 struct perf_evsel *evsel, bool print_lines,
2424 bool full_paths, int min_pcnt, int max_lines)
f1e2701d
ACM
2425{
2426 struct dso *dso = map->dso;
f1e2701d 2427 struct rb_root source_line = RB_ROOT;
f1e2701d 2428
5449f13c 2429 if (symbol__annotate(sym, map, evsel, 0, NULL) < 0)
f1e2701d
ACM
2430 return -1;
2431
05d3f1a1
JO
2432 symbol__calc_percent(sym, evsel);
2433
f1e2701d 2434 if (print_lines) {
4a4c03c1 2435 srcline_full_filename = full_paths;
8b4c74dc 2436 symbol__calc_lines(sym, map, &source_line);
86c98cab 2437 print_summary(&source_line, dso->long_name);
78f7defe
ACM
2438 }
2439
db8fd07a 2440 symbol__annotate_printf(sym, map, evsel, full_paths,
d5e3d747 2441 min_pcnt, max_lines, 0);
78f7defe 2442
f8eb37bd 2443 annotated_source__purge(symbol__annotation(sym)->src);
f1e2701d 2444
78f7defe
ACM
2445 return 0;
2446}
f626adff 2447
48c65bda
NK
2448bool ui__has_annotation(void)
2449{
2e0453af 2450 return use_browser == 1 && perf_hpp_list.sym;
48c65bda 2451}
ecda45bd 2452
2f025ea0
ACM
2453
2454double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes)
2455{
2456 double percent_max = 0.0;
2457 int i;
2458
2459 for (i = 0; i < notes->nr_events; i++) {
2460 if (al->samples[i].percent > percent_max)
2461 percent_max = al->samples[i].percent;
2462 }
2463
2464 return percent_max;
2465}
2466
a1e9b74c
ACM
2467static void disasm_line__write(struct disasm_line *dl, struct annotation *notes,
2468 void *obj, char *bf, size_t size,
2469 void (*obj__printf)(void *obj, const char *fmt, ...),
2470 void (*obj__write_graph)(void *obj, int graph))
2471{
2472 if (dl->ins.ops && dl->ins.ops->scnprintf) {
2473 if (ins__is_jump(&dl->ins)) {
751b1783 2474 bool fwd;
a1e9b74c 2475
751b1783
ACM
2476 if (dl->ops.target.outside)
2477 goto call_like;
2478 fwd = dl->ops.target.offset > dl->al.offset;
a1e9b74c
ACM
2479 obj__write_graph(obj, fwd ? DARROW_CHAR : UARROW_CHAR);
2480 obj__printf(obj, " ");
2481 } else if (ins__is_call(&dl->ins)) {
751b1783 2482call_like:
a1e9b74c
ACM
2483 obj__write_graph(obj, RARROW_CHAR);
2484 obj__printf(obj, " ");
2485 } else if (ins__is_ret(&dl->ins)) {
2486 obj__write_graph(obj, LARROW_CHAR);
2487 obj__printf(obj, " ");
2488 } else {
2489 obj__printf(obj, " ");
2490 }
2491 } else {
2492 obj__printf(obj, " ");
2493 }
2494
2495 disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset);
2496}
2497
c298304b
ACM
2498static void __annotation_line__write(struct annotation_line *al, struct annotation *notes,
2499 bool first_line, bool current_entry, bool change_color, int width,
2500 void *obj,
2501 int (*obj__set_color)(void *obj, int color),
2502 void (*obj__set_percent_color)(void *obj, double percent, bool current),
2503 int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current),
2504 void (*obj__printf)(void *obj, const char *fmt, ...),
2505 void (*obj__write_graph)(void *obj, int graph))
2506
2ba5eca1
ACM
2507{
2508 double percent_max = annotation_line__max_percent(al, notes);
a1e9b74c
ACM
2509 int pcnt_width = annotation__pcnt_width(notes),
2510 cycles_width = annotation__cycles_width(notes);
2ba5eca1 2511 bool show_title = false;
a1e9b74c
ACM
2512 char bf[256];
2513 int printed;
2ba5eca1
ACM
2514
2515 if (first_line && (al->offset == -1 || percent_max == 0.0)) {
2516 if (notes->have_cycles) {
2517 if (al->ipc == 0.0 && al->cycles == 0)
2518 show_title = true;
2519 } else
2520 show_title = true;
2521 }
2522
2ba5eca1
ACM
2523 if (al->offset != -1 && percent_max != 0.0) {
2524 int i;
2525
2526 for (i = 0; i < notes->nr_events; i++) {
2527 obj__set_percent_color(obj, al->samples[i].percent, current_entry);
2528 if (notes->options->show_total_period) {
2529 obj__printf(obj, "%11" PRIu64 " ", al->samples[i].he.period);
2530 } else if (notes->options->show_nr_samples) {
2531 obj__printf(obj, "%6" PRIu64 " ",
2532 al->samples[i].he.nr_samples);
2533 } else {
2534 obj__printf(obj, "%6.2f ",
2535 al->samples[i].percent);
2536 }
2537 }
2538 } else {
2ba5eca1
ACM
2539 obj__set_percent_color(obj, 0, current_entry);
2540
2541 if (!show_title)
a1e9b74c 2542 obj__printf(obj, "%-*s", pcnt_width, " ");
2ba5eca1 2543 else {
a1e9b74c 2544 obj__printf(obj, "%-*s", pcnt_width,
2ba5eca1
ACM
2545 notes->options->show_total_period ? "Period" :
2546 notes->options->show_nr_samples ? "Samples" : "Percent");
2547 }
2548 }
2549
2550 if (notes->have_cycles) {
2551 if (al->ipc)
2552 obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc);
2553 else if (!show_title)
2554 obj__printf(obj, "%*s", ANNOTATION__IPC_WIDTH, " ");
2555 else
2556 obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
2557
3e71fc03
JY
2558 if (!notes->options->show_minmax_cycle) {
2559 if (al->cycles)
2560 obj__printf(obj, "%*" PRIu64 " ",
2ba5eca1 2561 ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
3e71fc03
JY
2562 else if (!show_title)
2563 obj__printf(obj, "%*s",
2564 ANNOTATION__CYCLES_WIDTH, " ");
2565 else
2566 obj__printf(obj, "%*s ",
2567 ANNOTATION__CYCLES_WIDTH - 1,
2568 "Cycle");
2569 } else {
2570 if (al->cycles) {
2571 char str[32];
2572
2573 scnprintf(str, sizeof(str),
2574 "%" PRIu64 "(%" PRIu64 "/%" PRIu64 ")",
2575 al->cycles, al->cycles_min,
2576 al->cycles_max);
2577
2578 obj__printf(obj, "%*s ",
2579 ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
2580 str);
2581 } else if (!show_title)
2582 obj__printf(obj, "%*s",
2583 ANNOTATION__MINMAX_CYCLES_WIDTH,
2584 " ");
2585 else
2586 obj__printf(obj, "%*s ",
2587 ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
2588 "Cycle(min/max)");
2589 }
2ba5eca1
ACM
2590 }
2591
2592 obj__printf(obj, " ");
a1e9b74c
ACM
2593
2594 if (!*al->line)
2595 obj__printf(obj, "%-*s", width - pcnt_width - cycles_width, " ");
2596 else if (al->offset == -1) {
2597 if (al->line_nr && notes->options->show_linenr)
2598 printed = scnprintf(bf, sizeof(bf), "%-*d ", notes->widths.addr + 1, al->line_nr);
2599 else
2600 printed = scnprintf(bf, sizeof(bf), "%-*s ", notes->widths.addr, " ");
2601 obj__printf(obj, bf);
2602 obj__printf(obj, "%-*s", width - printed - pcnt_width - cycles_width + 1, al->line);
2603 } else {
2604 u64 addr = al->offset;
2605 int color = -1;
2606
2607 if (!notes->options->use_offset)
2608 addr += notes->start;
2609
2610 if (!notes->options->use_offset) {
2611 printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
2612 } else {
592c10e2
ACM
2613 if (al->jump_sources &&
2614 notes->options->offset_level >= ANNOTATION__OFFSET_JUMP_TARGETS) {
a1e9b74c
ACM
2615 if (notes->options->show_nr_jumps) {
2616 int prev;
2617 printed = scnprintf(bf, sizeof(bf), "%*d ",
2618 notes->widths.jumps,
2619 al->jump_sources);
2620 prev = obj__set_jumps_percent_color(obj, al->jump_sources,
2621 current_entry);
2622 obj__printf(obj, bf);
2623 obj__set_color(obj, prev);
2624 }
592c10e2 2625print_addr:
a1e9b74c
ACM
2626 printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
2627 notes->widths.target, addr);
592c10e2
ACM
2628 } else if (ins__is_call(&disasm_line(al)->ins) &&
2629 notes->options->offset_level >= ANNOTATION__OFFSET_CALL) {
2630 goto print_addr;
2631 } else if (notes->options->offset_level == ANNOTATION__MAX_OFFSET_LEVEL) {
2632 goto print_addr;
a1e9b74c
ACM
2633 } else {
2634 printed = scnprintf(bf, sizeof(bf), "%-*s ",
2635 notes->widths.addr, " ");
2636 }
2637 }
2638
2639 if (change_color)
2640 color = obj__set_color(obj, HE_COLORSET_ADDR);
2641 obj__printf(obj, bf);
2642 if (change_color)
2643 obj__set_color(obj, color);
2644
2645 disasm_line__write(disasm_line(al), notes, obj, bf, sizeof(bf), obj__printf, obj__write_graph);
2646
2647 obj__printf(obj, "%-*s", width - pcnt_width - cycles_width - 3 - printed, bf);
2648 }
2649
2ba5eca1
ACM
2650}
2651
c298304b
ACM
2652void annotation_line__write(struct annotation_line *al, struct annotation *notes,
2653 struct annotation_write_ops *ops)
2654{
2655 __annotation_line__write(al, notes, ops->first_line, ops->current_entry,
2656 ops->change_color, ops->width, ops->obj,
2657 ops->set_color, ops->set_percent_color,
2658 ops->set_jumps_percent_color, ops->printf,
2659 ops->write_graph);
2660}
2661
ecda45bd
ACM
2662int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel,
2663 struct annotation_options *options, struct arch **parch)
2664{
2665 struct annotation *notes = symbol__annotation(sym);
2666 size_t size = symbol__size(sym);
2667 int nr_pcnt = 1, err;
2668
2669 notes->offsets = zalloc(size * sizeof(struct annotation_line *));
2670 if (notes->offsets == NULL)
2671 return -1;
2672
2673 if (perf_evsel__is_group_event(evsel))
2674 nr_pcnt = evsel->nr_members;
2675
2676 err = symbol__annotate(sym, map, evsel, 0, parch);
2677 if (err)
2678 goto out_free_offsets;
2679
2680 notes->options = options;
2681
2682 symbol__calc_percent(sym, evsel);
2683
2684 notes->start = map__rip_2objdump(map, sym->start);
2685
2686 annotation__set_offsets(notes, size);
2687 annotation__mark_jump_targets(notes, sym);
2688 annotation__compute_ipc(notes, size);
2689 annotation__init_column_widths(notes, sym);
2690 notes->nr_events = nr_pcnt;
2691
2692 annotation__update_column_widths(notes);
2693
2694 return 0;
2695
2696out_free_offsets:
2697 zfree(&notes->offsets);
2698 return -1;
2699}
7f0b6fde 2700
b213eac2
ACM
2701int __annotation__scnprintf_samples_period(struct annotation *notes,
2702 char *bf, size_t size,
2703 struct perf_evsel *evsel,
2704 bool show_freq)
2705{
2706 const char *ev_name = perf_evsel__name(evsel);
c0459a09 2707 char buf[1024], ref[30] = " show reference callgraph, ";
b213eac2
ACM
2708 char sample_freq_str[64] = "";
2709 unsigned long nr_samples = 0;
2710 int nr_members = 1;
2711 bool enable_ref = false;
2712 u64 nr_events = 0;
2713 char unit;
2714 int i;
2715
c0459a09
ACM
2716 if (perf_evsel__is_group_event(evsel)) {
2717 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2718 ev_name = buf;
b213eac2 2719 nr_members = evsel->nr_members;
c0459a09 2720 }
b213eac2
ACM
2721
2722 for (i = 0; i < nr_members; i++) {
2723 struct sym_hist *ah = annotation__histogram(notes, evsel->idx + i);
2724
2725 nr_samples += ah->nr_samples;
2726 nr_events += ah->period;
2727 }
2728
2729 if (symbol_conf.show_ref_callgraph && strstr(ev_name, "call-graph=no"))
2730 enable_ref = true;
2731
2732 if (show_freq)
2733 scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
2734
2735 nr_samples = convert_unit(nr_samples, &unit);
2736 return scnprintf(bf, size, "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
2737 nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
2738 ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
2739}
2740
7f0b6fde
ACM
2741#define ANNOTATION__CFG(n) \
2742 { .name = #n, .value = &annotation__default_options.n, }
2743
2744/*
2745 * Keep the entries sorted, they are bsearch'ed
2746 */
2747static struct annotation_config {
2748 const char *name;
43c40231 2749 void *value;
7f0b6fde
ACM
2750} annotation__configs[] = {
2751 ANNOTATION__CFG(hide_src_code),
2752 ANNOTATION__CFG(jump_arrows),
43c40231 2753 ANNOTATION__CFG(offset_level),
7f0b6fde
ACM
2754 ANNOTATION__CFG(show_linenr),
2755 ANNOTATION__CFG(show_nr_jumps),
2756 ANNOTATION__CFG(show_nr_samples),
2757 ANNOTATION__CFG(show_total_period),
2758 ANNOTATION__CFG(use_offset),
2759};
2760
2761#undef ANNOTATION__CFG
2762
2763static int annotation_config__cmp(const void *name, const void *cfgp)
2764{
2765 const struct annotation_config *cfg = cfgp;
2766
2767 return strcmp(name, cfg->name);
2768}
2769
2770static int annotation__config(const char *var, const char *value,
2771 void *data __maybe_unused)
2772{
2773 struct annotation_config *cfg;
2774 const char *name;
2775
2776 if (!strstarts(var, "annotate."))
2777 return 0;
2778
2779 name = var + 9;
2780 cfg = bsearch(name, annotation__configs, ARRAY_SIZE(annotation__configs),
2781 sizeof(struct annotation_config), annotation_config__cmp);
2782
2783 if (cfg == NULL)
2784 pr_debug("%s variable unknown, ignoring...", var);
43c40231
ACM
2785 else if (strcmp(var, "annotate.offset_level") == 0) {
2786 perf_config_int(cfg->value, name, value);
2787
2788 if (*(int *)cfg->value > ANNOTATION__MAX_OFFSET_LEVEL)
2789 *(int *)cfg->value = ANNOTATION__MAX_OFFSET_LEVEL;
2790 else if (*(int *)cfg->value < ANNOTATION__MIN_OFFSET_LEVEL)
2791 *(int *)cfg->value = ANNOTATION__MIN_OFFSET_LEVEL;
2792 } else {
2793 *(bool *)cfg->value = perf_config_bool(name, value);
2794 }
7f0b6fde
ACM
2795 return 0;
2796}
2797
2798void annotation_config__init(void)
2799{
2800 perf_config(annotation__config, NULL);
2801
2802 annotation__default_options.show_total_period = symbol_conf.show_total_period;
2803 annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples;
2804}