Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
0004  *
0005  * Parts came from builtin-annotate.c, see those files for further
0006  * copyright notes.
0007  */
0008 
0009 #include <errno.h>
0010 #include <inttypes.h>
0011 #include <libgen.h>
0012 #include <stdlib.h>
0013 #include "util.h" // hex_width()
0014 #include "ui/ui.h"
0015 #include "sort.h"
0016 #include "build-id.h"
0017 #include "color.h"
0018 #include "config.h"
0019 #include "dso.h"
0020 #include "env.h"
0021 #include "map.h"
0022 #include "maps.h"
0023 #include "symbol.h"
0024 #include "srcline.h"
0025 #include "units.h"
0026 #include "debug.h"
0027 #include "annotate.h"
0028 #include "evsel.h"
0029 #include "evlist.h"
0030 #include "bpf-event.h"
0031 #include "bpf-utils.h"
0032 #include "block-range.h"
0033 #include "string2.h"
0034 #include "util/event.h"
0035 #include "arch/common.h"
0036 #include "namespaces.h"
0037 #include <regex.h>
0038 #include <pthread.h>
0039 #include <linux/bitops.h>
0040 #include <linux/kernel.h>
0041 #include <linux/string.h>
0042 #include <subcmd/parse-options.h>
0043 #include <subcmd/run-command.h>
0044 
0045 /* FIXME: For the HE_COLORSET */
0046 #include "ui/browser.h"
0047 
0048 /*
0049  * FIXME: Using the same values as slang.h,
0050  * but that header may not be available everywhere
0051  */
0052 #define LARROW_CHAR ((unsigned char)',')
0053 #define RARROW_CHAR ((unsigned char)'+')
0054 #define DARROW_CHAR ((unsigned char)'.')
0055 #define UARROW_CHAR ((unsigned char)'-')
0056 
0057 #include <linux/ctype.h>
0058 
0059 struct annotation_options annotation__default_options = {
0060     .use_offset     = true,
0061     .jump_arrows    = true,
0062     .annotate_src   = true,
0063     .offset_level   = ANNOTATION__OFFSET_JUMP_TARGETS,
0064     .percent_type   = PERCENT_PERIOD_LOCAL,
0065 };
0066 
0067 static regex_t   file_lineno;
0068 
0069 static struct ins_ops *ins__find(struct arch *arch, const char *name);
0070 static void ins__sort(struct arch *arch);
0071 static int disasm_line__parse(char *line, const char **namep, char **rawp);
0072 
0073 struct arch {
0074     const char  *name;
0075     struct ins  *instructions;
0076     size_t      nr_instructions;
0077     size_t      nr_instructions_allocated;
0078     struct ins_ops  *(*associate_instruction_ops)(struct arch *arch, const char *name);
0079     bool        sorted_instructions;
0080     bool        initialized;
0081     void        *priv;
0082     unsigned int    model;
0083     unsigned int    family;
0084     int     (*init)(struct arch *arch, char *cpuid);
0085     bool        (*ins_is_fused)(struct arch *arch, const char *ins1,
0086                     const char *ins2);
0087     struct      {
0088         char comment_char;
0089         char skip_functions_char;
0090     } objdump;
0091 };
0092 
0093 static struct ins_ops call_ops;
0094 static struct ins_ops dec_ops;
0095 static struct ins_ops jump_ops;
0096 static struct ins_ops mov_ops;
0097 static struct ins_ops nop_ops;
0098 static struct ins_ops lock_ops;
0099 static struct ins_ops ret_ops;
0100 
0101 static int arch__grow_instructions(struct arch *arch)
0102 {
0103     struct ins *new_instructions;
0104     size_t new_nr_allocated;
0105 
0106     if (arch->nr_instructions_allocated == 0 && arch->instructions)
0107         goto grow_from_non_allocated_table;
0108 
0109     new_nr_allocated = arch->nr_instructions_allocated + 128;
0110     new_instructions = realloc(arch->instructions, new_nr_allocated * sizeof(struct ins));
0111     if (new_instructions == NULL)
0112         return -1;
0113 
0114 out_update_instructions:
0115     arch->instructions = new_instructions;
0116     arch->nr_instructions_allocated = new_nr_allocated;
0117     return 0;
0118 
0119 grow_from_non_allocated_table:
0120     new_nr_allocated = arch->nr_instructions + 128;
0121     new_instructions = calloc(new_nr_allocated, sizeof(struct ins));
0122     if (new_instructions == NULL)
0123         return -1;
0124 
0125     memcpy(new_instructions, arch->instructions, arch->nr_instructions);
0126     goto out_update_instructions;
0127 }
0128 
0129 static int arch__associate_ins_ops(struct arch* arch, const char *name, struct ins_ops *ops)
0130 {
0131     struct ins *ins;
0132 
0133     if (arch->nr_instructions == arch->nr_instructions_allocated &&
0134         arch__grow_instructions(arch))
0135         return -1;
0136 
0137     ins = &arch->instructions[arch->nr_instructions];
0138     ins->name = strdup(name);
0139     if (!ins->name)
0140         return -1;
0141 
0142     ins->ops  = ops;
0143     arch->nr_instructions++;
0144 
0145     ins__sort(arch);
0146     return 0;
0147 }
0148 
0149 #include "arch/arc/annotate/instructions.c"
0150 #include "arch/arm/annotate/instructions.c"
0151 #include "arch/arm64/annotate/instructions.c"
0152 #include "arch/csky/annotate/instructions.c"
0153 #include "arch/mips/annotate/instructions.c"
0154 #include "arch/x86/annotate/instructions.c"
0155 #include "arch/powerpc/annotate/instructions.c"
0156 #include "arch/riscv64/annotate/instructions.c"
0157 #include "arch/s390/annotate/instructions.c"
0158 #include "arch/sparc/annotate/instructions.c"
0159 
0160 static struct arch architectures[] = {
0161     {
0162         .name = "arc",
0163         .init = arc__annotate_init,
0164     },
0165     {
0166         .name = "arm",
0167         .init = arm__annotate_init,
0168     },
0169     {
0170         .name = "arm64",
0171         .init = arm64__annotate_init,
0172     },
0173     {
0174         .name = "csky",
0175         .init = csky__annotate_init,
0176     },
0177     {
0178         .name = "mips",
0179         .init = mips__annotate_init,
0180         .objdump = {
0181             .comment_char = '#',
0182         },
0183     },
0184     {
0185         .name = "x86",
0186         .init = x86__annotate_init,
0187         .instructions = x86__instructions,
0188         .nr_instructions = ARRAY_SIZE(x86__instructions),
0189         .objdump =  {
0190             .comment_char = '#',
0191         },
0192     },
0193     {
0194         .name = "powerpc",
0195         .init = powerpc__annotate_init,
0196     },
0197     {
0198         .name = "riscv64",
0199         .init = riscv64__annotate_init,
0200     },
0201     {
0202         .name = "s390",
0203         .init = s390__annotate_init,
0204         .objdump =  {
0205             .comment_char = '#',
0206         },
0207     },
0208     {
0209         .name = "sparc",
0210         .init = sparc__annotate_init,
0211         .objdump = {
0212             .comment_char = '#',
0213         },
0214     },
0215 };
0216 
0217 static void ins__delete(struct ins_operands *ops)
0218 {
0219     if (ops == NULL)
0220         return;
0221     zfree(&ops->source.raw);
0222     zfree(&ops->source.name);
0223     zfree(&ops->target.raw);
0224     zfree(&ops->target.name);
0225 }
0226 
0227 static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
0228                   struct ins_operands *ops, int max_ins_name)
0229 {
0230     return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->raw);
0231 }
0232 
0233 int ins__scnprintf(struct ins *ins, char *bf, size_t size,
0234            struct ins_operands *ops, int max_ins_name)
0235 {
0236     if (ins->ops->scnprintf)
0237         return ins->ops->scnprintf(ins, bf, size, ops, max_ins_name);
0238 
0239     return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
0240 }
0241 
0242 bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
0243 {
0244     if (!arch || !arch->ins_is_fused)
0245         return false;
0246 
0247     return arch->ins_is_fused(arch, ins1, ins2);
0248 }
0249 
0250 static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
0251 {
0252     char *endptr, *tok, *name;
0253     struct map *map = ms->map;
0254     struct addr_map_symbol target = {
0255         .ms = { .map = map, },
0256     };
0257 
0258     ops->target.addr = strtoull(ops->raw, &endptr, 16);
0259 
0260     name = strchr(endptr, '<');
0261     if (name == NULL)
0262         goto indirect_call;
0263 
0264     name++;
0265 
0266     if (arch->objdump.skip_functions_char &&
0267         strchr(name, arch->objdump.skip_functions_char))
0268         return -1;
0269 
0270     tok = strchr(name, '>');
0271     if (tok == NULL)
0272         return -1;
0273 
0274     *tok = '\0';
0275     ops->target.name = strdup(name);
0276     *tok = '>';
0277 
0278     if (ops->target.name == NULL)
0279         return -1;
0280 find_target:
0281     target.addr = map__objdump_2mem(map, ops->target.addr);
0282 
0283     if (maps__find_ams(ms->maps, &target) == 0 &&
0284         map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr)
0285         ops->target.sym = target.ms.sym;
0286 
0287     return 0;
0288 
0289 indirect_call:
0290     tok = strchr(endptr, '*');
0291     if (tok != NULL) {
0292         endptr++;
0293 
0294         /* Indirect call can use a non-rip register and offset: callq  *0x8(%rbx).
0295          * Do not parse such instruction.  */
0296         if (strstr(endptr, "(%r") == NULL)
0297             ops->target.addr = strtoull(endptr, NULL, 16);
0298     }
0299     goto find_target;
0300 }
0301 
0302 static int call__scnprintf(struct ins *ins, char *bf, size_t size,
0303                struct ins_operands *ops, int max_ins_name)
0304 {
0305     if (ops->target.sym)
0306         return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name);
0307 
0308     if (ops->target.addr == 0)
0309         return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
0310 
0311     if (ops->target.name)
0312         return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.name);
0313 
0314     return scnprintf(bf, size, "%-*s *%" PRIx64, max_ins_name, ins->name, ops->target.addr);
0315 }
0316 
0317 static struct ins_ops call_ops = {
0318     .parse     = call__parse,
0319     .scnprintf = call__scnprintf,
0320 };
0321 
0322 bool ins__is_call(const struct ins *ins)
0323 {
0324     return ins->ops == &call_ops || ins->ops == &s390_call_ops;
0325 }
0326 
0327 /*
0328  * Prevents from matching commas in the comment section, e.g.:
0329  * ffff200008446e70:       b.cs    ffff2000084470f4 <generic_exec_single+0x314>  // b.hs, b.nlast
0330  *
0331  * and skip comma as part of function arguments, e.g.:
0332  * 1d8b4ac <linemap_lookup(line_maps const*, unsigned int)+0xcc>
0333  */
0334 static inline const char *validate_comma(const char *c, struct ins_operands *ops)
0335 {
0336     if (ops->raw_comment && c > ops->raw_comment)
0337         return NULL;
0338 
0339     if (ops->raw_func_start && c > ops->raw_func_start)
0340         return NULL;
0341 
0342     return c;
0343 }
0344 
0345 static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
0346 {
0347     struct map *map = ms->map;
0348     struct symbol *sym = ms->sym;
0349     struct addr_map_symbol target = {
0350         .ms = { .map = map, },
0351     };
0352     const char *c = strchr(ops->raw, ',');
0353     u64 start, end;
0354 
0355     ops->raw_comment = strchr(ops->raw, arch->objdump.comment_char);
0356     ops->raw_func_start = strchr(ops->raw, '<');
0357 
0358     c = validate_comma(c, ops);
0359 
0360     /*
0361      * Examples of lines to parse for the _cpp_lex_token@@Base
0362      * function:
0363      *
0364      * 1159e6c: jne    115aa32 <_cpp_lex_token@@Base+0xf92>
0365      * 1159e8b: jne    c469be <cpp_named_operator2name@@Base+0xa72>
0366      *
0367      * The first is a jump to an offset inside the same function,
0368      * the second is to another function, i.e. that 0xa72 is an
0369      * offset in the cpp_named_operator2name@@base function.
0370      */
0371     /*
0372      * skip over possible up to 2 operands to get to address, e.g.:
0373      * tbnz  w0, #26, ffff0000083cd190 <security_file_permission+0xd0>
0374      */
0375     if (c++ != NULL) {
0376         ops->target.addr = strtoull(c, NULL, 16);
0377         if (!ops->target.addr) {
0378             c = strchr(c, ',');
0379             c = validate_comma(c, ops);
0380             if (c++ != NULL)
0381                 ops->target.addr = strtoull(c, NULL, 16);
0382         }
0383     } else {
0384         ops->target.addr = strtoull(ops->raw, NULL, 16);
0385     }
0386 
0387     target.addr = map__objdump_2mem(map, ops->target.addr);
0388     start = map->unmap_ip(map, sym->start),
0389     end = map->unmap_ip(map, sym->end);
0390 
0391     ops->target.outside = target.addr < start || target.addr > end;
0392 
0393     /*
0394      * FIXME: things like this in _cpp_lex_token (gcc's cc1 program):
0395 
0396         cpp_named_operator2name@@Base+0xa72
0397 
0398      * Point to a place that is after the cpp_named_operator2name
0399      * boundaries, i.e.  in the ELF symbol table for cc1
0400      * cpp_named_operator2name is marked as being 32-bytes long, but it in
0401      * fact is much larger than that, so we seem to need a symbols__find()
0402      * routine that looks for >= current->start and  < next_symbol->start,
0403      * possibly just for C++ objects?
0404      *
0405      * For now lets just make some progress by marking jumps to outside the
0406      * current function as call like.
0407      *
0408      * Actual navigation will come next, with further understanding of how
0409      * the symbol searching and disassembly should be done.
0410      */
0411     if (maps__find_ams(ms->maps, &target) == 0 &&
0412         map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr)
0413         ops->target.sym = target.ms.sym;
0414 
0415     if (!ops->target.outside) {
0416         ops->target.offset = target.addr - start;
0417         ops->target.offset_avail = true;
0418     } else {
0419         ops->target.offset_avail = false;
0420     }
0421 
0422     return 0;
0423 }
0424 
0425 static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
0426                struct ins_operands *ops, int max_ins_name)
0427 {
0428     const char *c;
0429 
0430     if (!ops->target.addr || ops->target.offset < 0)
0431         return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
0432 
0433     if (ops->target.outside && ops->target.sym != NULL)
0434         return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name);
0435 
0436     c = strchr(ops->raw, ',');
0437     c = validate_comma(c, ops);
0438 
0439     if (c != NULL) {
0440         const char *c2 = strchr(c + 1, ',');
0441 
0442         c2 = validate_comma(c2, ops);
0443         /* check for 3-op insn */
0444         if (c2 != NULL)
0445             c = c2;
0446         c++;
0447 
0448         /* mirror arch objdump's space-after-comma style */
0449         if (*c == ' ')
0450             c++;
0451     }
0452 
0453     return scnprintf(bf, size, "%-*s %.*s%" PRIx64, max_ins_name,
0454              ins->name, c ? c - ops->raw : 0, ops->raw,
0455              ops->target.offset);
0456 }
0457 
0458 static struct ins_ops jump_ops = {
0459     .parse     = jump__parse,
0460     .scnprintf = jump__scnprintf,
0461 };
0462 
0463 bool ins__is_jump(const struct ins *ins)
0464 {
0465     return ins->ops == &jump_ops;
0466 }
0467 
0468 static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
0469 {
0470     char *endptr, *name, *t;
0471 
0472     if (strstr(raw, "(%rip)") == NULL)
0473         return 0;
0474 
0475     *addrp = strtoull(comment, &endptr, 16);
0476     if (endptr == comment)
0477         return 0;
0478     name = strchr(endptr, '<');
0479     if (name == NULL)
0480         return -1;
0481 
0482     name++;
0483 
0484     t = strchr(name, '>');
0485     if (t == NULL)
0486         return 0;
0487 
0488     *t = '\0';
0489     *namep = strdup(name);
0490     *t = '>';
0491 
0492     return 0;
0493 }
0494 
0495 static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
0496 {
0497     ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
0498     if (ops->locked.ops == NULL)
0499         return 0;
0500 
0501     if (disasm_line__parse(ops->raw, &ops->locked.ins.name, &ops->locked.ops->raw) < 0)
0502         goto out_free_ops;
0503 
0504     ops->locked.ins.ops = ins__find(arch, ops->locked.ins.name);
0505 
0506     if (ops->locked.ins.ops == NULL)
0507         goto out_free_ops;
0508 
0509     if (ops->locked.ins.ops->parse &&
0510         ops->locked.ins.ops->parse(arch, ops->locked.ops, ms) < 0)
0511         goto out_free_ops;
0512 
0513     return 0;
0514 
0515 out_free_ops:
0516     zfree(&ops->locked.ops);
0517     return 0;
0518 }
0519 
0520 static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
0521                struct ins_operands *ops, int max_ins_name)
0522 {
0523     int printed;
0524 
0525     if (ops->locked.ins.ops == NULL)
0526         return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
0527 
0528     printed = scnprintf(bf, size, "%-*s ", max_ins_name, ins->name);
0529     return printed + ins__scnprintf(&ops->locked.ins, bf + printed,
0530                     size - printed, ops->locked.ops, max_ins_name);
0531 }
0532 
0533 static void lock__delete(struct ins_operands *ops)
0534 {
0535     struct ins *ins = &ops->locked.ins;
0536 
0537     if (ins->ops && ins->ops->free)
0538         ins->ops->free(ops->locked.ops);
0539     else
0540         ins__delete(ops->locked.ops);
0541 
0542     zfree(&ops->locked.ops);
0543     zfree(&ops->target.raw);
0544     zfree(&ops->target.name);
0545 }
0546 
0547 static struct ins_ops lock_ops = {
0548     .free      = lock__delete,
0549     .parse     = lock__parse,
0550     .scnprintf = lock__scnprintf,
0551 };
0552 
0553 static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
0554 {
0555     char *s = strchr(ops->raw, ','), *target, *comment, prev;
0556 
0557     if (s == NULL)
0558         return -1;
0559 
0560     *s = '\0';
0561     ops->source.raw = strdup(ops->raw);
0562     *s = ',';
0563 
0564     if (ops->source.raw == NULL)
0565         return -1;
0566 
0567     target = ++s;
0568     comment = strchr(s, arch->objdump.comment_char);
0569 
0570     if (comment != NULL)
0571         s = comment - 1;
0572     else
0573         s = strchr(s, '\0') - 1;
0574 
0575     while (s > target && isspace(s[0]))
0576         --s;
0577     s++;
0578     prev = *s;
0579     *s = '\0';
0580 
0581     ops->target.raw = strdup(target);
0582     *s = prev;
0583 
0584     if (ops->target.raw == NULL)
0585         goto out_free_source;
0586 
0587     if (comment == NULL)
0588         return 0;
0589 
0590     comment = skip_spaces(comment);
0591     comment__symbol(ops->source.raw, comment + 1, &ops->source.addr, &ops->source.name);
0592     comment__symbol(ops->target.raw, comment + 1, &ops->target.addr, &ops->target.name);
0593 
0594     return 0;
0595 
0596 out_free_source:
0597     zfree(&ops->source.raw);
0598     return -1;
0599 }
0600 
0601 static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
0602                struct ins_operands *ops, int max_ins_name)
0603 {
0604     return scnprintf(bf, size, "%-*s %s,%s", max_ins_name, ins->name,
0605              ops->source.name ?: ops->source.raw,
0606              ops->target.name ?: ops->target.raw);
0607 }
0608 
0609 static struct ins_ops mov_ops = {
0610     .parse     = mov__parse,
0611     .scnprintf = mov__scnprintf,
0612 };
0613 
0614 static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
0615 {
0616     char *target, *comment, *s, prev;
0617 
0618     target = s = ops->raw;
0619 
0620     while (s[0] != '\0' && !isspace(s[0]))
0621         ++s;
0622     prev = *s;
0623     *s = '\0';
0624 
0625     ops->target.raw = strdup(target);
0626     *s = prev;
0627 
0628     if (ops->target.raw == NULL)
0629         return -1;
0630 
0631     comment = strchr(s, arch->objdump.comment_char);
0632     if (comment == NULL)
0633         return 0;
0634 
0635     comment = skip_spaces(comment);
0636     comment__symbol(ops->target.raw, comment + 1, &ops->target.addr, &ops->target.name);
0637 
0638     return 0;
0639 }
0640 
0641 static int dec__scnprintf(struct ins *ins, char *bf, size_t size,
0642                struct ins_operands *ops, int max_ins_name)
0643 {
0644     return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
0645              ops->target.name ?: ops->target.raw);
0646 }
0647 
0648 static struct ins_ops dec_ops = {
0649     .parse     = dec__parse,
0650     .scnprintf = dec__scnprintf,
0651 };
0652 
0653 static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size,
0654               struct ins_operands *ops __maybe_unused, int max_ins_name)
0655 {
0656     return scnprintf(bf, size, "%-*s", max_ins_name, "nop");
0657 }
0658 
0659 static struct ins_ops nop_ops = {
0660     .scnprintf = nop__scnprintf,
0661 };
0662 
0663 static struct ins_ops ret_ops = {
0664     .scnprintf = ins__raw_scnprintf,
0665 };
0666 
0667 bool ins__is_ret(const struct ins *ins)
0668 {
0669     return ins->ops == &ret_ops;
0670 }
0671 
0672 bool ins__is_lock(const struct ins *ins)
0673 {
0674     return ins->ops == &lock_ops;
0675 }
0676 
0677 static int ins__key_cmp(const void *name, const void *insp)
0678 {
0679     const struct ins *ins = insp;
0680 
0681     return strcmp(name, ins->name);
0682 }
0683 
0684 static int ins__cmp(const void *a, const void *b)
0685 {
0686     const struct ins *ia = a;
0687     const struct ins *ib = b;
0688 
0689     return strcmp(ia->name, ib->name);
0690 }
0691 
0692 static void ins__sort(struct arch *arch)
0693 {
0694     const int nmemb = arch->nr_instructions;
0695 
0696     qsort(arch->instructions, nmemb, sizeof(struct ins), ins__cmp);
0697 }
0698 
0699 static struct ins_ops *__ins__find(struct arch *arch, const char *name)
0700 {
0701     struct ins *ins;
0702     const int nmemb = arch->nr_instructions;
0703 
0704     if (!arch->sorted_instructions) {
0705         ins__sort(arch);
0706         arch->sorted_instructions = true;
0707     }
0708 
0709     ins = bsearch(name, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp);
0710     return ins ? ins->ops : NULL;
0711 }
0712 
0713 static struct ins_ops *ins__find(struct arch *arch, const char *name)
0714 {
0715     struct ins_ops *ops = __ins__find(arch, name);
0716 
0717     if (!ops && arch->associate_instruction_ops)
0718         ops = arch->associate_instruction_ops(arch, name);
0719 
0720     return ops;
0721 }
0722 
0723 static int arch__key_cmp(const void *name, const void *archp)
0724 {
0725     const struct arch *arch = archp;
0726 
0727     return strcmp(name, arch->name);
0728 }
0729 
0730 static int arch__cmp(const void *a, const void *b)
0731 {
0732     const struct arch *aa = a;
0733     const struct arch *ab = b;
0734 
0735     return strcmp(aa->name, ab->name);
0736 }
0737 
0738 static void arch__sort(void)
0739 {
0740     const int nmemb = ARRAY_SIZE(architectures);
0741 
0742     qsort(architectures, nmemb, sizeof(struct arch), arch__cmp);
0743 }
0744 
0745 static struct arch *arch__find(const char *name)
0746 {
0747     const int nmemb = ARRAY_SIZE(architectures);
0748     static bool sorted;
0749 
0750     if (!sorted) {
0751         arch__sort();
0752         sorted = true;
0753     }
0754 
0755     return bsearch(name, architectures, nmemb, sizeof(struct arch), arch__key_cmp);
0756 }
0757 
0758 static struct annotated_source *annotated_source__new(void)
0759 {
0760     struct annotated_source *src = zalloc(sizeof(*src));
0761 
0762     if (src != NULL)
0763         INIT_LIST_HEAD(&src->source);
0764 
0765     return src;
0766 }
0767 
0768 static __maybe_unused void annotated_source__delete(struct annotated_source *src)
0769 {
0770     if (src == NULL)
0771         return;
0772     zfree(&src->histograms);
0773     zfree(&src->cycles_hist);
0774     free(src);
0775 }
0776 
0777 static int annotated_source__alloc_histograms(struct annotated_source *src,
0778                           size_t size, int nr_hists)
0779 {
0780     size_t sizeof_sym_hist;
0781 
0782     /*
0783      * Add buffer of one element for zero length symbol.
0784      * When sample is taken from first instruction of
0785      * zero length symbol, perf still resolves it and
0786      * shows symbol name in perf report and allows to
0787      * annotate it.
0788      */
0789     if (size == 0)
0790         size = 1;
0791 
0792     /* Check for overflow when calculating sizeof_sym_hist */
0793     if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(struct sym_hist_entry))
0794         return -1;
0795 
0796     sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(struct sym_hist_entry));
0797 
0798     /* Check for overflow in zalloc argument */
0799     if (sizeof_sym_hist > SIZE_MAX / nr_hists)
0800         return -1;
0801 
0802     src->sizeof_sym_hist = sizeof_sym_hist;
0803     src->nr_histograms   = nr_hists;
0804     src->histograms      = calloc(nr_hists, sizeof_sym_hist) ;
0805     return src->histograms ? 0 : -1;
0806 }
0807 
0808 /* The cycles histogram is lazily allocated. */
0809 static int symbol__alloc_hist_cycles(struct symbol *sym)
0810 {
0811     struct annotation *notes = symbol__annotation(sym);
0812     const size_t size = symbol__size(sym);
0813 
0814     notes->src->cycles_hist = calloc(size, sizeof(struct cyc_hist));
0815     if (notes->src->cycles_hist == NULL)
0816         return -1;
0817     return 0;
0818 }
0819 
0820 void symbol__annotate_zero_histograms(struct symbol *sym)
0821 {
0822     struct annotation *notes = symbol__annotation(sym);
0823 
0824     pthread_mutex_lock(&notes->lock);
0825     if (notes->src != NULL) {
0826         memset(notes->src->histograms, 0,
0827                notes->src->nr_histograms * notes->src->sizeof_sym_hist);
0828         if (notes->src->cycles_hist)
0829             memset(notes->src->cycles_hist, 0,
0830                 symbol__size(sym) * sizeof(struct cyc_hist));
0831     }
0832     pthread_mutex_unlock(&notes->lock);
0833 }
0834 
0835 static int __symbol__account_cycles(struct cyc_hist *ch,
0836                     u64 start,
0837                     unsigned offset, unsigned cycles,
0838                     unsigned have_start)
0839 {
0840     /*
0841      * For now we can only account one basic block per
0842      * final jump. But multiple could be overlapping.
0843      * Always account the longest one. So when
0844      * a shorter one has been already seen throw it away.
0845      *
0846      * We separately always account the full cycles.
0847      */
0848     ch[offset].num_aggr++;
0849     ch[offset].cycles_aggr += cycles;
0850 
0851     if (cycles > ch[offset].cycles_max)
0852         ch[offset].cycles_max = cycles;
0853 
0854     if (ch[offset].cycles_min) {
0855         if (cycles && cycles < ch[offset].cycles_min)
0856             ch[offset].cycles_min = cycles;
0857     } else
0858         ch[offset].cycles_min = cycles;
0859 
0860     if (!have_start && ch[offset].have_start)
0861         return 0;
0862     if (ch[offset].num) {
0863         if (have_start && (!ch[offset].have_start ||
0864                    ch[offset].start > start)) {
0865             ch[offset].have_start = 0;
0866             ch[offset].cycles = 0;
0867             ch[offset].num = 0;
0868             if (ch[offset].reset < 0xffff)
0869                 ch[offset].reset++;
0870         } else if (have_start &&
0871                ch[offset].start < start)
0872             return 0;
0873     }
0874 
0875     if (ch[offset].num < NUM_SPARKS)
0876         ch[offset].cycles_spark[ch[offset].num] = cycles;
0877 
0878     ch[offset].have_start = have_start;
0879     ch[offset].start = start;
0880     ch[offset].cycles += cycles;
0881     ch[offset].num++;
0882     return 0;
0883 }
0884 
0885 static int __symbol__inc_addr_samples(struct map_symbol *ms,
0886                       struct annotated_source *src, int evidx, u64 addr,
0887                       struct perf_sample *sample)
0888 {
0889     struct symbol *sym = ms->sym;
0890     unsigned offset;
0891     struct sym_hist *h;
0892 
0893     pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, ms->map->unmap_ip(ms->map, addr));
0894 
0895     if ((addr < sym->start || addr >= sym->end) &&
0896         (addr != sym->end || sym->start != sym->end)) {
0897         pr_debug("%s(%d): ERANGE! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 "\n",
0898                __func__, __LINE__, sym->name, sym->start, addr, sym->end);
0899         return -ERANGE;
0900     }
0901 
0902     offset = addr - sym->start;
0903     h = annotated_source__histogram(src, evidx);
0904     if (h == NULL) {
0905         pr_debug("%s(%d): ENOMEM! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 ", func: %d\n",
0906              __func__, __LINE__, sym->name, sym->start, addr, sym->end, sym->type == STT_FUNC);
0907         return -ENOMEM;
0908     }
0909     h->nr_samples++;
0910     h->addr[offset].nr_samples++;
0911     h->period += sample->period;
0912     h->addr[offset].period += sample->period;
0913 
0914     pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
0915           ", evidx=%d] => nr_samples: %" PRIu64 ", period: %" PRIu64 "\n",
0916           sym->start, sym->name, addr, addr - sym->start, evidx,
0917           h->addr[offset].nr_samples, h->addr[offset].period);
0918     return 0;
0919 }
0920 
0921 static struct cyc_hist *symbol__cycles_hist(struct symbol *sym)
0922 {
0923     struct annotation *notes = symbol__annotation(sym);
0924 
0925     if (notes->src == NULL) {
0926         notes->src = annotated_source__new();
0927         if (notes->src == NULL)
0928             return NULL;
0929         goto alloc_cycles_hist;
0930     }
0931 
0932     if (!notes->src->cycles_hist) {
0933 alloc_cycles_hist:
0934         symbol__alloc_hist_cycles(sym);
0935     }
0936 
0937     return notes->src->cycles_hist;
0938 }
0939 
0940 struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists)
0941 {
0942     struct annotation *notes = symbol__annotation(sym);
0943 
0944     if (notes->src == NULL) {
0945         notes->src = annotated_source__new();
0946         if (notes->src == NULL)
0947             return NULL;
0948         goto alloc_histograms;
0949     }
0950 
0951     if (notes->src->histograms == NULL) {
0952 alloc_histograms:
0953         annotated_source__alloc_histograms(notes->src, symbol__size(sym),
0954                            nr_hists);
0955     }
0956 
0957     return notes->src;
0958 }
0959 
0960 static int symbol__inc_addr_samples(struct map_symbol *ms,
0961                     struct evsel *evsel, u64 addr,
0962                     struct perf_sample *sample)
0963 {
0964     struct symbol *sym = ms->sym;
0965     struct annotated_source *src;
0966 
0967     if (sym == NULL)
0968         return 0;
0969     src = symbol__hists(sym, evsel->evlist->core.nr_entries);
0970     return src ? __symbol__inc_addr_samples(ms, src, evsel->core.idx, addr, sample) : 0;
0971 }
0972 
0973 static int symbol__account_cycles(u64 addr, u64 start,
0974                   struct symbol *sym, unsigned cycles)
0975 {
0976     struct cyc_hist *cycles_hist;
0977     unsigned offset;
0978 
0979     if (sym == NULL)
0980         return 0;
0981     cycles_hist = symbol__cycles_hist(sym);
0982     if (cycles_hist == NULL)
0983         return -ENOMEM;
0984     if (addr < sym->start || addr >= sym->end)
0985         return -ERANGE;
0986 
0987     if (start) {
0988         if (start < sym->start || start >= sym->end)
0989             return -ERANGE;
0990         if (start >= addr)
0991             start = 0;
0992     }
0993     offset = addr - sym->start;
0994     return __symbol__account_cycles(cycles_hist,
0995                     start ? start - sym->start : 0,
0996                     offset, cycles,
0997                     !!start);
0998 }
0999 
1000 int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
1001                     struct addr_map_symbol *start,
1002                     unsigned cycles)
1003 {
1004     u64 saddr = 0;
1005     int err;
1006 
1007     if (!cycles)
1008         return 0;
1009 
1010     /*
1011      * Only set start when IPC can be computed. We can only
1012      * compute it when the basic block is completely in a single
1013      * function.
1014      * Special case the case when the jump is elsewhere, but
1015      * it starts on the function start.
1016      */
1017     if (start &&
1018         (start->ms.sym == ams->ms.sym ||
1019          (ams->ms.sym &&
1020            start->addr == ams->ms.sym->start + ams->ms.map->start)))
1021         saddr = start->al_addr;
1022     if (saddr == 0)
1023         pr_debug2("BB with bad start: addr %"PRIx64" start %"PRIx64" sym %"PRIx64" saddr %"PRIx64"\n",
1024             ams->addr,
1025             start ? start->addr : 0,
1026             ams->ms.sym ? ams->ms.sym->start + ams->ms.map->start : 0,
1027             saddr);
1028     err = symbol__account_cycles(ams->al_addr, saddr, ams->ms.sym, cycles);
1029     if (err)
1030         pr_debug2("account_cycles failed %d\n", err);
1031     return err;
1032 }
1033 
1034 static unsigned annotation__count_insn(struct annotation *notes, u64 start, u64 end)
1035 {
1036     unsigned n_insn = 0;
1037     u64 offset;
1038 
1039     for (offset = start; offset <= end; offset++) {
1040         if (notes->offsets[offset])
1041             n_insn++;
1042     }
1043     return n_insn;
1044 }
1045 
1046 static void annotation__count_and_fill(struct annotation *notes, u64 start, u64 end, struct cyc_hist *ch)
1047 {
1048     unsigned n_insn;
1049     unsigned int cover_insn = 0;
1050     u64 offset;
1051 
1052     n_insn = annotation__count_insn(notes, start, end);
1053     if (n_insn && ch->num && ch->cycles) {
1054         float ipc = n_insn / ((double)ch->cycles / (double)ch->num);
1055 
1056         /* Hide data when there are too many overlaps. */
1057         if (ch->reset >= 0x7fff)
1058             return;
1059 
1060         for (offset = start; offset <= end; offset++) {
1061             struct annotation_line *al = notes->offsets[offset];
1062 
1063             if (al && al->ipc == 0.0) {
1064                 al->ipc = ipc;
1065                 cover_insn++;
1066             }
1067         }
1068 
1069         if (cover_insn) {
1070             notes->hit_cycles += ch->cycles;
1071             notes->hit_insn += n_insn * ch->num;
1072             notes->cover_insn += cover_insn;
1073         }
1074     }
1075 }
1076 
1077 void annotation__compute_ipc(struct annotation *notes, size_t size)
1078 {
1079     s64 offset;
1080 
1081     if (!notes->src || !notes->src->cycles_hist)
1082         return;
1083 
1084     notes->total_insn = annotation__count_insn(notes, 0, size - 1);
1085     notes->hit_cycles = 0;
1086     notes->hit_insn = 0;
1087     notes->cover_insn = 0;
1088 
1089     pthread_mutex_lock(&notes->lock);
1090     for (offset = size - 1; offset >= 0; --offset) {
1091         struct cyc_hist *ch;
1092 
1093         ch = &notes->src->cycles_hist[offset];
1094         if (ch && ch->cycles) {
1095             struct annotation_line *al;
1096 
1097             if (ch->have_start)
1098                 annotation__count_and_fill(notes, ch->start, offset, ch);
1099             al = notes->offsets[offset];
1100             if (al && ch->num_aggr) {
1101                 al->cycles = ch->cycles_aggr / ch->num_aggr;
1102                 al->cycles_max = ch->cycles_max;
1103                 al->cycles_min = ch->cycles_min;
1104             }
1105             notes->have_cycles = true;
1106         }
1107     }
1108     pthread_mutex_unlock(&notes->lock);
1109 }
1110 
1111 int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, struct perf_sample *sample,
1112                  struct evsel *evsel)
1113 {
1114     return symbol__inc_addr_samples(&ams->ms, evsel, ams->al_addr, sample);
1115 }
1116 
1117 int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *sample,
1118                  struct evsel *evsel, u64 ip)
1119 {
1120     return symbol__inc_addr_samples(&he->ms, evsel, ip, sample);
1121 }
1122 
1123 static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map_symbol *ms)
1124 {
1125     dl->ins.ops = ins__find(arch, dl->ins.name);
1126 
1127     if (!dl->ins.ops)
1128         return;
1129 
1130     if (dl->ins.ops->parse && dl->ins.ops->parse(arch, &dl->ops, ms) < 0)
1131         dl->ins.ops = NULL;
1132 }
1133 
1134 static int disasm_line__parse(char *line, const char **namep, char **rawp)
1135 {
1136     char tmp, *name = skip_spaces(line);
1137 
1138     if (name[0] == '\0')
1139         return -1;
1140 
1141     *rawp = name + 1;
1142 
1143     while ((*rawp)[0] != '\0' && !isspace((*rawp)[0]))
1144         ++*rawp;
1145 
1146     tmp = (*rawp)[0];
1147     (*rawp)[0] = '\0';
1148     *namep = strdup(name);
1149 
1150     if (*namep == NULL)
1151         goto out;
1152 
1153     (*rawp)[0] = tmp;
1154     *rawp = strim(*rawp);
1155 
1156     return 0;
1157 
1158 out:
1159     return -1;
1160 }
1161 
1162 struct annotate_args {
1163     struct arch       *arch;
1164     struct map_symbol     ms;
1165     struct evsel          *evsel;
1166     struct annotation_options *options;
1167     s64           offset;
1168     char              *line;
1169     int           line_nr;
1170     char              *fileloc;
1171 };
1172 
1173 static void annotation_line__init(struct annotation_line *al,
1174                   struct annotate_args *args,
1175                   int nr)
1176 {
1177     al->offset = args->offset;
1178     al->line = strdup(args->line);
1179     al->line_nr = args->line_nr;
1180     al->fileloc = args->fileloc;
1181     al->data_nr = nr;
1182 }
1183 
1184 static void annotation_line__exit(struct annotation_line *al)
1185 {
1186     free_srcline(al->path);
1187     zfree(&al->line);
1188 }
1189 
1190 static size_t disasm_line_size(int nr)
1191 {
1192     struct annotation_line *al;
1193 
1194     return (sizeof(struct disasm_line) + (sizeof(al->data[0]) * nr));
1195 }
1196 
1197 /*
1198  * Allocating the disasm annotation line data with
1199  * following structure:
1200  *
1201  *    -------------------------------------------
1202  *    struct disasm_line | struct annotation_line
1203  *    -------------------------------------------
1204  *
1205  * We have 'struct annotation_line' member as last member
1206  * of 'struct disasm_line' to have an easy access.
1207  */
1208 static struct disasm_line *disasm_line__new(struct annotate_args *args)
1209 {
1210     struct disasm_line *dl = NULL;
1211     int nr = 1;
1212 
1213     if (evsel__is_group_event(args->evsel))
1214         nr = args->evsel->core.nr_members;
1215 
1216     dl = zalloc(disasm_line_size(nr));
1217     if (!dl)
1218         return NULL;
1219 
1220     annotation_line__init(&dl->al, args, nr);
1221     if (dl->al.line == NULL)
1222         goto out_delete;
1223 
1224     if (args->offset != -1) {
1225         if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0)
1226             goto out_free_line;
1227 
1228         disasm_line__init_ins(dl, args->arch, &args->ms);
1229     }
1230 
1231     return dl;
1232 
1233 out_free_line:
1234     zfree(&dl->al.line);
1235 out_delete:
1236     free(dl);
1237     return NULL;
1238 }
1239 
1240 void disasm_line__free(struct disasm_line *dl)
1241 {
1242     if (dl->ins.ops && dl->ins.ops->free)
1243         dl->ins.ops->free(&dl->ops);
1244     else
1245         ins__delete(&dl->ops);
1246     zfree(&dl->ins.name);
1247     annotation_line__exit(&dl->al);
1248     free(dl);
1249 }
1250 
1251 int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name)
1252 {
1253     if (raw || !dl->ins.ops)
1254         return scnprintf(bf, size, "%-*s %s", max_ins_name, dl->ins.name, dl->ops.raw);
1255 
1256     return ins__scnprintf(&dl->ins, bf, size, &dl->ops, max_ins_name);
1257 }
1258 
1259 void annotation__init(struct annotation *notes)
1260 {
1261     pthread_mutex_init(&notes->lock, NULL);
1262 }
1263 
1264 void annotation__exit(struct annotation *notes)
1265 {
1266     annotated_source__delete(notes->src);
1267     pthread_mutex_destroy(&notes->lock);
1268 }
1269 
1270 static void annotation_line__add(struct annotation_line *al, struct list_head *head)
1271 {
1272     list_add_tail(&al->node, head);
1273 }
1274 
1275 struct annotation_line *
1276 annotation_line__next(struct annotation_line *pos, struct list_head *head)
1277 {
1278     list_for_each_entry_continue(pos, head, node)
1279         if (pos->offset >= 0)
1280             return pos;
1281 
1282     return NULL;
1283 }
1284 
1285 static const char *annotate__address_color(struct block_range *br)
1286 {
1287     double cov = block_range__coverage(br);
1288 
1289     if (cov >= 0) {
1290         /* mark red for >75% coverage */
1291         if (cov > 0.75)
1292             return PERF_COLOR_RED;
1293 
1294         /* mark dull for <1% coverage */
1295         if (cov < 0.01)
1296             return PERF_COLOR_NORMAL;
1297     }
1298 
1299     return PERF_COLOR_MAGENTA;
1300 }
1301 
1302 static const char *annotate__asm_color(struct block_range *br)
1303 {
1304     double cov = block_range__coverage(br);
1305 
1306     if (cov >= 0) {
1307         /* mark dull for <1% coverage */
1308         if (cov < 0.01)
1309             return PERF_COLOR_NORMAL;
1310     }
1311 
1312     return PERF_COLOR_BLUE;
1313 }
1314 
1315 static void annotate__branch_printf(struct block_range *br, u64 addr)
1316 {
1317     bool emit_comment = true;
1318 
1319     if (!br)
1320         return;
1321 
1322 #if 1
1323     if (br->is_target && br->start == addr) {
1324         struct block_range *branch = br;
1325         double p;
1326 
1327         /*
1328          * Find matching branch to our target.
1329          */
1330         while (!branch->is_branch)
1331             branch = block_range__next(branch);
1332 
1333         p = 100 *(double)br->entry / branch->coverage;
1334 
1335         if (p > 0.1) {
1336             if (emit_comment) {
1337                 emit_comment = false;
1338                 printf("\t#");
1339             }
1340 
1341             /*
1342              * The percentage of coverage joined at this target in relation
1343              * to the next branch.
1344              */
1345             printf(" +%.2f%%", p);
1346         }
1347     }
1348 #endif
1349     if (br->is_branch && br->end == addr) {
1350         double p = 100*(double)br->taken / br->coverage;
1351 
1352         if (p > 0.1) {
1353             if (emit_comment) {
1354                 emit_comment = false;
1355                 printf("\t#");
1356             }
1357 
1358             /*
1359              * The percentage of coverage leaving at this branch, and
1360              * its prediction ratio.
1361              */
1362             printf(" -%.2f%% (p:%.2f%%)", p, 100*(double)br->pred  / br->taken);
1363         }
1364     }
1365 }
1366 
1367 static int disasm_line__print(struct disasm_line *dl, u64 start, int addr_fmt_width)
1368 {
1369     s64 offset = dl->al.offset;
1370     const u64 addr = start + offset;
1371     struct block_range *br;
1372 
1373     br = block_range__find(addr);
1374     color_fprintf(stdout, annotate__address_color(br), "  %*" PRIx64 ":", addr_fmt_width, addr);
1375     color_fprintf(stdout, annotate__asm_color(br), "%s", dl->al.line);
1376     annotate__branch_printf(br, addr);
1377     return 0;
1378 }
1379 
1380 static int
1381 annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start,
1382                struct evsel *evsel, u64 len, int min_pcnt, int printed,
1383                int max_lines, struct annotation_line *queue, int addr_fmt_width,
1384                int percent_type)
1385 {
1386     struct disasm_line *dl = container_of(al, struct disasm_line, al);
1387     static const char *prev_line;
1388 
1389     if (al->offset != -1) {
1390         double max_percent = 0.0;
1391         int i, nr_percent = 1;
1392         const char *color;
1393         struct annotation *notes = symbol__annotation(sym);
1394 
1395         for (i = 0; i < al->data_nr; i++) {
1396             double percent;
1397 
1398             percent = annotation_data__percent(&al->data[i],
1399                                percent_type);
1400 
1401             if (percent > max_percent)
1402                 max_percent = percent;
1403         }
1404 
1405         if (al->data_nr > nr_percent)
1406             nr_percent = al->data_nr;
1407 
1408         if (max_percent < min_pcnt)
1409             return -1;
1410 
1411         if (max_lines && printed >= max_lines)
1412             return 1;
1413 
1414         if (queue != NULL) {
1415             list_for_each_entry_from(queue, &notes->src->source, node) {
1416                 if (queue == al)
1417                     break;
1418                 annotation_line__print(queue, sym, start, evsel, len,
1419                                0, 0, 1, NULL, addr_fmt_width,
1420                                percent_type);
1421             }
1422         }
1423 
1424         color = get_percent_color(max_percent);
1425 
1426         for (i = 0; i < nr_percent; i++) {
1427             struct annotation_data *data = &al->data[i];
1428             double percent;
1429 
1430             percent = annotation_data__percent(data, percent_type);
1431             color = get_percent_color(percent);
1432 
1433             if (symbol_conf.show_total_period)
1434                 color_fprintf(stdout, color, " %11" PRIu64,
1435                           data->he.period);
1436             else if (symbol_conf.show_nr_samples)
1437                 color_fprintf(stdout, color, " %7" PRIu64,
1438                           data->he.nr_samples);
1439             else
1440                 color_fprintf(stdout, color, " %7.2f", percent);
1441         }
1442 
1443         printf(" : ");
1444 
1445         disasm_line__print(dl, start, addr_fmt_width);
1446 
1447         /*
1448          * Also color the filename and line if needed, with
1449          * the same color than the percentage. Don't print it
1450          * twice for close colored addr with the same filename:line
1451          */
1452         if (al->path) {
1453             if (!prev_line || strcmp(prev_line, al->path)) {
1454                 color_fprintf(stdout, color, " // %s", al->path);
1455                 prev_line = al->path;
1456             }
1457         }
1458 
1459         printf("\n");
1460     } else if (max_lines && printed >= max_lines)
1461         return 1;
1462     else {
1463         int width = symbol_conf.show_total_period ? 12 : 8;
1464 
1465         if (queue)
1466             return -1;
1467 
1468         if (evsel__is_group_event(evsel))
1469             width *= evsel->core.nr_members;
1470 
1471         if (!*al->line)
1472             printf(" %*s:\n", width, " ");
1473         else
1474             printf(" %*s: %-*d %s\n", width, " ", addr_fmt_width, al->line_nr, al->line);
1475     }
1476 
1477     return 0;
1478 }
1479 
1480 /*
1481  * symbol__parse_objdump_line() parses objdump output (with -d --no-show-raw)
1482  * which looks like following
1483  *
1484  *  0000000000415500 <_init>:
1485  *    415500:       sub    $0x8,%rsp
1486  *    415504:       mov    0x2f5ad5(%rip),%rax        # 70afe0 <_DYNAMIC+0x2f8>
1487  *    41550b:       test   %rax,%rax
1488  *    41550e:       je     415515 <_init+0x15>
1489  *    415510:       callq  416e70 <__gmon_start__@plt>
1490  *    415515:       add    $0x8,%rsp
1491  *    415519:       retq
1492  *
1493  * it will be parsed and saved into struct disasm_line as
1494  *  <offset>       <name>  <ops.raw>
1495  *
1496  * The offset will be a relative offset from the start of the symbol and -1
1497  * means that it's not a disassembly line so should be treated differently.
1498  * The ops.raw part will be parsed further according to type of the instruction.
1499  */
1500 static int symbol__parse_objdump_line(struct symbol *sym,
1501                       struct annotate_args *args,
1502                       char *parsed_line, int *line_nr, char **fileloc)
1503 {
1504     struct map *map = args->ms.map;
1505     struct annotation *notes = symbol__annotation(sym);
1506     struct disasm_line *dl;
1507     char *tmp;
1508     s64 line_ip, offset = -1;
1509     regmatch_t match[2];
1510 
1511     /* /filename:linenr ? Save line number and ignore. */
1512     if (regexec(&file_lineno, parsed_line, 2, match, 0) == 0) {
1513         *line_nr = atoi(parsed_line + match[1].rm_so);
1514         *fileloc = strdup(parsed_line);
1515         return 0;
1516     }
1517 
1518     /* Process hex address followed by ':'. */
1519     line_ip = strtoull(parsed_line, &tmp, 16);
1520     if (parsed_line != tmp && tmp[0] == ':' && tmp[1] != '\0') {
1521         u64 start = map__rip_2objdump(map, sym->start),
1522             end = map__rip_2objdump(map, sym->end);
1523 
1524         offset = line_ip - start;
1525         if ((u64)line_ip < start || (u64)line_ip >= end)
1526             offset = -1;
1527         else
1528             parsed_line = tmp + 1;
1529     }
1530 
1531     args->offset  = offset;
1532     args->line    = parsed_line;
1533     args->line_nr = *line_nr;
1534     args->fileloc = *fileloc;
1535     args->ms.sym  = sym;
1536 
1537     dl = disasm_line__new(args);
1538     (*line_nr)++;
1539 
1540     if (dl == NULL)
1541         return -1;
1542 
1543     if (!disasm_line__has_local_offset(dl)) {
1544         dl->ops.target.offset = dl->ops.target.addr -
1545                     map__rip_2objdump(map, sym->start);
1546         dl->ops.target.offset_avail = true;
1547     }
1548 
1549     /* kcore has no symbols, so add the call target symbol */
1550     if (dl->ins.ops && ins__is_call(&dl->ins) && !dl->ops.target.sym) {
1551         struct addr_map_symbol target = {
1552             .addr = dl->ops.target.addr,
1553             .ms = { .map = map, },
1554         };
1555 
1556         if (!maps__find_ams(args->ms.maps, &target) &&
1557             target.ms.sym->start == target.al_addr)
1558             dl->ops.target.sym = target.ms.sym;
1559     }
1560 
1561     annotation_line__add(&dl->al, &notes->src->source);
1562 
1563     return 0;
1564 }
1565 
1566 static __attribute__((constructor)) void symbol__init_regexpr(void)
1567 {
1568     regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED);
1569 }
1570 
1571 static void delete_last_nop(struct symbol *sym)
1572 {
1573     struct annotation *notes = symbol__annotation(sym);
1574     struct list_head *list = &notes->src->source;
1575     struct disasm_line *dl;
1576 
1577     while (!list_empty(list)) {
1578         dl = list_entry(list->prev, struct disasm_line, al.node);
1579 
1580         if (dl->ins.ops) {
1581             if (dl->ins.ops != &nop_ops)
1582                 return;
1583         } else {
1584             if (!strstr(dl->al.line, " nop ") &&
1585                 !strstr(dl->al.line, " nopl ") &&
1586                 !strstr(dl->al.line, " nopw "))
1587                 return;
1588         }
1589 
1590         list_del_init(&dl->al.node);
1591         disasm_line__free(dl);
1592     }
1593 }
1594 
1595 int symbol__strerror_disassemble(struct map_symbol *ms, int errnum, char *buf, size_t buflen)
1596 {
1597     struct dso *dso = ms->map->dso;
1598 
1599     BUG_ON(buflen == 0);
1600 
1601     if (errnum >= 0) {
1602         str_error_r(errnum, buf, buflen);
1603         return 0;
1604     }
1605 
1606     switch (errnum) {
1607     case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: {
1608         char bf[SBUILD_ID_SIZE + 15] = " with build id ";
1609         char *build_id_msg = NULL;
1610 
1611         if (dso->has_build_id) {
1612             build_id__sprintf(&dso->bid, bf + 15);
1613             build_id_msg = bf;
1614         }
1615         scnprintf(buf, buflen,
1616               "No vmlinux file%s\nwas found in the path.\n\n"
1617               "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"
1618               "Please use:\n\n"
1619               "  perf buildid-cache -vu vmlinux\n\n"
1620               "or:\n\n"
1621               "  --vmlinux vmlinux\n", build_id_msg ?: "");
1622     }
1623         break;
1624     case SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF:
1625         scnprintf(buf, buflen, "Please link with binutils's libopcode to enable BPF annotation");
1626         break;
1627     case SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_REGEXP:
1628         scnprintf(buf, buflen, "Problems with arch specific instruction name regular expressions.");
1629         break;
1630     case SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING:
1631         scnprintf(buf, buflen, "Problems while parsing the CPUID in the arch specific initialization.");
1632         break;
1633     case SYMBOL_ANNOTATE_ERRNO__BPF_INVALID_FILE:
1634         scnprintf(buf, buflen, "Invalid BPF file: %s.", dso->long_name);
1635         break;
1636     case SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF:
1637         scnprintf(buf, buflen, "The %s BPF file has no BTF section, compile with -g or use pahole -J.",
1638               dso->long_name);
1639         break;
1640     default:
1641         scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum);
1642         break;
1643     }
1644 
1645     return 0;
1646 }
1647 
1648 static int dso__disassemble_filename(struct dso *dso, char *filename, size_t filename_size)
1649 {
1650     char linkname[PATH_MAX];
1651     char *build_id_filename;
1652     char *build_id_path = NULL;
1653     char *pos;
1654     int len;
1655 
1656     if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1657         !dso__is_kcore(dso))
1658         return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
1659 
1660     build_id_filename = dso__build_id_filename(dso, NULL, 0, false);
1661     if (build_id_filename) {
1662         __symbol__join_symfs(filename, filename_size, build_id_filename);
1663         free(build_id_filename);
1664     } else {
1665         if (dso->has_build_id)
1666             return ENOMEM;
1667         goto fallback;
1668     }
1669 
1670     build_id_path = strdup(filename);
1671     if (!build_id_path)
1672         return ENOMEM;
1673 
1674     /*
1675      * old style build-id cache has name of XX/XXXXXXX.. while
1676      * new style has XX/XXXXXXX../{elf,kallsyms,vdso}.
1677      * extract the build-id part of dirname in the new style only.
1678      */
1679     pos = strrchr(build_id_path, '/');
1680     if (pos && strlen(pos) < SBUILD_ID_SIZE - 2)
1681         dirname(build_id_path);
1682 
1683     if (dso__is_kcore(dso))
1684         goto fallback;
1685 
1686     len = readlink(build_id_path, linkname, sizeof(linkname) - 1);
1687     if (len < 0)
1688         goto fallback;
1689 
1690     linkname[len] = '\0';
1691     if (strstr(linkname, DSO__NAME_KALLSYMS) ||
1692         access(filename, R_OK)) {
1693 fallback:
1694         /*
1695          * If we don't have build-ids or the build-id file isn't in the
1696          * cache, or is just a kallsyms file, well, lets hope that this
1697          * DSO is the same as when 'perf record' ran.
1698          */
1699         __symbol__join_symfs(filename, filename_size, dso->long_name);
1700 
1701         if (access(filename, R_OK) && errno == ENOENT && dso->nsinfo) {
1702             char *new_name = filename_with_chroot(dso->nsinfo->pid,
1703                                   filename);
1704             if (new_name) {
1705                 strlcpy(filename, new_name, filename_size);
1706                 free(new_name);
1707             }
1708         }
1709     }
1710 
1711     free(build_id_path);
1712     return 0;
1713 }
1714 
1715 #if defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
1716 #define PACKAGE "perf"
1717 #include <bfd.h>
1718 #include <dis-asm.h>
1719 #include <bpf/bpf.h>
1720 #include <bpf/btf.h>
1721 #include <bpf/libbpf.h>
1722 #include <linux/btf.h>
1723 #include <tools/dis-asm-compat.h>
1724 
1725 static int symbol__disassemble_bpf(struct symbol *sym,
1726                    struct annotate_args *args)
1727 {
1728     struct annotation *notes = symbol__annotation(sym);
1729     struct annotation_options *opts = args->options;
1730     struct bpf_prog_linfo *prog_linfo = NULL;
1731     struct bpf_prog_info_node *info_node;
1732     int len = sym->end - sym->start;
1733     disassembler_ftype disassemble;
1734     struct map *map = args->ms.map;
1735     struct perf_bpil *info_linear;
1736     struct disassemble_info info;
1737     struct dso *dso = map->dso;
1738     int pc = 0, count, sub_id;
1739     struct btf *btf = NULL;
1740     char tpath[PATH_MAX];
1741     size_t buf_size;
1742     int nr_skip = 0;
1743     char *buf;
1744     bfd *bfdf;
1745     int ret;
1746     FILE *s;
1747 
1748     if (dso->binary_type != DSO_BINARY_TYPE__BPF_PROG_INFO)
1749         return SYMBOL_ANNOTATE_ERRNO__BPF_INVALID_FILE;
1750 
1751     pr_debug("%s: handling sym %s addr %" PRIx64 " len %" PRIx64 "\n", __func__,
1752           sym->name, sym->start, sym->end - sym->start);
1753 
1754     memset(tpath, 0, sizeof(tpath));
1755     perf_exe(tpath, sizeof(tpath));
1756 
1757     bfdf = bfd_openr(tpath, NULL);
1758     assert(bfdf);
1759     assert(bfd_check_format(bfdf, bfd_object));
1760 
1761     s = open_memstream(&buf, &buf_size);
1762     if (!s) {
1763         ret = errno;
1764         goto out;
1765     }
1766     init_disassemble_info_compat(&info, s,
1767                      (fprintf_ftype) fprintf,
1768                      fprintf_styled);
1769     info.arch = bfd_get_arch(bfdf);
1770     info.mach = bfd_get_mach(bfdf);
1771 
1772     info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env,
1773                          dso->bpf_prog.id);
1774     if (!info_node) {
1775         ret = SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF;
1776         goto out;
1777     }
1778     info_linear = info_node->info_linear;
1779     sub_id = dso->bpf_prog.sub_id;
1780 
1781     info.buffer = (void *)(uintptr_t)(info_linear->info.jited_prog_insns);
1782     info.buffer_length = info_linear->info.jited_prog_len;
1783 
1784     if (info_linear->info.nr_line_info)
1785         prog_linfo = bpf_prog_linfo__new(&info_linear->info);
1786 
1787     if (info_linear->info.btf_id) {
1788         struct btf_node *node;
1789 
1790         node = perf_env__find_btf(dso->bpf_prog.env,
1791                       info_linear->info.btf_id);
1792         if (node)
1793             btf = btf__new((__u8 *)(node->data),
1794                        node->data_size);
1795     }
1796 
1797     disassemble_init_for_target(&info);
1798 
1799 #ifdef DISASM_FOUR_ARGS_SIGNATURE
1800     disassemble = disassembler(info.arch,
1801                    bfd_big_endian(bfdf),
1802                    info.mach,
1803                    bfdf);
1804 #else
1805     disassemble = disassembler(bfdf);
1806 #endif
1807     assert(disassemble);
1808 
1809     fflush(s);
1810     do {
1811         const struct bpf_line_info *linfo = NULL;
1812         struct disasm_line *dl;
1813         size_t prev_buf_size;
1814         const char *srcline;
1815         u64 addr;
1816 
1817         addr = pc + ((u64 *)(uintptr_t)(info_linear->info.jited_ksyms))[sub_id];
1818         count = disassemble(pc, &info);
1819 
1820         if (prog_linfo)
1821             linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo,
1822                                 addr, sub_id,
1823                                 nr_skip);
1824 
1825         if (linfo && btf) {
1826             srcline = btf__name_by_offset(btf, linfo->line_off);
1827             nr_skip++;
1828         } else
1829             srcline = NULL;
1830 
1831         fprintf(s, "\n");
1832         prev_buf_size = buf_size;
1833         fflush(s);
1834 
1835         if (!opts->hide_src_code && srcline) {
1836             args->offset = -1;
1837             args->line = strdup(srcline);
1838             args->line_nr = 0;
1839             args->fileloc = NULL;
1840             args->ms.sym  = sym;
1841             dl = disasm_line__new(args);
1842             if (dl) {
1843                 annotation_line__add(&dl->al,
1844                              &notes->src->source);
1845             }
1846         }
1847 
1848         args->offset = pc;
1849         args->line = buf + prev_buf_size;
1850         args->line_nr = 0;
1851         args->fileloc = NULL;
1852         args->ms.sym  = sym;
1853         dl = disasm_line__new(args);
1854         if (dl)
1855             annotation_line__add(&dl->al, &notes->src->source);
1856 
1857         pc += count;
1858     } while (count > 0 && pc < len);
1859 
1860     ret = 0;
1861 out:
1862     free(prog_linfo);
1863     btf__free(btf);
1864     fclose(s);
1865     bfd_close(bfdf);
1866     return ret;
1867 }
1868 #else // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
1869 static int symbol__disassemble_bpf(struct symbol *sym __maybe_unused,
1870                    struct annotate_args *args __maybe_unused)
1871 {
1872     return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF;
1873 }
1874 #endif // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
1875 
1876 static int
1877 symbol__disassemble_bpf_image(struct symbol *sym,
1878                   struct annotate_args *args)
1879 {
1880     struct annotation *notes = symbol__annotation(sym);
1881     struct disasm_line *dl;
1882 
1883     args->offset = -1;
1884     args->line = strdup("to be implemented");
1885     args->line_nr = 0;
1886     args->fileloc = NULL;
1887     dl = disasm_line__new(args);
1888     if (dl)
1889         annotation_line__add(&dl->al, &notes->src->source);
1890 
1891     free(args->line);
1892     return 0;
1893 }
1894 
1895 /*
1896  * Possibly create a new version of line with tabs expanded. Returns the
1897  * existing or new line, storage is updated if a new line is allocated. If
1898  * allocation fails then NULL is returned.
1899  */
1900 static char *expand_tabs(char *line, char **storage, size_t *storage_len)
1901 {
1902     size_t i, src, dst, len, new_storage_len, num_tabs;
1903     char *new_line;
1904     size_t line_len = strlen(line);
1905 
1906     for (num_tabs = 0, i = 0; i < line_len; i++)
1907         if (line[i] == '\t')
1908             num_tabs++;
1909 
1910     if (num_tabs == 0)
1911         return line;
1912 
1913     /*
1914      * Space for the line and '\0', less the leading and trailing
1915      * spaces. Each tab may introduce 7 additional spaces.
1916      */
1917     new_storage_len = line_len + 1 + (num_tabs * 7);
1918 
1919     new_line = malloc(new_storage_len);
1920     if (new_line == NULL) {
1921         pr_err("Failure allocating memory for tab expansion\n");
1922         return NULL;
1923     }
1924 
1925     /*
1926      * Copy regions starting at src and expand tabs. If there are two
1927      * adjacent tabs then 'src == i', the memcpy is of size 0 and the spaces
1928      * are inserted.
1929      */
1930     for (i = 0, src = 0, dst = 0; i < line_len && num_tabs; i++) {
1931         if (line[i] == '\t') {
1932             len = i - src;
1933             memcpy(&new_line[dst], &line[src], len);
1934             dst += len;
1935             new_line[dst++] = ' ';
1936             while (dst % 8 != 0)
1937                 new_line[dst++] = ' ';
1938             src = i + 1;
1939             num_tabs--;
1940         }
1941     }
1942 
1943     /* Expand the last region. */
1944     len = line_len - src;
1945     memcpy(&new_line[dst], &line[src], len);
1946     dst += len;
1947     new_line[dst] = '\0';
1948 
1949     free(*storage);
1950     *storage = new_line;
1951     *storage_len = new_storage_len;
1952     return new_line;
1953 
1954 }
1955 
1956 static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1957 {
1958     struct annotation_options *opts = args->options;
1959     struct map *map = args->ms.map;
1960     struct dso *dso = map->dso;
1961     char *command;
1962     FILE *file;
1963     char symfs_filename[PATH_MAX];
1964     struct kcore_extract kce;
1965     bool delete_extract = false;
1966     bool decomp = false;
1967     int lineno = 0;
1968     char *fileloc = NULL;
1969     int nline;
1970     char *line;
1971     size_t line_len;
1972     const char *objdump_argv[] = {
1973         "/bin/sh",
1974         "-c",
1975         NULL, /* Will be the objdump command to run. */
1976         "--",
1977         NULL, /* Will be the symfs path. */
1978         NULL,
1979     };
1980     struct child_process objdump_process;
1981     int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));
1982 
1983     if (err)
1984         return err;
1985 
1986     pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
1987          symfs_filename, sym->name, map->unmap_ip(map, sym->start),
1988          map->unmap_ip(map, sym->end));
1989 
1990     pr_debug("annotating [%p] %30s : [%p] %30s\n",
1991          dso, dso->long_name, sym, sym->name);
1992 
1993     if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) {
1994         return symbol__disassemble_bpf(sym, args);
1995     } else if (dso->binary_type == DSO_BINARY_TYPE__BPF_IMAGE) {
1996         return symbol__disassemble_bpf_image(sym, args);
1997     } else if (dso__is_kcore(dso)) {
1998         kce.kcore_filename = symfs_filename;
1999         kce.addr = map__rip_2objdump(map, sym->start);
2000         kce.offs = sym->start;
2001         kce.len = sym->end - sym->start;
2002         if (!kcore_extract__create(&kce)) {
2003             delete_extract = true;
2004             strlcpy(symfs_filename, kce.extract_filename,
2005                 sizeof(symfs_filename));
2006         }
2007     } else if (dso__needs_decompress(dso)) {
2008         char tmp[KMOD_DECOMP_LEN];
2009 
2010         if (dso__decompress_kmodule_path(dso, symfs_filename,
2011                          tmp, sizeof(tmp)) < 0)
2012             return -1;
2013 
2014         decomp = true;
2015         strcpy(symfs_filename, tmp);
2016     }
2017 
2018     err = asprintf(&command,
2019          "%s %s%s --start-address=0x%016" PRIx64
2020          " --stop-address=0x%016" PRIx64
2021          " -l -d %s %s %s %c%s%c %s%s -C \"$1\"",
2022          opts->objdump_path ?: "objdump",
2023          opts->disassembler_style ? "-M " : "",
2024          opts->disassembler_style ?: "",
2025          map__rip_2objdump(map, sym->start),
2026          map__rip_2objdump(map, sym->end),
2027          opts->show_asm_raw ? "" : "--no-show-raw-insn",
2028          opts->annotate_src ? "-S" : "",
2029          opts->prefix ? "--prefix " : "",
2030          opts->prefix ? '"' : ' ',
2031          opts->prefix ?: "",
2032          opts->prefix ? '"' : ' ',
2033          opts->prefix_strip ? "--prefix-strip=" : "",
2034          opts->prefix_strip ?: "");
2035 
2036     if (err < 0) {
2037         pr_err("Failure allocating memory for the command to run\n");
2038         goto out_remove_tmp;
2039     }
2040 
2041     pr_debug("Executing: %s\n", command);
2042 
2043     objdump_argv[2] = command;
2044     objdump_argv[4] = symfs_filename;
2045 
2046     /* Create a pipe to read from for stdout */
2047     memset(&objdump_process, 0, sizeof(objdump_process));
2048     objdump_process.argv = objdump_argv;
2049     objdump_process.out = -1;
2050     objdump_process.err = -1;
2051     objdump_process.no_stderr = 1;
2052     if (start_command(&objdump_process)) {
2053         pr_err("Failure starting to run %s\n", command);
2054         err = -1;
2055         goto out_free_command;
2056     }
2057 
2058     file = fdopen(objdump_process.out, "r");
2059     if (!file) {
2060         pr_err("Failure creating FILE stream for %s\n", command);
2061         /*
2062          * If we were using debug info should retry with
2063          * original binary.
2064          */
2065         err = -1;
2066         goto out_close_stdout;
2067     }
2068 
2069     /* Storage for getline. */
2070     line = NULL;
2071     line_len = 0;
2072 
2073     nline = 0;
2074     while (!feof(file)) {
2075         const char *match;
2076         char *expanded_line;
2077 
2078         if (getline(&line, &line_len, file) < 0 || !line)
2079             break;
2080 
2081         /* Skip lines containing "filename:" */
2082         match = strstr(line, symfs_filename);
2083         if (match && match[strlen(symfs_filename)] == ':')
2084             continue;
2085 
2086         expanded_line = strim(line);
2087         expanded_line = expand_tabs(expanded_line, &line, &line_len);
2088         if (!expanded_line)
2089             break;
2090 
2091         /*
2092          * The source code line number (lineno) needs to be kept in
2093          * across calls to symbol__parse_objdump_line(), so that it
2094          * can associate it with the instructions till the next one.
2095          * See disasm_line__new() and struct disasm_line::line_nr.
2096          */
2097         if (symbol__parse_objdump_line(sym, args, expanded_line,
2098                            &lineno, &fileloc) < 0)
2099             break;
2100         nline++;
2101     }
2102     free(line);
2103 
2104     err = finish_command(&objdump_process);
2105     if (err)
2106         pr_err("Error running %s\n", command);
2107 
2108     if (nline == 0) {
2109         err = -1;
2110         pr_err("No output from %s\n", command);
2111     }
2112 
2113     /*
2114      * kallsyms does not have symbol sizes so there may a nop at the end.
2115      * Remove it.
2116      */
2117     if (dso__is_kcore(dso))
2118         delete_last_nop(sym);
2119 
2120     fclose(file);
2121 
2122 out_close_stdout:
2123     close(objdump_process.out);
2124 
2125 out_free_command:
2126     free(command);
2127 
2128 out_remove_tmp:
2129     if (decomp)
2130         unlink(symfs_filename);
2131 
2132     if (delete_extract)
2133         kcore_extract__delete(&kce);
2134 
2135     return err;
2136 }
2137 
2138 static void calc_percent(struct sym_hist *sym_hist,
2139              struct hists *hists,
2140              struct annotation_data *data,
2141              s64 offset, s64 end)
2142 {
2143     unsigned int hits = 0;
2144     u64 period = 0;
2145 
2146     while (offset < end) {
2147         hits   += sym_hist->addr[offset].nr_samples;
2148         period += sym_hist->addr[offset].period;
2149         ++offset;
2150     }
2151 
2152     if (sym_hist->nr_samples) {
2153         data->he.period     = period;
2154         data->he.nr_samples = hits;
2155         data->percent[PERCENT_HITS_LOCAL] = 100.0 * hits / sym_hist->nr_samples;
2156     }
2157 
2158     if (hists->stats.nr_non_filtered_samples)
2159         data->percent[PERCENT_HITS_GLOBAL] = 100.0 * hits / hists->stats.nr_non_filtered_samples;
2160 
2161     if (sym_hist->period)
2162         data->percent[PERCENT_PERIOD_LOCAL] = 100.0 * period / sym_hist->period;
2163 
2164     if (hists->stats.total_period)
2165         data->percent[PERCENT_PERIOD_GLOBAL] = 100.0 * period / hists->stats.total_period;
2166 }
2167 
2168 static void annotation__calc_percent(struct annotation *notes,
2169                      struct evsel *leader, s64 len)
2170 {
2171     struct annotation_line *al, *next;
2172     struct evsel *evsel;
2173 
2174     list_for_each_entry(al, &notes->src->source, node) {
2175         s64 end;
2176         int i = 0;
2177 
2178         if (al->offset == -1)
2179             continue;
2180 
2181         next = annotation_line__next(al, &notes->src->source);
2182         end  = next ? next->offset : len;
2183 
2184         for_each_group_evsel(evsel, leader) {
2185             struct hists *hists = evsel__hists(evsel);
2186             struct annotation_data *data;
2187             struct sym_hist *sym_hist;
2188 
2189             BUG_ON(i >= al->data_nr);
2190 
2191             sym_hist = annotation__histogram(notes, evsel->core.idx);
2192             data = &al->data[i++];
2193 
2194             calc_percent(sym_hist, hists, data, al->offset, end);
2195         }
2196     }
2197 }
2198 
2199 void symbol__calc_percent(struct symbol *sym, struct evsel *evsel)
2200 {
2201     struct annotation *notes = symbol__annotation(sym);
2202 
2203     annotation__calc_percent(notes, evsel, symbol__size(sym));
2204 }
2205 
2206 int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
2207              struct annotation_options *options, struct arch **parch)
2208 {
2209     struct symbol *sym = ms->sym;
2210     struct annotation *notes = symbol__annotation(sym);
2211     struct annotate_args args = {
2212         .evsel      = evsel,
2213         .options    = options,
2214     };
2215     struct perf_env *env = evsel__env(evsel);
2216     const char *arch_name = perf_env__arch(env);
2217     struct arch *arch;
2218     int err;
2219 
2220     if (!arch_name)
2221         return errno;
2222 
2223     args.arch = arch = arch__find(arch_name);
2224     if (arch == NULL) {
2225         pr_err("%s: unsupported arch %s\n", __func__, arch_name);
2226         return ENOTSUP;
2227     }
2228 
2229     if (parch)
2230         *parch = arch;
2231 
2232     if (arch->init) {
2233         err = arch->init(arch, env ? env->cpuid : NULL);
2234         if (err) {
2235             pr_err("%s: failed to initialize %s arch priv area\n", __func__, arch->name);
2236             return err;
2237         }
2238     }
2239 
2240     args.ms = *ms;
2241     notes->start = map__rip_2objdump(ms->map, sym->start);
2242 
2243     return symbol__disassemble(sym, &args);
2244 }
2245 
2246 static void insert_source_line(struct rb_root *root, struct annotation_line *al,
2247                    struct annotation_options *opts)
2248 {
2249     struct annotation_line *iter;
2250     struct rb_node **p = &root->rb_node;
2251     struct rb_node *parent = NULL;
2252     int i, ret;
2253 
2254     while (*p != NULL) {
2255         parent = *p;
2256         iter = rb_entry(parent, struct annotation_line, rb_node);
2257 
2258         ret = strcmp(iter->path, al->path);
2259         if (ret == 0) {
2260             for (i = 0; i < al->data_nr; i++) {
2261                 iter->data[i].percent_sum += annotation_data__percent(&al->data[i],
2262                                               opts->percent_type);
2263             }
2264             return;
2265         }
2266 
2267         if (ret < 0)
2268             p = &(*p)->rb_left;
2269         else
2270             p = &(*p)->rb_right;
2271     }
2272 
2273     for (i = 0; i < al->data_nr; i++) {
2274         al->data[i].percent_sum = annotation_data__percent(&al->data[i],
2275                                    opts->percent_type);
2276     }
2277 
2278     rb_link_node(&al->rb_node, parent, p);
2279     rb_insert_color(&al->rb_node, root);
2280 }
2281 
2282 static int cmp_source_line(struct annotation_line *a, struct annotation_line *b)
2283 {
2284     int i;
2285 
2286     for (i = 0; i < a->data_nr; i++) {
2287         if (a->data[i].percent_sum == b->data[i].percent_sum)
2288             continue;
2289         return a->data[i].percent_sum > b->data[i].percent_sum;
2290     }
2291 
2292     return 0;
2293 }
2294 
2295 static void __resort_source_line(struct rb_root *root, struct annotation_line *al)
2296 {
2297     struct annotation_line *iter;
2298     struct rb_node **p = &root->rb_node;
2299     struct rb_node *parent = NULL;
2300 
2301     while (*p != NULL) {
2302         parent = *p;
2303         iter = rb_entry(parent, struct annotation_line, rb_node);
2304 
2305         if (cmp_source_line(al, iter))
2306             p = &(*p)->rb_left;
2307         else
2308             p = &(*p)->rb_right;
2309     }
2310 
2311     rb_link_node(&al->rb_node, parent, p);
2312     rb_insert_color(&al->rb_node, root);
2313 }
2314 
2315 static void resort_source_line(struct rb_root *dest_root, struct rb_root *src_root)
2316 {
2317     struct annotation_line *al;
2318     struct rb_node *node;
2319 
2320     node = rb_first(src_root);
2321     while (node) {
2322         struct rb_node *next;
2323 
2324         al = rb_entry(node, struct annotation_line, rb_node);
2325         next = rb_next(node);
2326         rb_erase(node, src_root);
2327 
2328         __resort_source_line(dest_root, al);
2329         node = next;
2330     }
2331 }
2332 
2333 static void print_summary(struct rb_root *root, const char *filename)
2334 {
2335     struct annotation_line *al;
2336     struct rb_node *node;
2337 
2338     printf("\nSorted summary for file %s\n", filename);
2339     printf("----------------------------------------------\n\n");
2340 
2341     if (RB_EMPTY_ROOT(root)) {
2342         printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
2343         return;
2344     }
2345 
2346     node = rb_first(root);
2347     while (node) {
2348         double percent, percent_max = 0.0;
2349         const char *color;
2350         char *path;
2351         int i;
2352 
2353         al = rb_entry(node, struct annotation_line, rb_node);
2354         for (i = 0; i < al->data_nr; i++) {
2355             percent = al->data[i].percent_sum;
2356             color = get_percent_color(percent);
2357             color_fprintf(stdout, color, " %7.2f", percent);
2358 
2359             if (percent > percent_max)
2360                 percent_max = percent;
2361         }
2362 
2363         path = al->path;
2364         color = get_percent_color(percent_max);
2365         color_fprintf(stdout, color, " %s\n", path);
2366 
2367         node = rb_next(node);
2368     }
2369 }
2370 
2371 static void symbol__annotate_hits(struct symbol *sym, struct evsel *evsel)
2372 {
2373     struct annotation *notes = symbol__annotation(sym);
2374     struct sym_hist *h = annotation__histogram(notes, evsel->core.idx);
2375     u64 len = symbol__size(sym), offset;
2376 
2377     for (offset = 0; offset < len; ++offset)
2378         if (h->addr[offset].nr_samples != 0)
2379             printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
2380                    sym->start + offset, h->addr[offset].nr_samples);
2381     printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->nr_samples", h->nr_samples);
2382 }
2383 
2384 static int annotated_source__addr_fmt_width(struct list_head *lines, u64 start)
2385 {
2386     char bf[32];
2387     struct annotation_line *line;
2388 
2389     list_for_each_entry_reverse(line, lines, node) {
2390         if (line->offset != -1)
2391             return scnprintf(bf, sizeof(bf), "%" PRIx64, start + line->offset);
2392     }
2393 
2394     return 0;
2395 }
2396 
2397 int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel,
2398                 struct annotation_options *opts)
2399 {
2400     struct map *map = ms->map;
2401     struct symbol *sym = ms->sym;
2402     struct dso *dso = map->dso;
2403     char *filename;
2404     const char *d_filename;
2405     const char *evsel_name = evsel__name(evsel);
2406     struct annotation *notes = symbol__annotation(sym);
2407     struct sym_hist *h = annotation__histogram(notes, evsel->core.idx);
2408     struct annotation_line *pos, *queue = NULL;
2409     u64 start = map__rip_2objdump(map, sym->start);
2410     int printed = 2, queue_len = 0, addr_fmt_width;
2411     int more = 0;
2412     bool context = opts->context;
2413     u64 len;
2414     int width = symbol_conf.show_total_period ? 12 : 8;
2415     int graph_dotted_len;
2416     char buf[512];
2417 
2418     filename = strdup(dso->long_name);
2419     if (!filename)
2420         return -ENOMEM;
2421 
2422     if (opts->full_path)
2423         d_filename = filename;
2424     else
2425         d_filename = basename(filename);
2426 
2427     len = symbol__size(sym);
2428 
2429     if (evsel__is_group_event(evsel)) {
2430         width *= evsel->core.nr_members;
2431         evsel__group_desc(evsel, buf, sizeof(buf));
2432         evsel_name = buf;
2433     }
2434 
2435     graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples, "
2436                   "percent: %s)\n",
2437                   width, width, symbol_conf.show_total_period ? "Period" :
2438                   symbol_conf.show_nr_samples ? "Samples" : "Percent",
2439                   d_filename, evsel_name, h->nr_samples,
2440                   percent_type_str(opts->percent_type));
2441 
2442     printf("%-*.*s----\n",
2443            graph_dotted_len, graph_dotted_len, graph_dotted_line);
2444 
2445     if (verbose > 0)
2446         symbol__annotate_hits(sym, evsel);
2447 
2448     addr_fmt_width = annotated_source__addr_fmt_width(&notes->src->source, start);
2449 
2450     list_for_each_entry(pos, &notes->src->source, node) {
2451         int err;
2452 
2453         if (context && queue == NULL) {
2454             queue = pos;
2455             queue_len = 0;
2456         }
2457 
2458         err = annotation_line__print(pos, sym, start, evsel, len,
2459                          opts->min_pcnt, printed, opts->max_lines,
2460                          queue, addr_fmt_width, opts->percent_type);
2461 
2462         switch (err) {
2463         case 0:
2464             ++printed;
2465             if (context) {
2466                 printed += queue_len;
2467                 queue = NULL;
2468                 queue_len = 0;
2469             }
2470             break;
2471         case 1:
2472             /* filtered by max_lines */
2473             ++more;
2474             break;
2475         case -1:
2476         default:
2477             /*
2478              * Filtered by min_pcnt or non IP lines when
2479              * context != 0
2480              */
2481             if (!context)
2482                 break;
2483             if (queue_len == context)
2484                 queue = list_entry(queue->node.next, typeof(*queue), node);
2485             else
2486                 ++queue_len;
2487             break;
2488         }
2489     }
2490 
2491     free(filename);
2492 
2493     return more;
2494 }
2495 
2496 static void FILE__set_percent_color(void *fp __maybe_unused,
2497                     double percent __maybe_unused,
2498                     bool current __maybe_unused)
2499 {
2500 }
2501 
2502 static int FILE__set_jumps_percent_color(void *fp __maybe_unused,
2503                      int nr __maybe_unused, bool current __maybe_unused)
2504 {
2505     return 0;
2506 }
2507 
2508 static int FILE__set_color(void *fp __maybe_unused, int color __maybe_unused)
2509 {
2510     return 0;
2511 }
2512 
2513 static void FILE__printf(void *fp, const char *fmt, ...)
2514 {
2515     va_list args;
2516 
2517     va_start(args, fmt);
2518     vfprintf(fp, fmt, args);
2519     va_end(args);
2520 }
2521 
2522 static void FILE__write_graph(void *fp, int graph)
2523 {
2524     const char *s;
2525     switch (graph) {
2526 
2527     case DARROW_CHAR: s = "↓"; break;
2528     case UARROW_CHAR: s = "↑"; break;
2529     case LARROW_CHAR: s = "←"; break;
2530     case RARROW_CHAR: s = "→"; break;
2531     default:        s = "?"; break;
2532     }
2533 
2534     fputs(s, fp);
2535 }
2536 
2537 static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp,
2538                      struct annotation_options *opts)
2539 {
2540     struct annotation *notes = symbol__annotation(sym);
2541     struct annotation_write_ops wops = {
2542         .first_line      = true,
2543         .obj             = fp,
2544         .set_color       = FILE__set_color,
2545         .set_percent_color   = FILE__set_percent_color,
2546         .set_jumps_percent_color = FILE__set_jumps_percent_color,
2547         .printf          = FILE__printf,
2548         .write_graph         = FILE__write_graph,
2549     };
2550     struct annotation_line *al;
2551 
2552     list_for_each_entry(al, &notes->src->source, node) {
2553         if (annotation_line__filter(al, notes))
2554             continue;
2555         annotation_line__write(al, notes, &wops, opts);
2556         fputc('\n', fp);
2557         wops.first_line = false;
2558     }
2559 
2560     return 0;
2561 }
2562 
2563 int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel,
2564                 struct annotation_options *opts)
2565 {
2566     const char *ev_name = evsel__name(evsel);
2567     char buf[1024];
2568     char *filename;
2569     int err = -1;
2570     FILE *fp;
2571 
2572     if (asprintf(&filename, "%s.annotation", ms->sym->name) < 0)
2573         return -1;
2574 
2575     fp = fopen(filename, "w");
2576     if (fp == NULL)
2577         goto out_free_filename;
2578 
2579     if (evsel__is_group_event(evsel)) {
2580         evsel__group_desc(evsel, buf, sizeof(buf));
2581         ev_name = buf;
2582     }
2583 
2584     fprintf(fp, "%s() %s\nEvent: %s\n\n",
2585         ms->sym->name, ms->map->dso->long_name, ev_name);
2586     symbol__annotate_fprintf2(ms->sym, fp, opts);
2587 
2588     fclose(fp);
2589     err = 0;
2590 out_free_filename:
2591     free(filename);
2592     return err;
2593 }
2594 
2595 void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
2596 {
2597     struct annotation *notes = symbol__annotation(sym);
2598     struct sym_hist *h = annotation__histogram(notes, evidx);
2599 
2600     memset(h, 0, notes->src->sizeof_sym_hist);
2601 }
2602 
2603 void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
2604 {
2605     struct annotation *notes = symbol__annotation(sym);
2606     struct sym_hist *h = annotation__histogram(notes, evidx);
2607     int len = symbol__size(sym), offset;
2608 
2609     h->nr_samples = 0;
2610     for (offset = 0; offset < len; ++offset) {
2611         h->addr[offset].nr_samples = h->addr[offset].nr_samples * 7 / 8;
2612         h->nr_samples += h->addr[offset].nr_samples;
2613     }
2614 }
2615 
2616 void annotated_source__purge(struct annotated_source *as)
2617 {
2618     struct annotation_line *al, *n;
2619 
2620     list_for_each_entry_safe(al, n, &as->source, node) {
2621         list_del_init(&al->node);
2622         disasm_line__free(disasm_line(al));
2623     }
2624 }
2625 
2626 static size_t disasm_line__fprintf(struct disasm_line *dl, FILE *fp)
2627 {
2628     size_t printed;
2629 
2630     if (dl->al.offset == -1)
2631         return fprintf(fp, "%s\n", dl->al.line);
2632 
2633     printed = fprintf(fp, "%#" PRIx64 " %s", dl->al.offset, dl->ins.name);
2634 
2635     if (dl->ops.raw[0] != '\0') {
2636         printed += fprintf(fp, "%.*s %s\n", 6 - (int)printed, " ",
2637                    dl->ops.raw);
2638     }
2639 
2640     return printed + fprintf(fp, "\n");
2641 }
2642 
2643 size_t disasm__fprintf(struct list_head *head, FILE *fp)
2644 {
2645     struct disasm_line *pos;
2646     size_t printed = 0;
2647 
2648     list_for_each_entry(pos, head, al.node)
2649         printed += disasm_line__fprintf(pos, fp);
2650 
2651     return printed;
2652 }
2653 
2654 bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym)
2655 {
2656     if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) ||
2657         !disasm_line__has_local_offset(dl) || dl->ops.target.offset < 0 ||
2658         dl->ops.target.offset >= (s64)symbol__size(sym))
2659         return false;
2660 
2661     return true;
2662 }
2663 
2664 void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym)
2665 {
2666     u64 offset, size = symbol__size(sym);
2667 
2668     /* PLT symbols contain external offsets */
2669     if (strstr(sym->name, "@plt"))
2670         return;
2671 
2672     for (offset = 0; offset < size; ++offset) {
2673         struct annotation_line *al = notes->offsets[offset];
2674         struct disasm_line *dl;
2675 
2676         dl = disasm_line(al);
2677 
2678         if (!disasm_line__is_valid_local_jump(dl, sym))
2679             continue;
2680 
2681         al = notes->offsets[dl->ops.target.offset];
2682 
2683         /*
2684          * FIXME: Oops, no jump target? Buggy disassembler? Or do we
2685          * have to adjust to the previous offset?
2686          */
2687         if (al == NULL)
2688             continue;
2689 
2690         if (++al->jump_sources > notes->max_jump_sources)
2691             notes->max_jump_sources = al->jump_sources;
2692     }
2693 }
2694 
2695 void annotation__set_offsets(struct annotation *notes, s64 size)
2696 {
2697     struct annotation_line *al;
2698 
2699     notes->max_line_len = 0;
2700     notes->nr_entries = 0;
2701     notes->nr_asm_entries = 0;
2702 
2703     list_for_each_entry(al, &notes->src->source, node) {
2704         size_t line_len = strlen(al->line);
2705 
2706         if (notes->max_line_len < line_len)
2707             notes->max_line_len = line_len;
2708         al->idx = notes->nr_entries++;
2709         if (al->offset != -1) {
2710             al->idx_asm = notes->nr_asm_entries++;
2711             /*
2712              * FIXME: short term bandaid to cope with assembly
2713              * routines that comes with labels in the same column
2714              * as the address in objdump, sigh.
2715              *
2716              * E.g. copy_user_generic_unrolled
2717              */
2718             if (al->offset < size)
2719                 notes->offsets[al->offset] = al;
2720         } else
2721             al->idx_asm = -1;
2722     }
2723 }
2724 
2725 static inline int width_jumps(int n)
2726 {
2727     if (n >= 100)
2728         return 5;
2729     if (n / 10)
2730         return 2;
2731     return 1;
2732 }
2733 
2734 static int annotation__max_ins_name(struct annotation *notes)
2735 {
2736     int max_name = 0, len;
2737     struct annotation_line *al;
2738 
2739         list_for_each_entry(al, &notes->src->source, node) {
2740         if (al->offset == -1)
2741             continue;
2742 
2743         len = strlen(disasm_line(al)->ins.name);
2744         if (max_name < len)
2745             max_name = len;
2746     }
2747 
2748     return max_name;
2749 }
2750 
2751 void annotation__init_column_widths(struct annotation *notes, struct symbol *sym)
2752 {
2753     notes->widths.addr = notes->widths.target =
2754         notes->widths.min_addr = hex_width(symbol__size(sym));
2755     notes->widths.max_addr = hex_width(sym->end);
2756     notes->widths.jumps = width_jumps(notes->max_jump_sources);
2757     notes->widths.max_ins_name = annotation__max_ins_name(notes);
2758 }
2759 
2760 void annotation__update_column_widths(struct annotation *notes)
2761 {
2762     if (notes->options->use_offset)
2763         notes->widths.target = notes->widths.min_addr;
2764     else
2765         notes->widths.target = notes->widths.max_addr;
2766 
2767     notes->widths.addr = notes->widths.target;
2768 
2769     if (notes->options->show_nr_jumps)
2770         notes->widths.addr += notes->widths.jumps + 1;
2771 }
2772 
2773 static void annotation__calc_lines(struct annotation *notes, struct map *map,
2774                    struct rb_root *root,
2775                    struct annotation_options *opts)
2776 {
2777     struct annotation_line *al;
2778     struct rb_root tmp_root = RB_ROOT;
2779 
2780     list_for_each_entry(al, &notes->src->source, node) {
2781         double percent_max = 0.0;
2782         int i;
2783 
2784         for (i = 0; i < al->data_nr; i++) {
2785             double percent;
2786 
2787             percent = annotation_data__percent(&al->data[i],
2788                                opts->percent_type);
2789 
2790             if (percent > percent_max)
2791                 percent_max = percent;
2792         }
2793 
2794         if (percent_max <= 0.5)
2795             continue;
2796 
2797         al->path = get_srcline(map->dso, notes->start + al->offset, NULL,
2798                        false, true, notes->start + al->offset);
2799         insert_source_line(&tmp_root, al, opts);
2800     }
2801 
2802     resort_source_line(root, &tmp_root);
2803 }
2804 
2805 static void symbol__calc_lines(struct map_symbol *ms, struct rb_root *root,
2806                    struct annotation_options *opts)
2807 {
2808     struct annotation *notes = symbol__annotation(ms->sym);
2809 
2810     annotation__calc_lines(notes, ms->map, root, opts);
2811 }
2812 
2813 int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel,
2814               struct annotation_options *opts)
2815 {
2816     struct dso *dso = ms->map->dso;
2817     struct symbol *sym = ms->sym;
2818     struct rb_root source_line = RB_ROOT;
2819     struct hists *hists = evsel__hists(evsel);
2820     char buf[1024];
2821     int err;
2822 
2823     err = symbol__annotate2(ms, evsel, opts, NULL);
2824     if (err) {
2825         char msg[BUFSIZ];
2826 
2827         dso->annotate_warned = true;
2828         symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
2829         ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
2830         return -1;
2831     }
2832 
2833     if (opts->print_lines) {
2834         srcline_full_filename = opts->full_path;
2835         symbol__calc_lines(ms, &source_line, opts);
2836         print_summary(&source_line, dso->long_name);
2837     }
2838 
2839     hists__scnprintf_title(hists, buf, sizeof(buf));
2840     fprintf(stdout, "%s, [percent: %s]\n%s() %s\n",
2841         buf, percent_type_str(opts->percent_type), sym->name, dso->long_name);
2842     symbol__annotate_fprintf2(sym, stdout, opts);
2843 
2844     annotated_source__purge(symbol__annotation(sym)->src);
2845 
2846     return 0;
2847 }
2848 
2849 int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel,
2850              struct annotation_options *opts)
2851 {
2852     struct dso *dso = ms->map->dso;
2853     struct symbol *sym = ms->sym;
2854     struct rb_root source_line = RB_ROOT;
2855     int err;
2856 
2857     err = symbol__annotate(ms, evsel, opts, NULL);
2858     if (err) {
2859         char msg[BUFSIZ];
2860 
2861         dso->annotate_warned = true;
2862         symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
2863         ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
2864         return -1;
2865     }
2866 
2867     symbol__calc_percent(sym, evsel);
2868 
2869     if (opts->print_lines) {
2870         srcline_full_filename = opts->full_path;
2871         symbol__calc_lines(ms, &source_line, opts);
2872         print_summary(&source_line, dso->long_name);
2873     }
2874 
2875     symbol__annotate_printf(ms, evsel, opts);
2876 
2877     annotated_source__purge(symbol__annotation(sym)->src);
2878 
2879     return 0;
2880 }
2881 
2882 bool ui__has_annotation(void)
2883 {
2884     return use_browser == 1 && perf_hpp_list.sym;
2885 }
2886 
2887 
2888 static double annotation_line__max_percent(struct annotation_line *al,
2889                        struct annotation *notes,
2890                        unsigned int percent_type)
2891 {
2892     double percent_max = 0.0;
2893     int i;
2894 
2895     for (i = 0; i < notes->nr_events; i++) {
2896         double percent;
2897 
2898         percent = annotation_data__percent(&al->data[i],
2899                            percent_type);
2900 
2901         if (percent > percent_max)
2902             percent_max = percent;
2903     }
2904 
2905     return percent_max;
2906 }
2907 
2908 static void disasm_line__write(struct disasm_line *dl, struct annotation *notes,
2909                    void *obj, char *bf, size_t size,
2910                    void (*obj__printf)(void *obj, const char *fmt, ...),
2911                    void (*obj__write_graph)(void *obj, int graph))
2912 {
2913     if (dl->ins.ops && dl->ins.ops->scnprintf) {
2914         if (ins__is_jump(&dl->ins)) {
2915             bool fwd;
2916 
2917             if (dl->ops.target.outside)
2918                 goto call_like;
2919             fwd = dl->ops.target.offset > dl->al.offset;
2920             obj__write_graph(obj, fwd ? DARROW_CHAR : UARROW_CHAR);
2921             obj__printf(obj, " ");
2922         } else if (ins__is_call(&dl->ins)) {
2923 call_like:
2924             obj__write_graph(obj, RARROW_CHAR);
2925             obj__printf(obj, " ");
2926         } else if (ins__is_ret(&dl->ins)) {
2927             obj__write_graph(obj, LARROW_CHAR);
2928             obj__printf(obj, " ");
2929         } else {
2930             obj__printf(obj, "  ");
2931         }
2932     } else {
2933         obj__printf(obj, "  ");
2934     }
2935 
2936     disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset, notes->widths.max_ins_name);
2937 }
2938 
2939 static void ipc_coverage_string(char *bf, int size, struct annotation *notes)
2940 {
2941     double ipc = 0.0, coverage = 0.0;
2942 
2943     if (notes->hit_cycles)
2944         ipc = notes->hit_insn / ((double)notes->hit_cycles);
2945 
2946     if (notes->total_insn) {
2947         coverage = notes->cover_insn * 100.0 /
2948             ((double)notes->total_insn);
2949     }
2950 
2951     scnprintf(bf, size, "(Average IPC: %.2f, IPC Coverage: %.1f%%)",
2952           ipc, coverage);
2953 }
2954 
2955 static void __annotation_line__write(struct annotation_line *al, struct annotation *notes,
2956                      bool first_line, bool current_entry, bool change_color, int width,
2957                      void *obj, unsigned int percent_type,
2958                      int  (*obj__set_color)(void *obj, int color),
2959                      void (*obj__set_percent_color)(void *obj, double percent, bool current),
2960                      int  (*obj__set_jumps_percent_color)(void *obj, int nr, bool current),
2961                      void (*obj__printf)(void *obj, const char *fmt, ...),
2962                      void (*obj__write_graph)(void *obj, int graph))
2963 
2964 {
2965     double percent_max = annotation_line__max_percent(al, notes, percent_type);
2966     int pcnt_width = annotation__pcnt_width(notes),
2967         cycles_width = annotation__cycles_width(notes);
2968     bool show_title = false;
2969     char bf[256];
2970     int printed;
2971 
2972     if (first_line && (al->offset == -1 || percent_max == 0.0)) {
2973         if (notes->have_cycles) {
2974             if (al->ipc == 0.0 && al->cycles == 0)
2975                 show_title = true;
2976         } else
2977             show_title = true;
2978     }
2979 
2980     if (al->offset != -1 && percent_max != 0.0) {
2981         int i;
2982 
2983         for (i = 0; i < notes->nr_events; i++) {
2984             double percent;
2985 
2986             percent = annotation_data__percent(&al->data[i], percent_type);
2987 
2988             obj__set_percent_color(obj, percent, current_entry);
2989             if (symbol_conf.show_total_period) {
2990                 obj__printf(obj, "%11" PRIu64 " ", al->data[i].he.period);
2991             } else if (symbol_conf.show_nr_samples) {
2992                 obj__printf(obj, "%6" PRIu64 " ",
2993                            al->data[i].he.nr_samples);
2994             } else {
2995                 obj__printf(obj, "%6.2f ", percent);
2996             }
2997         }
2998     } else {
2999         obj__set_percent_color(obj, 0, current_entry);
3000 
3001         if (!show_title)
3002             obj__printf(obj, "%-*s", pcnt_width, " ");
3003         else {
3004             obj__printf(obj, "%-*s", pcnt_width,
3005                        symbol_conf.show_total_period ? "Period" :
3006                        symbol_conf.show_nr_samples ? "Samples" : "Percent");
3007         }
3008     }
3009 
3010     if (notes->have_cycles) {
3011         if (al->ipc)
3012             obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc);
3013         else if (!show_title)
3014             obj__printf(obj, "%*s", ANNOTATION__IPC_WIDTH, " ");
3015         else
3016             obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
3017 
3018         if (!notes->options->show_minmax_cycle) {
3019             if (al->cycles)
3020                 obj__printf(obj, "%*" PRIu64 " ",
3021                        ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
3022             else if (!show_title)
3023                 obj__printf(obj, "%*s",
3024                         ANNOTATION__CYCLES_WIDTH, " ");
3025             else
3026                 obj__printf(obj, "%*s ",
3027                         ANNOTATION__CYCLES_WIDTH - 1,
3028                         "Cycle");
3029         } else {
3030             if (al->cycles) {
3031                 char str[32];
3032 
3033                 scnprintf(str, sizeof(str),
3034                     "%" PRIu64 "(%" PRIu64 "/%" PRIu64 ")",
3035                     al->cycles, al->cycles_min,
3036                     al->cycles_max);
3037 
3038                 obj__printf(obj, "%*s ",
3039                         ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
3040                         str);
3041             } else if (!show_title)
3042                 obj__printf(obj, "%*s",
3043                         ANNOTATION__MINMAX_CYCLES_WIDTH,
3044                         " ");
3045             else
3046                 obj__printf(obj, "%*s ",
3047                         ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
3048                         "Cycle(min/max)");
3049         }
3050 
3051         if (show_title && !*al->line) {
3052             ipc_coverage_string(bf, sizeof(bf), notes);
3053             obj__printf(obj, "%*s", ANNOTATION__AVG_IPC_WIDTH, bf);
3054         }
3055     }
3056 
3057     obj__printf(obj, " ");
3058 
3059     if (!*al->line)
3060         obj__printf(obj, "%-*s", width - pcnt_width - cycles_width, " ");
3061     else if (al->offset == -1) {
3062         if (al->line_nr && notes->options->show_linenr)
3063             printed = scnprintf(bf, sizeof(bf), "%-*d ", notes->widths.addr + 1, al->line_nr);
3064         else
3065             printed = scnprintf(bf, sizeof(bf), "%-*s  ", notes->widths.addr, " ");
3066         obj__printf(obj, bf);
3067         obj__printf(obj, "%-*s", width - printed - pcnt_width - cycles_width + 1, al->line);
3068     } else {
3069         u64 addr = al->offset;
3070         int color = -1;
3071 
3072         if (!notes->options->use_offset)
3073             addr += notes->start;
3074 
3075         if (!notes->options->use_offset) {
3076             printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
3077         } else {
3078             if (al->jump_sources &&
3079                 notes->options->offset_level >= ANNOTATION__OFFSET_JUMP_TARGETS) {
3080                 if (notes->options->show_nr_jumps) {
3081                     int prev;
3082                     printed = scnprintf(bf, sizeof(bf), "%*d ",
3083                                 notes->widths.jumps,
3084                                 al->jump_sources);
3085                     prev = obj__set_jumps_percent_color(obj, al->jump_sources,
3086                                         current_entry);
3087                     obj__printf(obj, bf);
3088                     obj__set_color(obj, prev);
3089                 }
3090 print_addr:
3091                 printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
3092                             notes->widths.target, addr);
3093             } else if (ins__is_call(&disasm_line(al)->ins) &&
3094                    notes->options->offset_level >= ANNOTATION__OFFSET_CALL) {
3095                 goto print_addr;
3096             } else if (notes->options->offset_level == ANNOTATION__MAX_OFFSET_LEVEL) {
3097                 goto print_addr;
3098             } else {
3099                 printed = scnprintf(bf, sizeof(bf), "%-*s  ",
3100                             notes->widths.addr, " ");
3101             }
3102         }
3103 
3104         if (change_color)
3105             color = obj__set_color(obj, HE_COLORSET_ADDR);
3106         obj__printf(obj, bf);
3107         if (change_color)
3108             obj__set_color(obj, color);
3109 
3110         disasm_line__write(disasm_line(al), notes, obj, bf, sizeof(bf), obj__printf, obj__write_graph);
3111 
3112         obj__printf(obj, "%-*s", width - pcnt_width - cycles_width - 3 - printed, bf);
3113     }
3114 
3115 }
3116 
3117 void annotation_line__write(struct annotation_line *al, struct annotation *notes,
3118                 struct annotation_write_ops *wops,
3119                 struct annotation_options *opts)
3120 {
3121     __annotation_line__write(al, notes, wops->first_line, wops->current_entry,
3122                  wops->change_color, wops->width, wops->obj,
3123                  opts->percent_type,
3124                  wops->set_color, wops->set_percent_color,
3125                  wops->set_jumps_percent_color, wops->printf,
3126                  wops->write_graph);
3127 }
3128 
3129 int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
3130               struct annotation_options *options, struct arch **parch)
3131 {
3132     struct symbol *sym = ms->sym;
3133     struct annotation *notes = symbol__annotation(sym);
3134     size_t size = symbol__size(sym);
3135     int nr_pcnt = 1, err;
3136 
3137     notes->offsets = zalloc(size * sizeof(struct annotation_line *));
3138     if (notes->offsets == NULL)
3139         return ENOMEM;
3140 
3141     if (evsel__is_group_event(evsel))
3142         nr_pcnt = evsel->core.nr_members;
3143 
3144     err = symbol__annotate(ms, evsel, options, parch);
3145     if (err)
3146         goto out_free_offsets;
3147 
3148     notes->options = options;
3149 
3150     symbol__calc_percent(sym, evsel);
3151 
3152     annotation__set_offsets(notes, size);
3153     annotation__mark_jump_targets(notes, sym);
3154     annotation__compute_ipc(notes, size);
3155     annotation__init_column_widths(notes, sym);
3156     notes->nr_events = nr_pcnt;
3157 
3158     annotation__update_column_widths(notes);
3159     sym->annotate2 = 1;
3160 
3161     return 0;
3162 
3163 out_free_offsets:
3164     zfree(&notes->offsets);
3165     return err;
3166 }
3167 
3168 static int annotation__config(const char *var, const char *value, void *data)
3169 {
3170     struct annotation_options *opt = data;
3171 
3172     if (!strstarts(var, "annotate."))
3173         return 0;
3174 
3175     if (!strcmp(var, "annotate.offset_level")) {
3176         perf_config_u8(&opt->offset_level, "offset_level", value);
3177 
3178         if (opt->offset_level > ANNOTATION__MAX_OFFSET_LEVEL)
3179             opt->offset_level = ANNOTATION__MAX_OFFSET_LEVEL;
3180         else if (opt->offset_level < ANNOTATION__MIN_OFFSET_LEVEL)
3181             opt->offset_level = ANNOTATION__MIN_OFFSET_LEVEL;
3182     } else if (!strcmp(var, "annotate.hide_src_code")) {
3183         opt->hide_src_code = perf_config_bool("hide_src_code", value);
3184     } else if (!strcmp(var, "annotate.jump_arrows")) {
3185         opt->jump_arrows = perf_config_bool("jump_arrows", value);
3186     } else if (!strcmp(var, "annotate.show_linenr")) {
3187         opt->show_linenr = perf_config_bool("show_linenr", value);
3188     } else if (!strcmp(var, "annotate.show_nr_jumps")) {
3189         opt->show_nr_jumps = perf_config_bool("show_nr_jumps", value);
3190     } else if (!strcmp(var, "annotate.show_nr_samples")) {
3191         symbol_conf.show_nr_samples = perf_config_bool("show_nr_samples",
3192                                 value);
3193     } else if (!strcmp(var, "annotate.show_total_period")) {
3194         symbol_conf.show_total_period = perf_config_bool("show_total_period",
3195                                 value);
3196     } else if (!strcmp(var, "annotate.use_offset")) {
3197         opt->use_offset = perf_config_bool("use_offset", value);
3198     } else if (!strcmp(var, "annotate.disassembler_style")) {
3199         opt->disassembler_style = value;
3200     } else if (!strcmp(var, "annotate.demangle")) {
3201         symbol_conf.demangle = perf_config_bool("demangle", value);
3202     } else if (!strcmp(var, "annotate.demangle_kernel")) {
3203         symbol_conf.demangle_kernel = perf_config_bool("demangle_kernel", value);
3204     } else {
3205         pr_debug("%s variable unknown, ignoring...", var);
3206     }
3207 
3208     return 0;
3209 }
3210 
3211 void annotation_config__init(struct annotation_options *opt)
3212 {
3213     perf_config(annotation__config, opt);
3214 }
3215 
3216 static unsigned int parse_percent_type(char *str1, char *str2)
3217 {
3218     unsigned int type = (unsigned int) -1;
3219 
3220     if (!strcmp("period", str1)) {
3221         if (!strcmp("local", str2))
3222             type = PERCENT_PERIOD_LOCAL;
3223         else if (!strcmp("global", str2))
3224             type = PERCENT_PERIOD_GLOBAL;
3225     }
3226 
3227     if (!strcmp("hits", str1)) {
3228         if (!strcmp("local", str2))
3229             type = PERCENT_HITS_LOCAL;
3230         else if (!strcmp("global", str2))
3231             type = PERCENT_HITS_GLOBAL;
3232     }
3233 
3234     return type;
3235 }
3236 
3237 int annotate_parse_percent_type(const struct option *opt, const char *_str,
3238                 int unset __maybe_unused)
3239 {
3240     struct annotation_options *opts = opt->value;
3241     unsigned int type;
3242     char *str1, *str2;
3243     int err = -1;
3244 
3245     str1 = strdup(_str);
3246     if (!str1)
3247         return -ENOMEM;
3248 
3249     str2 = strchr(str1, '-');
3250     if (!str2)
3251         goto out;
3252 
3253     *str2++ = 0;
3254 
3255     type = parse_percent_type(str1, str2);
3256     if (type == (unsigned int) -1)
3257         type = parse_percent_type(str2, str1);
3258     if (type != (unsigned int) -1) {
3259         opts->percent_type = type;
3260         err = 0;
3261     }
3262 
3263 out:
3264     free(str1);
3265     return err;
3266 }
3267 
3268 int annotate_check_args(struct annotation_options *args)
3269 {
3270     if (args->prefix_strip && !args->prefix) {
3271         pr_err("--prefix-strip requires --prefix\n");
3272         return -1;
3273     }
3274     return 0;
3275 }