linux/tools/perf/util/annotate.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
   4 *
   5 * Parts came from builtin-annotate.c, see those files for further
   6 * copyright notes.
   7 */
   8
   9#include <errno.h>
  10#include <inttypes.h>
  11#include <libgen.h>
  12#include <stdlib.h>
  13#include "util.h" // hex_width()
  14#include "ui/ui.h"
  15#include "sort.h"
  16#include "build-id.h"
  17#include "color.h"
  18#include "config.h"
  19#include "dso.h"
  20#include "env.h"
  21#include "map.h"
  22#include "maps.h"
  23#include "symbol.h"
  24#include "srcline.h"
  25#include "units.h"
  26#include "debug.h"
  27#include "annotate.h"
  28#include "evsel.h"
  29#include "evlist.h"
  30#include "bpf-event.h"
  31#include "bpf-utils.h"
  32#include "block-range.h"
  33#include "string2.h"
  34#include "util/event.h"
  35#include "arch/common.h"
  36#include "namespaces.h"
  37#include <regex.h>
  38#include <pthread.h>
  39#include <linux/bitops.h>
  40#include <linux/kernel.h>
  41#include <linux/string.h>
  42#include <subcmd/parse-options.h>
  43#include <subcmd/run-command.h>
  44
  45/* FIXME: For the HE_COLORSET */
  46#include "ui/browser.h"
  47
  48/*
  49 * FIXME: Using the same values as slang.h,
  50 * but that header may not be available everywhere
  51 */
  52#define LARROW_CHAR     ((unsigned char)',')
  53#define RARROW_CHAR     ((unsigned char)'+')
  54#define DARROW_CHAR     ((unsigned char)'.')
  55#define UARROW_CHAR     ((unsigned char)'-')
  56
  57#include <linux/ctype.h>
  58
  59struct annotation_options annotation__default_options = {
  60        .use_offset     = true,
  61        .jump_arrows    = true,
  62        .annotate_src   = true,
  63        .offset_level   = ANNOTATION__OFFSET_JUMP_TARGETS,
  64        .percent_type   = PERCENT_PERIOD_LOCAL,
  65};
  66
  67static regex_t   file_lineno;
  68
  69static struct ins_ops *ins__find(struct arch *arch, const char *name);
  70static void ins__sort(struct arch *arch);
  71static int disasm_line__parse(char *line, const char **namep, char **rawp);
  72
  73struct arch {
  74        const char      *name;
  75        struct ins      *instructions;
  76        size_t          nr_instructions;
  77        size_t          nr_instructions_allocated;
  78        struct ins_ops  *(*associate_instruction_ops)(struct arch *arch, const char *name);
  79        bool            sorted_instructions;
  80        bool            initialized;
  81        void            *priv;
  82        unsigned int    model;
  83        unsigned int    family;
  84        int             (*init)(struct arch *arch, char *cpuid);
  85        bool            (*ins_is_fused)(struct arch *arch, const char *ins1,
  86                                        const char *ins2);
  87        struct          {
  88                char comment_char;
  89                char skip_functions_char;
  90        } objdump;
  91};
  92
  93static struct ins_ops call_ops;
  94static struct ins_ops dec_ops;
  95static struct ins_ops jump_ops;
  96static struct ins_ops mov_ops;
  97static struct ins_ops nop_ops;
  98static struct ins_ops lock_ops;
  99static struct ins_ops ret_ops;
 100
 101static int arch__grow_instructions(struct arch *arch)
 102{
 103        struct ins *new_instructions;
 104        size_t new_nr_allocated;
 105
 106        if (arch->nr_instructions_allocated == 0 && arch->instructions)
 107                goto grow_from_non_allocated_table;
 108
 109        new_nr_allocated = arch->nr_instructions_allocated + 128;
 110        new_instructions = realloc(arch->instructions, new_nr_allocated * sizeof(struct ins));
 111        if (new_instructions == NULL)
 112                return -1;
 113
 114out_update_instructions:
 115        arch->instructions = new_instructions;
 116        arch->nr_instructions_allocated = new_nr_allocated;
 117        return 0;
 118
 119grow_from_non_allocated_table:
 120        new_nr_allocated = arch->nr_instructions + 128;
 121        new_instructions = calloc(new_nr_allocated, sizeof(struct ins));
 122        if (new_instructions == NULL)
 123                return -1;
 124
 125        memcpy(new_instructions, arch->instructions, arch->nr_instructions);
 126        goto out_update_instructions;
 127}
 128
 129static int arch__associate_ins_ops(struct arch* arch, const char *name, struct ins_ops *ops)
 130{
 131        struct ins *ins;
 132
 133        if (arch->nr_instructions == arch->nr_instructions_allocated &&
 134            arch__grow_instructions(arch))
 135                return -1;
 136
 137        ins = &arch->instructions[arch->nr_instructions];
 138        ins->name = strdup(name);
 139        if (!ins->name)
 140                return -1;
 141
 142        ins->ops  = ops;
 143        arch->nr_instructions++;
 144
 145        ins__sort(arch);
 146        return 0;
 147}
 148
 149#include "arch/arc/annotate/instructions.c"
 150#include "arch/arm/annotate/instructions.c"
 151#include "arch/arm64/annotate/instructions.c"
 152#include "arch/csky/annotate/instructions.c"
 153#include "arch/mips/annotate/instructions.c"
 154#include "arch/x86/annotate/instructions.c"
 155#include "arch/powerpc/annotate/instructions.c"
 156#include "arch/riscv64/annotate/instructions.c"
 157#include "arch/s390/annotate/instructions.c"
 158#include "arch/sparc/annotate/instructions.c"
 159
 160static struct arch architectures[] = {
 161        {
 162                .name = "arc",
 163                .init = arc__annotate_init,
 164        },
 165        {
 166                .name = "arm",
 167                .init = arm__annotate_init,
 168        },
 169        {
 170                .name = "arm64",
 171                .init = arm64__annotate_init,
 172        },
 173        {
 174                .name = "csky",
 175                .init = csky__annotate_init,
 176        },
 177        {
 178                .name = "mips",
 179                .init = mips__annotate_init,
 180                .objdump = {
 181                        .comment_char = '#',
 182                },
 183        },
 184        {
 185                .name = "x86",
 186                .init = x86__annotate_init,
 187                .instructions = x86__instructions,
 188                .nr_instructions = ARRAY_SIZE(x86__instructions),
 189                .objdump =  {
 190                        .comment_char = '#',
 191                },
 192        },
 193        {
 194                .name = "powerpc",
 195                .init = powerpc__annotate_init,
 196        },
 197        {
 198                .name = "riscv64",
 199                .init = riscv64__annotate_init,
 200        },
 201        {
 202                .name = "s390",
 203                .init = s390__annotate_init,
 204                .objdump =  {
 205                        .comment_char = '#',
 206                },
 207        },
 208        {
 209                .name = "sparc",
 210                .init = sparc__annotate_init,
 211                .objdump = {
 212                        .comment_char = '#',
 213                },
 214        },
 215};
 216
 217static void ins__delete(struct ins_operands *ops)
 218{
 219        if (ops == NULL)
 220                return;
 221        zfree(&ops->source.raw);
 222        zfree(&ops->source.name);
 223        zfree(&ops->target.raw);
 224        zfree(&ops->target.name);
 225}
 226
 227static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
 228                              struct ins_operands *ops, int max_ins_name)
 229{
 230        return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->raw);
 231}
 232
 233int ins__scnprintf(struct ins *ins, char *bf, size_t size,
 234                   struct ins_operands *ops, int max_ins_name)
 235{
 236        if (ins->ops->scnprintf)
 237                return ins->ops->scnprintf(ins, bf, size, ops, max_ins_name);
 238
 239        return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
 240}
 241
 242bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2)
 243{
 244        if (!arch || !arch->ins_is_fused)
 245                return false;
 246
 247        return arch->ins_is_fused(arch, ins1, ins2);
 248}
 249
 250static int call__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
 251{
 252        char *endptr, *tok, *name;
 253        struct map *map = ms->map;
 254        struct addr_map_symbol target = {
 255                .ms = { .map = map, },
 256        };
 257
 258        ops->target.addr = strtoull(ops->raw, &endptr, 16);
 259
 260        name = strchr(endptr, '<');
 261        if (name == NULL)
 262                goto indirect_call;
 263
 264        name++;
 265
 266        if (arch->objdump.skip_functions_char &&
 267            strchr(name, arch->objdump.skip_functions_char))
 268                return -1;
 269
 270        tok = strchr(name, '>');
 271        if (tok == NULL)
 272                return -1;
 273
 274        *tok = '\0';
 275        ops->target.name = strdup(name);
 276        *tok = '>';
 277
 278        if (ops->target.name == NULL)
 279                return -1;
 280find_target:
 281        target.addr = map__objdump_2mem(map, ops->target.addr);
 282
 283        if (maps__find_ams(ms->maps, &target) == 0 &&
 284            map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr)
 285                ops->target.sym = target.ms.sym;
 286
 287        return 0;
 288
 289indirect_call:
 290        tok = strchr(endptr, '*');
 291        if (tok != NULL) {
 292                endptr++;
 293
 294                /* Indirect call can use a non-rip register and offset: callq  *0x8(%rbx).
 295                 * Do not parse such instruction.  */
 296                if (strstr(endptr, "(%r") == NULL)
 297                        ops->target.addr = strtoull(endptr, NULL, 16);
 298        }
 299        goto find_target;
 300}
 301
 302static int call__scnprintf(struct ins *ins, char *bf, size_t size,
 303                           struct ins_operands *ops, int max_ins_name)
 304{
 305        if (ops->target.sym)
 306                return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name);
 307
 308        if (ops->target.addr == 0)
 309                return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
 310
 311        if (ops->target.name)
 312                return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.name);
 313
 314        return scnprintf(bf, size, "%-*s *%" PRIx64, max_ins_name, ins->name, ops->target.addr);
 315}
 316
 317static struct ins_ops call_ops = {
 318        .parse     = call__parse,
 319        .scnprintf = call__scnprintf,
 320};
 321
 322bool ins__is_call(const struct ins *ins)
 323{
 324        return ins->ops == &call_ops || ins->ops == &s390_call_ops;
 325}
 326
 327/*
 328 * Prevents from matching commas in the comment section, e.g.:
 329 * ffff200008446e70:       b.cs    ffff2000084470f4 <generic_exec_single+0x314>  // b.hs, b.nlast
 330 *
 331 * and skip comma as part of function arguments, e.g.:
 332 * 1d8b4ac <linemap_lookup(line_maps const*, unsigned int)+0xcc>
 333 */
 334static inline const char *validate_comma(const char *c, struct ins_operands *ops)
 335{
 336        if (ops->raw_comment && c > ops->raw_comment)
 337                return NULL;
 338
 339        if (ops->raw_func_start && c > ops->raw_func_start)
 340                return NULL;
 341
 342        return c;
 343}
 344
 345static int jump__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
 346{
 347        struct map *map = ms->map;
 348        struct symbol *sym = ms->sym;
 349        struct addr_map_symbol target = {
 350                .ms = { .map = map, },
 351        };
 352        const char *c = strchr(ops->raw, ',');
 353        u64 start, end;
 354
 355        ops->raw_comment = strchr(ops->raw, arch->objdump.comment_char);
 356        ops->raw_func_start = strchr(ops->raw, '<');
 357
 358        c = validate_comma(c, ops);
 359
 360        /*
 361         * Examples of lines to parse for the _cpp_lex_token@@Base
 362         * function:
 363         *
 364         * 1159e6c: jne    115aa32 <_cpp_lex_token@@Base+0xf92>
 365         * 1159e8b: jne    c469be <cpp_named_operator2name@@Base+0xa72>
 366         *
 367         * The first is a jump to an offset inside the same function,
 368         * the second is to another function, i.e. that 0xa72 is an
 369         * offset in the cpp_named_operator2name@@base function.
 370         */
 371        /*
 372         * skip over possible up to 2 operands to get to address, e.g.:
 373         * tbnz  w0, #26, ffff0000083cd190 <security_file_permission+0xd0>
 374         */
 375        if (c++ != NULL) {
 376                ops->target.addr = strtoull(c, NULL, 16);
 377                if (!ops->target.addr) {
 378                        c = strchr(c, ',');
 379                        c = validate_comma(c, ops);
 380                        if (c++ != NULL)
 381                                ops->target.addr = strtoull(c, NULL, 16);
 382                }
 383        } else {
 384                ops->target.addr = strtoull(ops->raw, NULL, 16);
 385        }
 386
 387        target.addr = map__objdump_2mem(map, ops->target.addr);
 388        start = map->unmap_ip(map, sym->start),
 389        end = map->unmap_ip(map, sym->end);
 390
 391        ops->target.outside = target.addr < start || target.addr > end;
 392
 393        /*
 394         * FIXME: things like this in _cpp_lex_token (gcc's cc1 program):
 395
 396                cpp_named_operator2name@@Base+0xa72
 397
 398         * Point to a place that is after the cpp_named_operator2name
 399         * boundaries, i.e.  in the ELF symbol table for cc1
 400         * cpp_named_operator2name is marked as being 32-bytes long, but it in
 401         * fact is much larger than that, so we seem to need a symbols__find()
 402         * routine that looks for >= current->start and  < next_symbol->start,
 403         * possibly just for C++ objects?
 404         *
 405         * For now lets just make some progress by marking jumps to outside the
 406         * current function as call like.
 407         *
 408         * Actual navigation will come next, with further understanding of how
 409         * the symbol searching and disassembly should be done.
 410         */
 411        if (maps__find_ams(ms->maps, &target) == 0 &&
 412            map__rip_2objdump(target.ms.map, map->map_ip(target.ms.map, target.addr)) == ops->target.addr)
 413                ops->target.sym = target.ms.sym;
 414
 415        if (!ops->target.outside) {
 416                ops->target.offset = target.addr - start;
 417                ops->target.offset_avail = true;
 418        } else {
 419                ops->target.offset_avail = false;
 420        }
 421
 422        return 0;
 423}
 424
 425static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
 426                           struct ins_operands *ops, int max_ins_name)
 427{
 428        const char *c;
 429
 430        if (!ops->target.addr || ops->target.offset < 0)
 431                return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
 432
 433        if (ops->target.outside && ops->target.sym != NULL)
 434                return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name, ops->target.sym->name);
 435
 436        c = strchr(ops->raw, ',');
 437        c = validate_comma(c, ops);
 438
 439        if (c != NULL) {
 440                const char *c2 = strchr(c + 1, ',');
 441
 442                c2 = validate_comma(c2, ops);
 443                /* check for 3-op insn */
 444                if (c2 != NULL)
 445                        c = c2;
 446                c++;
 447
 448                /* mirror arch objdump's space-after-comma style */
 449                if (*c == ' ')
 450                        c++;
 451        }
 452
 453        return scnprintf(bf, size, "%-*s %.*s%" PRIx64, max_ins_name,
 454                         ins->name, c ? c - ops->raw : 0, ops->raw,
 455                         ops->target.offset);
 456}
 457
 458static struct ins_ops jump_ops = {
 459        .parse     = jump__parse,
 460        .scnprintf = jump__scnprintf,
 461};
 462
 463bool ins__is_jump(const struct ins *ins)
 464{
 465        return ins->ops == &jump_ops;
 466}
 467
 468static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
 469{
 470        char *endptr, *name, *t;
 471
 472        if (strstr(raw, "(%rip)") == NULL)
 473                return 0;
 474
 475        *addrp = strtoull(comment, &endptr, 16);
 476        if (endptr == comment)
 477                return 0;
 478        name = strchr(endptr, '<');
 479        if (name == NULL)
 480                return -1;
 481
 482        name++;
 483
 484        t = strchr(name, '>');
 485        if (t == NULL)
 486                return 0;
 487
 488        *t = '\0';
 489        *namep = strdup(name);
 490        *t = '>';
 491
 492        return 0;
 493}
 494
 495static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms)
 496{
 497        ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
 498        if (ops->locked.ops == NULL)
 499                return 0;
 500
 501        if (disasm_line__parse(ops->raw, &ops->locked.ins.name, &ops->locked.ops->raw) < 0)
 502                goto out_free_ops;
 503
 504        ops->locked.ins.ops = ins__find(arch, ops->locked.ins.name);
 505
 506        if (ops->locked.ins.ops == NULL)
 507                goto out_free_ops;
 508
 509        if (ops->locked.ins.ops->parse &&
 510            ops->locked.ins.ops->parse(arch, ops->locked.ops, ms) < 0)
 511                goto out_free_ops;
 512
 513        return 0;
 514
 515out_free_ops:
 516        zfree(&ops->locked.ops);
 517        return 0;
 518}
 519
 520static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
 521                           struct ins_operands *ops, int max_ins_name)
 522{
 523        int printed;
 524
 525        if (ops->locked.ins.ops == NULL)
 526                return ins__raw_scnprintf(ins, bf, size, ops, max_ins_name);
 527
 528        printed = scnprintf(bf, size, "%-*s ", max_ins_name, ins->name);
 529        return printed + ins__scnprintf(&ops->locked.ins, bf + printed,
 530                                        size - printed, ops->locked.ops, max_ins_name);
 531}
 532
 533static void lock__delete(struct ins_operands *ops)
 534{
 535        struct ins *ins = &ops->locked.ins;
 536
 537        if (ins->ops && ins->ops->free)
 538                ins->ops->free(ops->locked.ops);
 539        else
 540                ins__delete(ops->locked.ops);
 541
 542        zfree(&ops->locked.ops);
 543        zfree(&ops->target.raw);
 544        zfree(&ops->target.name);
 545}
 546
 547static struct ins_ops lock_ops = {
 548        .free      = lock__delete,
 549        .parse     = lock__parse,
 550        .scnprintf = lock__scnprintf,
 551};
 552
 553static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
 554{
 555        char *s = strchr(ops->raw, ','), *target, *comment, prev;
 556
 557        if (s == NULL)
 558                return -1;
 559
 560        *s = '\0';
 561        ops->source.raw = strdup(ops->raw);
 562        *s = ',';
 563
 564        if (ops->source.raw == NULL)
 565                return -1;
 566
 567        target = ++s;
 568        comment = strchr(s, arch->objdump.comment_char);
 569
 570        if (comment != NULL)
 571                s = comment - 1;
 572        else
 573                s = strchr(s, '\0') - 1;
 574
 575        while (s > target && isspace(s[0]))
 576                --s;
 577        s++;
 578        prev = *s;
 579        *s = '\0';
 580
 581        ops->target.raw = strdup(target);
 582        *s = prev;
 583
 584        if (ops->target.raw == NULL)
 585                goto out_free_source;
 586
 587        if (comment == NULL)
 588                return 0;
 589
 590        comment = skip_spaces(comment);
 591        comment__symbol(ops->source.raw, comment + 1, &ops->source.addr, &ops->source.name);
 592        comment__symbol(ops->target.raw, comment + 1, &ops->target.addr, &ops->target.name);
 593
 594        return 0;
 595
 596out_free_source:
 597        zfree(&ops->source.raw);
 598        return -1;
 599}
 600
 601static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
 602                           struct ins_operands *ops, int max_ins_name)
 603{
 604        return scnprintf(bf, size, "%-*s %s,%s", max_ins_name, ins->name,
 605                         ops->source.name ?: ops->source.raw,
 606                         ops->target.name ?: ops->target.raw);
 607}
 608
 609static struct ins_ops mov_ops = {
 610        .parse     = mov__parse,
 611        .scnprintf = mov__scnprintf,
 612};
 613
 614static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops, struct map_symbol *ms __maybe_unused)
 615{
 616        char *target, *comment, *s, prev;
 617
 618        target = s = ops->raw;
 619
 620        while (s[0] != '\0' && !isspace(s[0]))
 621                ++s;
 622        prev = *s;
 623        *s = '\0';
 624
 625        ops->target.raw = strdup(target);
 626        *s = prev;
 627
 628        if (ops->target.raw == NULL)
 629                return -1;
 630
 631        comment = strchr(s, arch->objdump.comment_char);
 632        if (comment == NULL)
 633                return 0;
 634
 635        comment = skip_spaces(comment);
 636        comment__symbol(ops->target.raw, comment + 1, &ops->target.addr, &ops->target.name);
 637
 638        return 0;
 639}
 640
 641static int dec__scnprintf(struct ins *ins, char *bf, size_t size,
 642                           struct ins_operands *ops, int max_ins_name)
 643{
 644        return scnprintf(bf, size, "%-*s %s", max_ins_name, ins->name,
 645                         ops->target.name ?: ops->target.raw);
 646}
 647
 648static struct ins_ops dec_ops = {
 649        .parse     = dec__parse,
 650        .scnprintf = dec__scnprintf,
 651};
 652
 653static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size,
 654                          struct ins_operands *ops __maybe_unused, int max_ins_name)
 655{
 656        return scnprintf(bf, size, "%-*s", max_ins_name, "nop");
 657}
 658
 659static struct ins_ops nop_ops = {
 660        .scnprintf = nop__scnprintf,
 661};
 662
 663static struct ins_ops ret_ops = {
 664        .scnprintf = ins__raw_scnprintf,
 665};
 666
 667bool ins__is_ret(const struct ins *ins)
 668{
 669        return ins->ops == &ret_ops;
 670}
 671
 672bool ins__is_lock(const struct ins *ins)
 673{
 674        return ins->ops == &lock_ops;
 675}
 676
 677static int ins__key_cmp(const void *name, const void *insp)
 678{
 679        const struct ins *ins = insp;
 680
 681        return strcmp(name, ins->name);
 682}
 683
 684static int ins__cmp(const void *a, const void *b)
 685{
 686        const struct ins *ia = a;
 687        const struct ins *ib = b;
 688
 689        return strcmp(ia->name, ib->name);
 690}
 691
 692static void ins__sort(struct arch *arch)
 693{
 694        const int nmemb = arch->nr_instructions;
 695
 696        qsort(arch->instructions, nmemb, sizeof(struct ins), ins__cmp);
 697}
 698
 699static struct ins_ops *__ins__find(struct arch *arch, const char *name)
 700{
 701        struct ins *ins;
 702        const int nmemb = arch->nr_instructions;
 703
 704        if (!arch->sorted_instructions) {
 705                ins__sort(arch);
 706                arch->sorted_instructions = true;
 707        }
 708
 709        ins = bsearch(name, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp);
 710        return ins ? ins->ops : NULL;
 711}
 712
 713static struct ins_ops *ins__find(struct arch *arch, const char *name)
 714{
 715        struct ins_ops *ops = __ins__find(arch, name);
 716
 717        if (!ops && arch->associate_instruction_ops)
 718                ops = arch->associate_instruction_ops(arch, name);
 719
 720        return ops;
 721}
 722
 723static int arch__key_cmp(const void *name, const void *archp)
 724{
 725        const struct arch *arch = archp;
 726
 727        return strcmp(name, arch->name);
 728}
 729
 730static int arch__cmp(const void *a, const void *b)
 731{
 732        const struct arch *aa = a;
 733        const struct arch *ab = b;
 734
 735        return strcmp(aa->name, ab->name);
 736}
 737
 738static void arch__sort(void)
 739{
 740        const int nmemb = ARRAY_SIZE(architectures);
 741
 742        qsort(architectures, nmemb, sizeof(struct arch), arch__cmp);
 743}
 744
 745static struct arch *arch__find(const char *name)
 746{
 747        const int nmemb = ARRAY_SIZE(architectures);
 748        static bool sorted;
 749
 750        if (!sorted) {
 751                arch__sort();
 752                sorted = true;
 753        }
 754
 755        return bsearch(name, architectures, nmemb, sizeof(struct arch), arch__key_cmp);
 756}
 757
 758static struct annotated_source *annotated_source__new(void)
 759{
 760        struct annotated_source *src = zalloc(sizeof(*src));
 761
 762        if (src != NULL)
 763                INIT_LIST_HEAD(&src->source);
 764
 765        return src;
 766}
 767
 768static __maybe_unused void annotated_source__delete(struct annotated_source *src)
 769{
 770        if (src == NULL)
 771                return;
 772        zfree(&src->histograms);
 773        zfree(&src->cycles_hist);
 774        free(src);
 775}
 776
 777static int annotated_source__alloc_histograms(struct annotated_source *src,
 778                                              size_t size, int nr_hists)
 779{
 780        size_t sizeof_sym_hist;
 781
 782        /*
 783         * Add buffer of one element for zero length symbol.
 784         * When sample is taken from first instruction of
 785         * zero length symbol, perf still resolves it and
 786         * shows symbol name in perf report and allows to
 787         * annotate it.
 788         */
 789        if (size == 0)
 790                size = 1;
 791
 792        /* Check for overflow when calculating sizeof_sym_hist */
 793        if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(struct sym_hist_entry))
 794                return -1;
 795
 796        sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(struct sym_hist_entry));
 797
 798        /* Check for overflow in zalloc argument */
 799        if (sizeof_sym_hist > SIZE_MAX / nr_hists)
 800                return -1;
 801
 802        src->sizeof_sym_hist = sizeof_sym_hist;
 803        src->nr_histograms   = nr_hists;
 804        src->histograms      = calloc(nr_hists, sizeof_sym_hist) ;
 805        return src->histograms ? 0 : -1;
 806}
 807
 808/* The cycles histogram is lazily allocated. */
 809static int symbol__alloc_hist_cycles(struct symbol *sym)
 810{
 811        struct annotation *notes = symbol__annotation(sym);
 812        const size_t size = symbol__size(sym);
 813
 814        notes->src->cycles_hist = calloc(size, sizeof(struct cyc_hist));
 815        if (notes->src->cycles_hist == NULL)
 816                return -1;
 817        return 0;
 818}
 819
 820void symbol__annotate_zero_histograms(struct symbol *sym)
 821{
 822        struct annotation *notes = symbol__annotation(sym);
 823
 824        pthread_mutex_lock(&notes->lock);
 825        if (notes->src != NULL) {
 826                memset(notes->src->histograms, 0,
 827                       notes->src->nr_histograms * notes->src->sizeof_sym_hist);
 828                if (notes->src->cycles_hist)
 829                        memset(notes->src->cycles_hist, 0,
 830                                symbol__size(sym) * sizeof(struct cyc_hist));
 831        }
 832        pthread_mutex_unlock(&notes->lock);
 833}
 834
 835static int __symbol__account_cycles(struct cyc_hist *ch,
 836                                    u64 start,
 837                                    unsigned offset, unsigned cycles,
 838                                    unsigned have_start)
 839{
 840        /*
 841         * For now we can only account one basic block per
 842         * final jump. But multiple could be overlapping.
 843         * Always account the longest one. So when
 844         * a shorter one has been already seen throw it away.
 845         *
 846         * We separately always account the full cycles.
 847         */
 848        ch[offset].num_aggr++;
 849        ch[offset].cycles_aggr += cycles;
 850
 851        if (cycles > ch[offset].cycles_max)
 852                ch[offset].cycles_max = cycles;
 853
 854        if (ch[offset].cycles_min) {
 855                if (cycles && cycles < ch[offset].cycles_min)
 856                        ch[offset].cycles_min = cycles;
 857        } else
 858                ch[offset].cycles_min = cycles;
 859
 860        if (!have_start && ch[offset].have_start)
 861                return 0;
 862        if (ch[offset].num) {
 863                if (have_start && (!ch[offset].have_start ||
 864                                   ch[offset].start > start)) {
 865                        ch[offset].have_start = 0;
 866                        ch[offset].cycles = 0;
 867                        ch[offset].num = 0;
 868                        if (ch[offset].reset < 0xffff)
 869                                ch[offset].reset++;
 870                } else if (have_start &&
 871                           ch[offset].start < start)
 872                        return 0;
 873        }
 874
 875        if (ch[offset].num < NUM_SPARKS)
 876                ch[offset].cycles_spark[ch[offset].num] = cycles;
 877
 878        ch[offset].have_start = have_start;
 879        ch[offset].start = start;
 880        ch[offset].cycles += cycles;
 881        ch[offset].num++;
 882        return 0;
 883}
 884
 885static int __symbol__inc_addr_samples(struct map_symbol *ms,
 886                                      struct annotated_source *src, int evidx, u64 addr,
 887                                      struct perf_sample *sample)
 888{
 889        struct symbol *sym = ms->sym;
 890        unsigned offset;
 891        struct sym_hist *h;
 892
 893        pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, ms->map->unmap_ip(ms->map, addr));
 894
 895        if ((addr < sym->start || addr >= sym->end) &&
 896            (addr != sym->end || sym->start != sym->end)) {
 897                pr_debug("%s(%d): ERANGE! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 "\n",
 898                       __func__, __LINE__, sym->name, sym->start, addr, sym->end);
 899                return -ERANGE;
 900        }
 901
 902        offset = addr - sym->start;
 903        h = annotated_source__histogram(src, evidx);
 904        if (h == NULL) {
 905                pr_debug("%s(%d): ENOMEM! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 ", func: %d\n",
 906                         __func__, __LINE__, sym->name, sym->start, addr, sym->end, sym->type == STT_FUNC);
 907                return -ENOMEM;
 908        }
 909        h->nr_samples++;
 910        h->addr[offset].nr_samples++;
 911        h->period += sample->period;
 912        h->addr[offset].period += sample->period;
 913
 914        pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
 915                  ", evidx=%d] => nr_samples: %" PRIu64 ", period: %" PRIu64 "\n",
 916                  sym->start, sym->name, addr, addr - sym->start, evidx,
 917                  h->addr[offset].nr_samples, h->addr[offset].period);
 918        return 0;
 919}
 920
 921static struct cyc_hist *symbol__cycles_hist(struct symbol *sym)
 922{
 923        struct annotation *notes = symbol__annotation(sym);
 924
 925        if (notes->src == NULL) {
 926                notes->src = annotated_source__new();
 927                if (notes->src == NULL)
 928                        return NULL;
 929                goto alloc_cycles_hist;
 930        }
 931
 932        if (!notes->src->cycles_hist) {
 933alloc_cycles_hist:
 934                symbol__alloc_hist_cycles(sym);
 935        }
 936
 937        return notes->src->cycles_hist;
 938}
 939
 940struct annotated_source *symbol__hists(struct symbol *sym, int nr_hists)
 941{
 942        struct annotation *notes = symbol__annotation(sym);
 943
 944        if (notes->src == NULL) {
 945                notes->src = annotated_source__new();
 946                if (notes->src == NULL)
 947                        return NULL;
 948                goto alloc_histograms;
 949        }
 950
 951        if (notes->src->histograms == NULL) {
 952alloc_histograms:
 953                annotated_source__alloc_histograms(notes->src, symbol__size(sym),
 954                                                   nr_hists);
 955        }
 956
 957        return notes->src;
 958}
 959
 960static int symbol__inc_addr_samples(struct map_symbol *ms,
 961                                    struct evsel *evsel, u64 addr,
 962                                    struct perf_sample *sample)
 963{
 964        struct symbol *sym = ms->sym;
 965        struct annotated_source *src;
 966
 967        if (sym == NULL)
 968                return 0;
 969        src = symbol__hists(sym, evsel->evlist->core.nr_entries);
 970        return src ? __symbol__inc_addr_samples(ms, src, evsel->core.idx, addr, sample) : 0;
 971}
 972
 973static int symbol__account_cycles(u64 addr, u64 start,
 974                                  struct symbol *sym, unsigned cycles)
 975{
 976        struct cyc_hist *cycles_hist;
 977        unsigned offset;
 978
 979        if (sym == NULL)
 980                return 0;
 981        cycles_hist = symbol__cycles_hist(sym);
 982        if (cycles_hist == NULL)
 983                return -ENOMEM;
 984        if (addr < sym->start || addr >= sym->end)
 985                return -ERANGE;
 986
 987        if (start) {
 988                if (start < sym->start || start >= sym->end)
 989                        return -ERANGE;
 990                if (start >= addr)
 991                        start = 0;
 992        }
 993        offset = addr - sym->start;
 994        return __symbol__account_cycles(cycles_hist,
 995                                        start ? start - sym->start : 0,
 996                                        offset, cycles,
 997                                        !!start);
 998}
 999
1000int 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
1034static 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
1046static 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
1077void 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
1111int 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
1117int 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
1123static 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
1134static 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
1158out:
1159        return -1;
1160}
1161
1162struct 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
1173static 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
1184static void annotation_line__exit(struct annotation_line *al)
1185{
1186        free_srcline(al->path);
1187        zfree(&al->line);
1188}
1189
1190static 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 */
1208static 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
1233out_free_line:
1234        zfree(&dl->al.line);
1235out_delete:
1236        free(dl);
1237        return NULL;
1238}
1239
1240void 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
1251int 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
1259void annotation__init(struct annotation *notes)
1260{
1261        pthread_mutex_init(&notes->lock, NULL);
1262}
1263
1264void annotation__exit(struct annotation *notes)
1265{
1266        annotated_source__delete(notes->src);
1267        pthread_mutex_destroy(&notes->lock);
1268}
1269
1270static void annotation_line__add(struct annotation_line *al, struct list_head *head)
1271{
1272        list_add_tail(&al->node, head);
1273}
1274
1275struct annotation_line *
1276annotation_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
1285static 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
1302static 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
1315static 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
1367static 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
1380static int
1381annotation_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 */
1500static 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
1566static __attribute__((constructor)) void symbol__init_regexpr(void)
1567{
1568        regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED);
1569}
1570
1571static 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
1595int 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
1648static 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)) {
1693fallback:
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
1724static int symbol__disassemble_bpf(struct symbol *sym,
1725                                   struct annotate_args *args)
1726{
1727        struct annotation *notes = symbol__annotation(sym);
1728        struct annotation_options *opts = args->options;
1729        struct bpf_prog_linfo *prog_linfo = NULL;
1730        struct bpf_prog_info_node *info_node;
1731        int len = sym->end - sym->start;
1732        disassembler_ftype disassemble;
1733        struct map *map = args->ms.map;
1734        struct perf_bpil *info_linear;
1735        struct disassemble_info info;
1736        struct dso *dso = map->dso;
1737        int pc = 0, count, sub_id;
1738        struct btf *btf = NULL;
1739        char tpath[PATH_MAX];
1740        size_t buf_size;
1741        int nr_skip = 0;
1742        char *buf;
1743        bfd *bfdf;
1744        int ret;
1745        FILE *s;
1746
1747        if (dso->binary_type != DSO_BINARY_TYPE__BPF_PROG_INFO)
1748                return SYMBOL_ANNOTATE_ERRNO__BPF_INVALID_FILE;
1749
1750        pr_debug("%s: handling sym %s addr %" PRIx64 " len %" PRIx64 "\n", __func__,
1751                  sym->name, sym->start, sym->end - sym->start);
1752
1753        memset(tpath, 0, sizeof(tpath));
1754        perf_exe(tpath, sizeof(tpath));
1755
1756        bfdf = bfd_openr(tpath, NULL);
1757        assert(bfdf);
1758        assert(bfd_check_format(bfdf, bfd_object));
1759
1760        s = open_memstream(&buf, &buf_size);
1761        if (!s) {
1762                ret = errno;
1763                goto out;
1764        }
1765        init_disassemble_info(&info, s,
1766                              (fprintf_ftype) fprintf);
1767
1768        info.arch = bfd_get_arch(bfdf);
1769        info.mach = bfd_get_mach(bfdf);
1770
1771        info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env,
1772                                                 dso->bpf_prog.id);
1773        if (!info_node) {
1774                ret = SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF;
1775                goto out;
1776        }
1777        info_linear = info_node->info_linear;
1778        sub_id = dso->bpf_prog.sub_id;
1779
1780        info.buffer = (void *)(uintptr_t)(info_linear->info.jited_prog_insns);
1781        info.buffer_length = info_linear->info.jited_prog_len;
1782
1783        if (info_linear->info.nr_line_info)
1784                prog_linfo = bpf_prog_linfo__new(&info_linear->info);
1785
1786        if (info_linear->info.btf_id) {
1787                struct btf_node *node;
1788
1789                node = perf_env__find_btf(dso->bpf_prog.env,
1790                                          info_linear->info.btf_id);
1791                if (node)
1792                        btf = btf__new((__u8 *)(node->data),
1793                                       node->data_size);
1794        }
1795
1796        disassemble_init_for_target(&info);
1797
1798#ifdef DISASM_FOUR_ARGS_SIGNATURE
1799        disassemble = disassembler(info.arch,
1800                                   bfd_big_endian(bfdf),
1801                                   info.mach,
1802                                   bfdf);
1803#else
1804        disassemble = disassembler(bfdf);
1805#endif
1806        assert(disassemble);
1807
1808        fflush(s);
1809        do {
1810                const struct bpf_line_info *linfo = NULL;
1811                struct disasm_line *dl;
1812                size_t prev_buf_size;
1813                const char *srcline;
1814                u64 addr;
1815
1816                addr = pc + ((u64 *)(uintptr_t)(info_linear->info.jited_ksyms))[sub_id];
1817                count = disassemble(pc, &info);
1818
1819                if (prog_linfo)
1820                        linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo,
1821                                                                addr, sub_id,
1822                                                                nr_skip);
1823
1824                if (linfo && btf) {
1825                        srcline = btf__name_by_offset(btf, linfo->line_off);
1826                        nr_skip++;
1827                } else
1828                        srcline = NULL;
1829
1830                fprintf(s, "\n");
1831                prev_buf_size = buf_size;
1832                fflush(s);
1833
1834                if (!opts->hide_src_code && srcline) {
1835                        args->offset = -1;
1836                        args->line = strdup(srcline);
1837                        args->line_nr = 0;
1838                        args->fileloc = NULL;
1839                        args->ms.sym  = sym;
1840                        dl = disasm_line__new(args);
1841                        if (dl) {
1842                                annotation_line__add(&dl->al,
1843                                                     &notes->src->source);
1844                        }
1845                }
1846
1847                args->offset = pc;
1848                args->line = buf + prev_buf_size;
1849                args->line_nr = 0;
1850                args->fileloc = NULL;
1851                args->ms.sym  = sym;
1852                dl = disasm_line__new(args);
1853                if (dl)
1854                        annotation_line__add(&dl->al, &notes->src->source);
1855
1856                pc += count;
1857        } while (count > 0 && pc < len);
1858
1859        ret = 0;
1860out:
1861        free(prog_linfo);
1862        btf__free(btf);
1863        fclose(s);
1864        bfd_close(bfdf);
1865        return ret;
1866}
1867#else // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
1868static int symbol__disassemble_bpf(struct symbol *sym __maybe_unused,
1869                                   struct annotate_args *args __maybe_unused)
1870{
1871        return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF;
1872}
1873#endif // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT)
1874
1875static int
1876symbol__disassemble_bpf_image(struct symbol *sym,
1877                              struct annotate_args *args)
1878{
1879        struct annotation *notes = symbol__annotation(sym);
1880        struct disasm_line *dl;
1881
1882        args->offset = -1;
1883        args->line = strdup("to be implemented");
1884        args->line_nr = 0;
1885        args->fileloc = NULL;
1886        dl = disasm_line__new(args);
1887        if (dl)
1888                annotation_line__add(&dl->al, &notes->src->source);
1889
1890        free(args->line);
1891        return 0;
1892}
1893
1894/*
1895 * Possibly create a new version of line with tabs expanded. Returns the
1896 * existing or new line, storage is updated if a new line is allocated. If
1897 * allocation fails then NULL is returned.
1898 */
1899static char *expand_tabs(char *line, char **storage, size_t *storage_len)
1900{
1901        size_t i, src, dst, len, new_storage_len, num_tabs;
1902        char *new_line;
1903        size_t line_len = strlen(line);
1904
1905        for (num_tabs = 0, i = 0; i < line_len; i++)
1906                if (line[i] == '\t')
1907                        num_tabs++;
1908
1909        if (num_tabs == 0)
1910                return line;
1911
1912        /*
1913         * Space for the line and '\0', less the leading and trailing
1914         * spaces. Each tab may introduce 7 additional spaces.
1915         */
1916        new_storage_len = line_len + 1 + (num_tabs * 7);
1917
1918        new_line = malloc(new_storage_len);
1919        if (new_line == NULL) {
1920                pr_err("Failure allocating memory for tab expansion\n");
1921                return NULL;
1922        }
1923
1924        /*
1925         * Copy regions starting at src and expand tabs. If there are two
1926         * adjacent tabs then 'src == i', the memcpy is of size 0 and the spaces
1927         * are inserted.
1928         */
1929        for (i = 0, src = 0, dst = 0; i < line_len && num_tabs; i++) {
1930                if (line[i] == '\t') {
1931                        len = i - src;
1932                        memcpy(&new_line[dst], &line[src], len);
1933                        dst += len;
1934                        new_line[dst++] = ' ';
1935                        while (dst % 8 != 0)
1936                                new_line[dst++] = ' ';
1937                        src = i + 1;
1938                        num_tabs--;
1939                }
1940        }
1941
1942        /* Expand the last region. */
1943        len = line_len - src;
1944        memcpy(&new_line[dst], &line[src], len);
1945        dst += len;
1946        new_line[dst] = '\0';
1947
1948        free(*storage);
1949        *storage = new_line;
1950        *storage_len = new_storage_len;
1951        return new_line;
1952
1953}
1954
1955static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
1956{
1957        struct annotation_options *opts = args->options;
1958        struct map *map = args->ms.map;
1959        struct dso *dso = map->dso;
1960        char *command;
1961        FILE *file;
1962        char symfs_filename[PATH_MAX];
1963        struct kcore_extract kce;
1964        bool delete_extract = false;
1965        bool decomp = false;
1966        int lineno = 0;
1967        char *fileloc = NULL;
1968        int nline;
1969        char *line;
1970        size_t line_len;
1971        const char *objdump_argv[] = {
1972                "/bin/sh",
1973                "-c",
1974                NULL, /* Will be the objdump command to run. */
1975                "--",
1976                NULL, /* Will be the symfs path. */
1977                NULL,
1978        };
1979        struct child_process objdump_process;
1980        int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));
1981
1982        if (err)
1983                return err;
1984
1985        pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
1986                 symfs_filename, sym->name, map->unmap_ip(map, sym->start),
1987                 map->unmap_ip(map, sym->end));
1988
1989        pr_debug("annotating [%p] %30s : [%p] %30s\n",
1990                 dso, dso->long_name, sym, sym->name);
1991
1992        if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) {
1993                return symbol__disassemble_bpf(sym, args);
1994        } else if (dso->binary_type == DSO_BINARY_TYPE__BPF_IMAGE) {
1995                return symbol__disassemble_bpf_image(sym, args);
1996        } else if (dso__is_kcore(dso)) {
1997                kce.kcore_filename = symfs_filename;
1998                kce.addr = map__rip_2objdump(map, sym->start);
1999                kce.offs = sym->start;
2000                kce.len = sym->end - sym->start;
2001                if (!kcore_extract__create(&kce)) {
2002                        delete_extract = true;
2003                        strlcpy(symfs_filename, kce.extract_filename,
2004                                sizeof(symfs_filename));
2005                }
2006        } else if (dso__needs_decompress(dso)) {
2007                char tmp[KMOD_DECOMP_LEN];
2008
2009                if (dso__decompress_kmodule_path(dso, symfs_filename,
2010                                                 tmp, sizeof(tmp)) < 0)
2011                        return -1;
2012
2013                decomp = true;
2014                strcpy(symfs_filename, tmp);
2015        }
2016
2017        err = asprintf(&command,
2018                 "%s %s%s --start-address=0x%016" PRIx64
2019                 " --stop-address=0x%016" PRIx64
2020                 " -l -d %s %s %s %c%s%c %s%s -C \"$1\"",
2021                 opts->objdump_path ?: "objdump",
2022                 opts->disassembler_style ? "-M " : "",
2023                 opts->disassembler_style ?: "",
2024                 map__rip_2objdump(map, sym->start),
2025                 map__rip_2objdump(map, sym->end),
2026                 opts->show_asm_raw ? "" : "--no-show-raw-insn",
2027                 opts->annotate_src ? "-S" : "",
2028                 opts->prefix ? "--prefix " : "",
2029                 opts->prefix ? '"' : ' ',
2030                 opts->prefix ?: "",
2031                 opts->prefix ? '"' : ' ',
2032                 opts->prefix_strip ? "--prefix-strip=" : "",
2033                 opts->prefix_strip ?: "");
2034
2035        if (err < 0) {
2036                pr_err("Failure allocating memory for the command to run\n");
2037                goto out_remove_tmp;
2038        }
2039
2040        pr_debug("Executing: %s\n", command);
2041
2042        objdump_argv[2] = command;
2043        objdump_argv[4] = symfs_filename;
2044
2045        /* Create a pipe to read from for stdout */
2046        memset(&objdump_process, 0, sizeof(objdump_process));
2047        objdump_process.argv = objdump_argv;
2048        objdump_process.out = -1;
2049        objdump_process.err = -1;
2050        objdump_process.no_stderr = 1;
2051        if (start_command(&objdump_process)) {
2052                pr_err("Failure starting to run %s\n", command);
2053                err = -1;
2054                goto out_free_command;
2055        }
2056
2057        file = fdopen(objdump_process.out, "r");
2058        if (!file) {
2059                pr_err("Failure creating FILE stream for %s\n", command);
2060                /*
2061                 * If we were using debug info should retry with
2062                 * original binary.
2063                 */
2064                err = -1;
2065                goto out_close_stdout;
2066        }
2067
2068        /* Storage for getline. */
2069        line = NULL;
2070        line_len = 0;
2071
2072        nline = 0;
2073        while (!feof(file)) {
2074                const char *match;
2075                char *expanded_line;
2076
2077                if (getline(&line, &line_len, file) < 0 || !line)
2078                        break;
2079
2080                /* Skip lines containing "filename:" */
2081                match = strstr(line, symfs_filename);
2082                if (match && match[strlen(symfs_filename)] == ':')
2083                        continue;
2084
2085                expanded_line = strim(line);
2086                expanded_line = expand_tabs(expanded_line, &line, &line_len);
2087                if (!expanded_line)
2088                        break;
2089
2090                /*
2091                 * The source code line number (lineno) needs to be kept in
2092                 * across calls to symbol__parse_objdump_line(), so that it
2093                 * can associate it with the instructions till the next one.
2094                 * See disasm_line__new() and struct disasm_line::line_nr.
2095                 */
2096                if (symbol__parse_objdump_line(sym, args, expanded_line,
2097                                               &lineno, &fileloc) < 0)
2098                        break;
2099                nline++;
2100        }
2101        free(line);
2102
2103        err = finish_command(&objdump_process);
2104        if (err)
2105                pr_err("Error running %s\n", command);
2106
2107        if (nline == 0) {
2108                err = -1;
2109                pr_err("No output from %s\n", command);
2110        }
2111
2112        /*
2113         * kallsyms does not have symbol sizes so there may a nop at the end.
2114         * Remove it.
2115         */
2116        if (dso__is_kcore(dso))
2117                delete_last_nop(sym);
2118
2119        fclose(file);
2120
2121out_close_stdout:
2122        close(objdump_process.out);
2123
2124out_free_command:
2125        free(command);
2126
2127out_remove_tmp:
2128        if (decomp)
2129                unlink(symfs_filename);
2130
2131        if (delete_extract)
2132                kcore_extract__delete(&kce);
2133
2134        return err;
2135}
2136
2137static void calc_percent(struct sym_hist *sym_hist,
2138                         struct hists *hists,
2139                         struct annotation_data *data,
2140                         s64 offset, s64 end)
2141{
2142        unsigned int hits = 0;
2143        u64 period = 0;
2144
2145        while (offset < end) {
2146                hits   += sym_hist->addr[offset].nr_samples;
2147                period += sym_hist->addr[offset].period;
2148                ++offset;
2149        }
2150
2151        if (sym_hist->nr_samples) {
2152                data->he.period     = period;
2153                data->he.nr_samples = hits;
2154                data->percent[PERCENT_HITS_LOCAL] = 100.0 * hits / sym_hist->nr_samples;
2155        }
2156
2157        if (hists->stats.nr_non_filtered_samples)
2158                data->percent[PERCENT_HITS_GLOBAL] = 100.0 * hits / hists->stats.nr_non_filtered_samples;
2159
2160        if (sym_hist->period)
2161                data->percent[PERCENT_PERIOD_LOCAL] = 100.0 * period / sym_hist->period;
2162
2163        if (hists->stats.total_period)
2164                data->percent[PERCENT_PERIOD_GLOBAL] = 100.0 * period / hists->stats.total_period;
2165}
2166
2167static void annotation__calc_percent(struct annotation *notes,
2168                                     struct evsel *leader, s64 len)
2169{
2170        struct annotation_line *al, *next;
2171        struct evsel *evsel;
2172
2173        list_for_each_entry(al, &notes->src->source, node) {
2174                s64 end;
2175                int i = 0;
2176
2177                if (al->offset == -1)
2178                        continue;
2179
2180                next = annotation_line__next(al, &notes->src->source);
2181                end  = next ? next->offset : len;
2182
2183                for_each_group_evsel(evsel, leader) {
2184                        struct hists *hists = evsel__hists(evsel);
2185                        struct annotation_data *data;
2186                        struct sym_hist *sym_hist;
2187
2188                        BUG_ON(i >= al->data_nr);
2189
2190                        sym_hist = annotation__histogram(notes, evsel->core.idx);
2191                        data = &al->data[i++];
2192
2193                        calc_percent(sym_hist, hists, data, al->offset, end);
2194                }
2195        }
2196}
2197
2198void symbol__calc_percent(struct symbol *sym, struct evsel *evsel)
2199{
2200        struct annotation *notes = symbol__annotation(sym);
2201
2202        annotation__calc_percent(notes, evsel, symbol__size(sym));
2203}
2204
2205int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
2206                     struct annotation_options *options, struct arch **parch)
2207{
2208        struct symbol *sym = ms->sym;
2209        struct annotation *notes = symbol__annotation(sym);
2210        struct annotate_args args = {
2211                .evsel          = evsel,
2212                .options        = options,
2213        };
2214        struct perf_env *env = evsel__env(evsel);
2215        const char *arch_name = perf_env__arch(env);
2216        struct arch *arch;
2217        int err;
2218
2219        if (!arch_name)
2220                return errno;
2221
2222        args.arch = arch = arch__find(arch_name);
2223        if (arch == NULL) {
2224                pr_err("%s: unsupported arch %s\n", __func__, arch_name);
2225                return ENOTSUP;
2226        }
2227
2228        if (parch)
2229                *parch = arch;
2230
2231        if (arch->init) {
2232                err = arch->init(arch, env ? env->cpuid : NULL);
2233                if (err) {
2234                        pr_err("%s: failed to initialize %s arch priv area\n", __func__, arch->name);
2235                        return err;
2236                }
2237        }
2238
2239        args.ms = *ms;
2240        notes->start = map__rip_2objdump(ms->map, sym->start);
2241
2242        return symbol__disassemble(sym, &args);
2243}
2244
2245static void insert_source_line(struct rb_root *root, struct annotation_line *al,
2246                               struct annotation_options *opts)
2247{
2248        struct annotation_line *iter;
2249        struct rb_node **p = &root->rb_node;
2250        struct rb_node *parent = NULL;
2251        int i, ret;
2252
2253        while (*p != NULL) {
2254                parent = *p;
2255                iter = rb_entry(parent, struct annotation_line, rb_node);
2256
2257                ret = strcmp(iter->path, al->path);
2258                if (ret == 0) {
2259                        for (i = 0; i < al->data_nr; i++) {
2260                                iter->data[i].percent_sum += annotation_data__percent(&al->data[i],
2261                                                                                      opts->percent_type);
2262                        }
2263                        return;
2264                }
2265
2266                if (ret < 0)
2267                        p = &(*p)->rb_left;
2268                else
2269                        p = &(*p)->rb_right;
2270        }
2271
2272        for (i = 0; i < al->data_nr; i++) {
2273                al->data[i].percent_sum = annotation_data__percent(&al->data[i],
2274                                                                   opts->percent_type);
2275        }
2276
2277        rb_link_node(&al->rb_node, parent, p);
2278        rb_insert_color(&al->rb_node, root);
2279}
2280
2281static int cmp_source_line(struct annotation_line *a, struct annotation_line *b)
2282{
2283        int i;
2284
2285        for (i = 0; i < a->data_nr; i++) {
2286                if (a->data[i].percent_sum == b->data[i].percent_sum)
2287                        continue;
2288                return a->data[i].percent_sum > b->data[i].percent_sum;
2289        }
2290
2291        return 0;
2292}
2293
2294static void __resort_source_line(struct rb_root *root, struct annotation_line *al)
2295{
2296        struct annotation_line *iter;
2297        struct rb_node **p = &root->rb_node;
2298        struct rb_node *parent = NULL;
2299
2300        while (*p != NULL) {
2301                parent = *p;
2302                iter = rb_entry(parent, struct annotation_line, rb_node);
2303
2304                if (cmp_source_line(al, iter))
2305                        p = &(*p)->rb_left;
2306                else
2307                        p = &(*p)->rb_right;
2308        }
2309
2310        rb_link_node(&al->rb_node, parent, p);
2311        rb_insert_color(&al->rb_node, root);
2312}
2313
2314static void resort_source_line(struct rb_root *dest_root, struct rb_root *src_root)
2315{
2316        struct annotation_line *al;
2317        struct rb_node *node;
2318
2319        node = rb_first(src_root);
2320        while (node) {
2321                struct rb_node *next;
2322
2323                al = rb_entry(node, struct annotation_line, rb_node);
2324                next = rb_next(node);
2325                rb_erase(node, src_root);
2326
2327                __resort_source_line(dest_root, al);
2328                node = next;
2329        }
2330}
2331
2332static void print_summary(struct rb_root *root, const char *filename)
2333{
2334        struct annotation_line *al;
2335        struct rb_node *node;
2336
2337        printf("\nSorted summary for file %s\n", filename);
2338        printf("----------------------------------------------\n\n");
2339
2340        if (RB_EMPTY_ROOT(root)) {
2341                printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
2342                return;
2343        }
2344
2345        node = rb_first(root);
2346        while (node) {
2347                double percent, percent_max = 0.0;
2348                const char *color;
2349                char *path;
2350                int i;
2351
2352                al = rb_entry(node, struct annotation_line, rb_node);
2353                for (i = 0; i < al->data_nr; i++) {
2354                        percent = al->data[i].percent_sum;
2355                        color = get_percent_color(percent);
2356                        color_fprintf(stdout, color, " %7.2f", percent);
2357
2358                        if (percent > percent_max)
2359                                percent_max = percent;
2360                }
2361
2362                path = al->path;
2363                color = get_percent_color(percent_max);
2364                color_fprintf(stdout, color, " %s\n", path);
2365
2366                node = rb_next(node);
2367        }
2368}
2369
2370static void symbol__annotate_hits(struct symbol *sym, struct evsel *evsel)
2371{
2372        struct annotation *notes = symbol__annotation(sym);
2373        struct sym_hist *h = annotation__histogram(notes, evsel->core.idx);
2374        u64 len = symbol__size(sym), offset;
2375
2376        for (offset = 0; offset < len; ++offset)
2377                if (h->addr[offset].nr_samples != 0)
2378                        printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
2379                               sym->start + offset, h->addr[offset].nr_samples);
2380        printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->nr_samples", h->nr_samples);
2381}
2382
2383static int annotated_source__addr_fmt_width(struct list_head *lines, u64 start)
2384{
2385        char bf[32];
2386        struct annotation_line *line;
2387
2388        list_for_each_entry_reverse(line, lines, node) {
2389                if (line->offset != -1)
2390                        return scnprintf(bf, sizeof(bf), "%" PRIx64, start + line->offset);
2391        }
2392
2393        return 0;
2394}
2395
2396int symbol__annotate_printf(struct map_symbol *ms, struct evsel *evsel,
2397                            struct annotation_options *opts)
2398{
2399        struct map *map = ms->map;
2400        struct symbol *sym = ms->sym;
2401        struct dso *dso = map->dso;
2402        char *filename;
2403        const char *d_filename;
2404        const char *evsel_name = evsel__name(evsel);
2405        struct annotation *notes = symbol__annotation(sym);
2406        struct sym_hist *h = annotation__histogram(notes, evsel->core.idx);
2407        struct annotation_line *pos, *queue = NULL;
2408        u64 start = map__rip_2objdump(map, sym->start);
2409        int printed = 2, queue_len = 0, addr_fmt_width;
2410        int more = 0;
2411        bool context = opts->context;
2412        u64 len;
2413        int width = symbol_conf.show_total_period ? 12 : 8;
2414        int graph_dotted_len;
2415        char buf[512];
2416
2417        filename = strdup(dso->long_name);
2418        if (!filename)
2419                return -ENOMEM;
2420
2421        if (opts->full_path)
2422                d_filename = filename;
2423        else
2424                d_filename = basename(filename);
2425
2426        len = symbol__size(sym);
2427
2428        if (evsel__is_group_event(evsel)) {
2429                width *= evsel->core.nr_members;
2430                evsel__group_desc(evsel, buf, sizeof(buf));
2431                evsel_name = buf;
2432        }
2433
2434        graph_dotted_len = printf(" %-*.*s|     Source code & Disassembly of %s for %s (%" PRIu64 " samples, "
2435                                  "percent: %s)\n",
2436                                  width, width, symbol_conf.show_total_period ? "Period" :
2437                                  symbol_conf.show_nr_samples ? "Samples" : "Percent",
2438                                  d_filename, evsel_name, h->nr_samples,
2439                                  percent_type_str(opts->percent_type));
2440
2441        printf("%-*.*s----\n",
2442               graph_dotted_len, graph_dotted_len, graph_dotted_line);
2443
2444        if (verbose > 0)
2445                symbol__annotate_hits(sym, evsel);
2446
2447        addr_fmt_width = annotated_source__addr_fmt_width(&notes->src->source, start);
2448
2449        list_for_each_entry(pos, &notes->src->source, node) {
2450                int err;
2451
2452                if (context && queue == NULL) {
2453                        queue = pos;
2454                        queue_len = 0;
2455                }
2456
2457                err = annotation_line__print(pos, sym, start, evsel, len,
2458                                             opts->min_pcnt, printed, opts->max_lines,
2459                                             queue, addr_fmt_width, opts->percent_type);
2460
2461                switch (err) {
2462                case 0:
2463                        ++printed;
2464                        if (context) {
2465                                printed += queue_len;
2466                                queue = NULL;
2467                                queue_len = 0;
2468                        }
2469                        break;
2470                case 1:
2471                        /* filtered by max_lines */
2472                        ++more;
2473                        break;
2474                case -1:
2475                default:
2476                        /*
2477                         * Filtered by min_pcnt or non IP lines when
2478                         * context != 0
2479                         */
2480                        if (!context)
2481                                break;
2482                        if (queue_len == context)
2483                                queue = list_entry(queue->node.next, typeof(*queue), node);
2484                        else
2485                                ++queue_len;
2486                        break;
2487                }
2488        }
2489
2490        free(filename);
2491
2492        return more;
2493}
2494
2495static void FILE__set_percent_color(void *fp __maybe_unused,
2496                                    double percent __maybe_unused,
2497                                    bool current __maybe_unused)
2498{
2499}
2500
2501static int FILE__set_jumps_percent_color(void *fp __maybe_unused,
2502                                         int nr __maybe_unused, bool current __maybe_unused)
2503{
2504        return 0;
2505}
2506
2507static int FILE__set_color(void *fp __maybe_unused, int color __maybe_unused)
2508{
2509        return 0;
2510}
2511
2512static void FILE__printf(void *fp, const char *fmt, ...)
2513{
2514        va_list args;
2515
2516        va_start(args, fmt);
2517        vfprintf(fp, fmt, args);
2518        va_end(args);
2519}
2520
2521static void FILE__write_graph(void *fp, int graph)
2522{
2523        const char *s;
2524        switch (graph) {
2525
2526        case DARROW_CHAR: s = "↓"; break;
2527        case UARROW_CHAR: s = "↑"; break;
2528        case LARROW_CHAR: s = "←"; break;
2529        case RARROW_CHAR: s = "→"; break;
2530        default:                s = "?"; break;
2531        }
2532
2533        fputs(s, fp);
2534}
2535
2536static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp,
2537                                     struct annotation_options *opts)
2538{
2539        struct annotation *notes = symbol__annotation(sym);
2540        struct annotation_write_ops wops = {
2541                .first_line              = true,
2542                .obj                     = fp,
2543                .set_color               = FILE__set_color,
2544                .set_percent_color       = FILE__set_percent_color,
2545                .set_jumps_percent_color = FILE__set_jumps_percent_color,
2546                .printf                  = FILE__printf,
2547                .write_graph             = FILE__write_graph,
2548        };
2549        struct annotation_line *al;
2550
2551        list_for_each_entry(al, &notes->src->source, node) {
2552                if (annotation_line__filter(al, notes))
2553                        continue;
2554                annotation_line__write(al, notes, &wops, opts);
2555                fputc('\n', fp);
2556                wops.first_line = false;
2557        }
2558
2559        return 0;
2560}
2561
2562int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel,
2563                                struct annotation_options *opts)
2564{
2565        const char *ev_name = evsel__name(evsel);
2566        char buf[1024];
2567        char *filename;
2568        int err = -1;
2569        FILE *fp;
2570
2571        if (asprintf(&filename, "%s.annotation", ms->sym->name) < 0)
2572                return -1;
2573
2574        fp = fopen(filename, "w");
2575        if (fp == NULL)
2576                goto out_free_filename;
2577
2578        if (evsel__is_group_event(evsel)) {
2579                evsel__group_desc(evsel, buf, sizeof(buf));
2580                ev_name = buf;
2581        }
2582
2583        fprintf(fp, "%s() %s\nEvent: %s\n\n",
2584                ms->sym->name, ms->map->dso->long_name, ev_name);
2585        symbol__annotate_fprintf2(ms->sym, fp, opts);
2586
2587        fclose(fp);
2588        err = 0;
2589out_free_filename:
2590        free(filename);
2591        return err;
2592}
2593
2594void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
2595{
2596        struct annotation *notes = symbol__annotation(sym);
2597        struct sym_hist *h = annotation__histogram(notes, evidx);
2598
2599        memset(h, 0, notes->src->sizeof_sym_hist);
2600}
2601
2602void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
2603{
2604        struct annotation *notes = symbol__annotation(sym);
2605        struct sym_hist *h = annotation__histogram(notes, evidx);
2606        int len = symbol__size(sym), offset;
2607
2608        h->nr_samples = 0;
2609        for (offset = 0; offset < len; ++offset) {
2610                h->addr[offset].nr_samples = h->addr[offset].nr_samples * 7 / 8;
2611                h->nr_samples += h->addr[offset].nr_samples;
2612        }
2613}
2614
2615void annotated_source__purge(struct annotated_source *as)
2616{
2617        struct annotation_line *al, *n;
2618
2619        list_for_each_entry_safe(al, n, &as->source, node) {
2620                list_del_init(&al->node);
2621                disasm_line__free(disasm_line(al));
2622        }
2623}
2624
2625static size_t disasm_line__fprintf(struct disasm_line *dl, FILE *fp)
2626{
2627        size_t printed;
2628
2629        if (dl->al.offset == -1)
2630                return fprintf(fp, "%s\n", dl->al.line);
2631
2632        printed = fprintf(fp, "%#" PRIx64 " %s", dl->al.offset, dl->ins.name);
2633
2634        if (dl->ops.raw[0] != '\0') {
2635                printed += fprintf(fp, "%.*s %s\n", 6 - (int)printed, " ",
2636                                   dl->ops.raw);
2637        }
2638
2639        return printed + fprintf(fp, "\n");
2640}
2641
2642size_t disasm__fprintf(struct list_head *head, FILE *fp)
2643{
2644        struct disasm_line *pos;
2645        size_t printed = 0;
2646
2647        list_for_each_entry(pos, head, al.node)
2648                printed += disasm_line__fprintf(pos, fp);
2649
2650        return printed;
2651}
2652
2653bool disasm_line__is_valid_local_jump(struct disasm_line *dl, struct symbol *sym)
2654{
2655        if (!dl || !dl->ins.ops || !ins__is_jump(&dl->ins) ||
2656            !disasm_line__has_local_offset(dl) || dl->ops.target.offset < 0 ||
2657            dl->ops.target.offset >= (s64)symbol__size(sym))
2658                return false;
2659
2660        return true;
2661}
2662
2663void annotation__mark_jump_targets(struct annotation *notes, struct symbol *sym)
2664{
2665        u64 offset, size = symbol__size(sym);
2666
2667        /* PLT symbols contain external offsets */
2668        if (strstr(sym->name, "@plt"))
2669                return;
2670
2671        for (offset = 0; offset < size; ++offset) {
2672                struct annotation_line *al = notes->offsets[offset];
2673                struct disasm_line *dl;
2674
2675                dl = disasm_line(al);
2676
2677                if (!disasm_line__is_valid_local_jump(dl, sym))
2678                        continue;
2679
2680                al = notes->offsets[dl->ops.target.offset];
2681
2682                /*
2683                 * FIXME: Oops, no jump target? Buggy disassembler? Or do we
2684                 * have to adjust to the previous offset?
2685                 */
2686                if (al == NULL)
2687                        continue;
2688
2689                if (++al->jump_sources > notes->max_jump_sources)
2690                        notes->max_jump_sources = al->jump_sources;
2691        }
2692}
2693
2694void annotation__set_offsets(struct annotation *notes, s64 size)
2695{
2696        struct annotation_line *al;
2697
2698        notes->max_line_len = 0;
2699        notes->nr_entries = 0;
2700        notes->nr_asm_entries = 0;
2701
2702        list_for_each_entry(al, &notes->src->source, node) {
2703                size_t line_len = strlen(al->line);
2704
2705                if (notes->max_line_len < line_len)
2706                        notes->max_line_len = line_len;
2707                al->idx = notes->nr_entries++;
2708                if (al->offset != -1) {
2709                        al->idx_asm = notes->nr_asm_entries++;
2710                        /*
2711                         * FIXME: short term bandaid to cope with assembly
2712                         * routines that comes with labels in the same column
2713                         * as the address in objdump, sigh.
2714                         *
2715                         * E.g. copy_user_generic_unrolled
2716                         */
2717                        if (al->offset < size)
2718                                notes->offsets[al->offset] = al;
2719                } else
2720                        al->idx_asm = -1;
2721        }
2722}
2723
2724static inline int width_jumps(int n)
2725{
2726        if (n >= 100)
2727                return 5;
2728        if (n / 10)
2729                return 2;
2730        return 1;
2731}
2732
2733static int annotation__max_ins_name(struct annotation *notes)
2734{
2735        int max_name = 0, len;
2736        struct annotation_line *al;
2737
2738        list_for_each_entry(al, &notes->src->source, node) {
2739                if (al->offset == -1)
2740                        continue;
2741
2742                len = strlen(disasm_line(al)->ins.name);
2743                if (max_name < len)
2744                        max_name = len;
2745        }
2746
2747        return max_name;
2748}
2749
2750void annotation__init_column_widths(struct annotation *notes, struct symbol *sym)
2751{
2752        notes->widths.addr = notes->widths.target =
2753                notes->widths.min_addr = hex_width(symbol__size(sym));
2754        notes->widths.max_addr = hex_width(sym->end);
2755        notes->widths.jumps = width_jumps(notes->max_jump_sources);
2756        notes->widths.max_ins_name = annotation__max_ins_name(notes);
2757}
2758
2759void annotation__update_column_widths(struct annotation *notes)
2760{
2761        if (notes->options->use_offset)
2762                notes->widths.target = notes->widths.min_addr;
2763        else
2764                notes->widths.target = notes->widths.max_addr;
2765
2766        notes->widths.addr = notes->widths.target;
2767
2768        if (notes->options->show_nr_jumps)
2769                notes->widths.addr += notes->widths.jumps + 1;
2770}
2771
2772static void annotation__calc_lines(struct annotation *notes, struct map *map,
2773                                   struct rb_root *root,
2774                                   struct annotation_options *opts)
2775{
2776        struct annotation_line *al;
2777        struct rb_root tmp_root = RB_ROOT;
2778
2779        list_for_each_entry(al, &notes->src->source, node) {
2780                double percent_max = 0.0;
2781                int i;
2782
2783                for (i = 0; i < al->data_nr; i++) {
2784                        double percent;
2785
2786                        percent = annotation_data__percent(&al->data[i],
2787                                                           opts->percent_type);
2788
2789                        if (percent > percent_max)
2790                                percent_max = percent;
2791                }
2792
2793                if (percent_max <= 0.5)
2794                        continue;
2795
2796                al->path = get_srcline(map->dso, notes->start + al->offset, NULL,
2797                                       false, true, notes->start + al->offset);
2798                insert_source_line(&tmp_root, al, opts);
2799        }
2800
2801        resort_source_line(root, &tmp_root);
2802}
2803
2804static void symbol__calc_lines(struct map_symbol *ms, struct rb_root *root,
2805                               struct annotation_options *opts)
2806{
2807        struct annotation *notes = symbol__annotation(ms->sym);
2808
2809        annotation__calc_lines(notes, ms->map, root, opts);
2810}
2811
2812int symbol__tty_annotate2(struct map_symbol *ms, struct evsel *evsel,
2813                          struct annotation_options *opts)
2814{
2815        struct dso *dso = ms->map->dso;
2816        struct symbol *sym = ms->sym;
2817        struct rb_root source_line = RB_ROOT;
2818        struct hists *hists = evsel__hists(evsel);
2819        char buf[1024];
2820        int err;
2821
2822        err = symbol__annotate2(ms, evsel, opts, NULL);
2823        if (err) {
2824                char msg[BUFSIZ];
2825
2826                dso->annotate_warned = true;
2827                symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
2828                ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
2829                return -1;
2830        }
2831
2832        if (opts->print_lines) {
2833                srcline_full_filename = opts->full_path;
2834                symbol__calc_lines(ms, &source_line, opts);
2835                print_summary(&source_line, dso->long_name);
2836        }
2837
2838        hists__scnprintf_title(hists, buf, sizeof(buf));
2839        fprintf(stdout, "%s, [percent: %s]\n%s() %s\n",
2840                buf, percent_type_str(opts->percent_type), sym->name, dso->long_name);
2841        symbol__annotate_fprintf2(sym, stdout, opts);
2842
2843        annotated_source__purge(symbol__annotation(sym)->src);
2844
2845        return 0;
2846}
2847
2848int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel,
2849                         struct annotation_options *opts)
2850{
2851        struct dso *dso = ms->map->dso;
2852        struct symbol *sym = ms->sym;
2853        struct rb_root source_line = RB_ROOT;
2854        int err;
2855
2856        err = symbol__annotate(ms, evsel, opts, NULL);
2857        if (err) {
2858                char msg[BUFSIZ];
2859
2860                dso->annotate_warned = true;
2861                symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
2862                ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
2863                return -1;
2864        }
2865
2866        symbol__calc_percent(sym, evsel);
2867
2868        if (opts->print_lines) {
2869                srcline_full_filename = opts->full_path;
2870                symbol__calc_lines(ms, &source_line, opts);
2871                print_summary(&source_line, dso->long_name);
2872        }
2873
2874        symbol__annotate_printf(ms, evsel, opts);
2875
2876        annotated_source__purge(symbol__annotation(sym)->src);
2877
2878        return 0;
2879}
2880
2881bool ui__has_annotation(void)
2882{
2883        return use_browser == 1 && perf_hpp_list.sym;
2884}
2885
2886
2887static double annotation_line__max_percent(struct annotation_line *al,
2888                                           struct annotation *notes,
2889                                           unsigned int percent_type)
2890{
2891        double percent_max = 0.0;
2892        int i;
2893
2894        for (i = 0; i < notes->nr_events; i++) {
2895                double percent;
2896
2897                percent = annotation_data__percent(&al->data[i],
2898                                                   percent_type);
2899
2900                if (percent > percent_max)
2901                        percent_max = percent;
2902        }
2903
2904        return percent_max;
2905}
2906
2907static void disasm_line__write(struct disasm_line *dl, struct annotation *notes,
2908                               void *obj, char *bf, size_t size,
2909                               void (*obj__printf)(void *obj, const char *fmt, ...),
2910                               void (*obj__write_graph)(void *obj, int graph))
2911{
2912        if (dl->ins.ops && dl->ins.ops->scnprintf) {
2913                if (ins__is_jump(&dl->ins)) {
2914                        bool fwd;
2915
2916                        if (dl->ops.target.outside)
2917                                goto call_like;
2918                        fwd = dl->ops.target.offset > dl->al.offset;
2919                        obj__write_graph(obj, fwd ? DARROW_CHAR : UARROW_CHAR);
2920                        obj__printf(obj, " ");
2921                } else if (ins__is_call(&dl->ins)) {
2922call_like:
2923                        obj__write_graph(obj, RARROW_CHAR);
2924                        obj__printf(obj, " ");
2925                } else if (ins__is_ret(&dl->ins)) {
2926                        obj__write_graph(obj, LARROW_CHAR);
2927                        obj__printf(obj, " ");
2928                } else {
2929                        obj__printf(obj, "  ");
2930                }
2931        } else {
2932                obj__printf(obj, "  ");
2933        }
2934
2935        disasm_line__scnprintf(dl, bf, size, !notes->options->use_offset, notes->widths.max_ins_name);
2936}
2937
2938static void ipc_coverage_string(char *bf, int size, struct annotation *notes)
2939{
2940        double ipc = 0.0, coverage = 0.0;
2941
2942        if (notes->hit_cycles)
2943                ipc = notes->hit_insn / ((double)notes->hit_cycles);
2944
2945        if (notes->total_insn) {
2946                coverage = notes->cover_insn * 100.0 /
2947                        ((double)notes->total_insn);
2948        }
2949
2950        scnprintf(bf, size, "(Average IPC: %.2f, IPC Coverage: %.1f%%)",
2951                  ipc, coverage);
2952}
2953
2954static void __annotation_line__write(struct annotation_line *al, struct annotation *notes,
2955                                     bool first_line, bool current_entry, bool change_color, int width,
2956                                     void *obj, unsigned int percent_type,
2957                                     int  (*obj__set_color)(void *obj, int color),
2958                                     void (*obj__set_percent_color)(void *obj, double percent, bool current),
2959                                     int  (*obj__set_jumps_percent_color)(void *obj, int nr, bool current),
2960                                     void (*obj__printf)(void *obj, const char *fmt, ...),
2961                                     void (*obj__write_graph)(void *obj, int graph))
2962
2963{
2964        double percent_max = annotation_line__max_percent(al, notes, percent_type);
2965        int pcnt_width = annotation__pcnt_width(notes),
2966            cycles_width = annotation__cycles_width(notes);
2967        bool show_title = false;
2968        char bf[256];
2969        int printed;
2970
2971        if (first_line && (al->offset == -1 || percent_max == 0.0)) {
2972                if (notes->have_cycles) {
2973                        if (al->ipc == 0.0 && al->cycles == 0)
2974                                show_title = true;
2975                } else
2976                        show_title = true;
2977        }
2978
2979        if (al->offset != -1 && percent_max != 0.0) {
2980                int i;
2981
2982                for (i = 0; i < notes->nr_events; i++) {
2983                        double percent;
2984
2985                        percent = annotation_data__percent(&al->data[i], percent_type);
2986
2987                        obj__set_percent_color(obj, percent, current_entry);
2988                        if (symbol_conf.show_total_period) {
2989                                obj__printf(obj, "%11" PRIu64 " ", al->data[i].he.period);
2990                        } else if (symbol_conf.show_nr_samples) {
2991                                obj__printf(obj, "%6" PRIu64 " ",
2992                                                   al->data[i].he.nr_samples);
2993                        } else {
2994                                obj__printf(obj, "%6.2f ", percent);
2995                        }
2996                }
2997        } else {
2998                obj__set_percent_color(obj, 0, current_entry);
2999
3000                if (!show_title)
3001                        obj__printf(obj, "%-*s", pcnt_width, " ");
3002                else {
3003                        obj__printf(obj, "%-*s", pcnt_width,
3004                                           symbol_conf.show_total_period ? "Period" :
3005                                           symbol_conf.show_nr_samples ? "Samples" : "Percent");
3006                }
3007        }
3008
3009        if (notes->have_cycles) {
3010                if (al->ipc)
3011                        obj__printf(obj, "%*.2f ", ANNOTATION__IPC_WIDTH - 1, al->ipc);
3012                else if (!show_title)
3013                        obj__printf(obj, "%*s", ANNOTATION__IPC_WIDTH, " ");
3014                else
3015                        obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
3016
3017                if (!notes->options->show_minmax_cycle) {
3018                        if (al->cycles)
3019                                obj__printf(obj, "%*" PRIu64 " ",
3020                                           ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
3021                        else if (!show_title)
3022                                obj__printf(obj, "%*s",
3023                                            ANNOTATION__CYCLES_WIDTH, " ");
3024                        else
3025                                obj__printf(obj, "%*s ",
3026                                            ANNOTATION__CYCLES_WIDTH - 1,
3027                                            "Cycle");
3028                } else {
3029                        if (al->cycles) {
3030                                char str[32];
3031
3032                                scnprintf(str, sizeof(str),
3033                                        "%" PRIu64 "(%" PRIu64 "/%" PRIu64 ")",
3034                                        al->cycles, al->cycles_min,
3035                                        al->cycles_max);
3036
3037                                obj__printf(obj, "%*s ",
3038                                            ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
3039                                            str);
3040                        } else if (!show_title)
3041                                obj__printf(obj, "%*s",
3042                                            ANNOTATION__MINMAX_CYCLES_WIDTH,
3043                                            " ");
3044                        else
3045                                obj__printf(obj, "%*s ",
3046                                            ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
3047                                            "Cycle(min/max)");
3048                }
3049
3050                if (show_title && !*al->line) {
3051                        ipc_coverage_string(bf, sizeof(bf), notes);
3052                        obj__printf(obj, "%*s", ANNOTATION__AVG_IPC_WIDTH, bf);
3053                }
3054        }
3055
3056        obj__printf(obj, " ");
3057
3058        if (!*al->line)
3059                obj__printf(obj, "%-*s", width - pcnt_width - cycles_width, " ");
3060        else if (al->offset == -1) {
3061                if (al->line_nr && notes->options->show_linenr)
3062                        printed = scnprintf(bf, sizeof(bf), "%-*d ", notes->widths.addr + 1, al->line_nr);
3063                else
3064                        printed = scnprintf(bf, sizeof(bf), "%-*s  ", notes->widths.addr, " ");
3065                obj__printf(obj, bf);
3066                obj__printf(obj, "%-*s", width - printed - pcnt_width - cycles_width + 1, al->line);
3067        } else {
3068                u64 addr = al->offset;
3069                int color = -1;
3070
3071                if (!notes->options->use_offset)
3072                        addr += notes->start;
3073
3074                if (!notes->options->use_offset) {
3075                        printed = scnprintf(bf, sizeof(bf), "%" PRIx64 ": ", addr);
3076                } else {
3077                        if (al->jump_sources &&
3078                            notes->options->offset_level >= ANNOTATION__OFFSET_JUMP_TARGETS) {
3079                                if (notes->options->show_nr_jumps) {
3080                                        int prev;
3081                                        printed = scnprintf(bf, sizeof(bf), "%*d ",
3082                                                            notes->widths.jumps,
3083                                                            al->jump_sources);
3084                                        prev = obj__set_jumps_percent_color(obj, al->jump_sources,
3085                                                                            current_entry);
3086                                        obj__printf(obj, bf);
3087                                        obj__set_color(obj, prev);
3088                                }
3089print_addr:
3090                                printed = scnprintf(bf, sizeof(bf), "%*" PRIx64 ": ",
3091                                                    notes->widths.target, addr);
3092                        } else if (ins__is_call(&disasm_line(al)->ins) &&
3093                                   notes->options->offset_level >= ANNOTATION__OFFSET_CALL) {
3094                                goto print_addr;
3095                        } else if (notes->options->offset_level == ANNOTATION__MAX_OFFSET_LEVEL) {
3096                                goto print_addr;
3097                        } else {
3098                                printed = scnprintf(bf, sizeof(bf), "%-*s  ",
3099                                                    notes->widths.addr, " ");
3100                        }
3101                }
3102
3103                if (change_color)
3104                        color = obj__set_color(obj, HE_COLORSET_ADDR);
3105                obj__printf(obj, bf);
3106                if (change_color)
3107                        obj__set_color(obj, color);
3108
3109                disasm_line__write(disasm_line(al), notes, obj, bf, sizeof(bf), obj__printf, obj__write_graph);
3110
3111                obj__printf(obj, "%-*s", width - pcnt_width - cycles_width - 3 - printed, bf);
3112        }
3113
3114}
3115
3116void annotation_line__write(struct annotation_line *al, struct annotation *notes,
3117                            struct annotation_write_ops *wops,
3118                            struct annotation_options *opts)
3119{
3120        __annotation_line__write(al, notes, wops->first_line, wops->current_entry,
3121                                 wops->change_color, wops->width, wops->obj,
3122                                 opts->percent_type,
3123                                 wops->set_color, wops->set_percent_color,
3124                                 wops->set_jumps_percent_color, wops->printf,
3125                                 wops->write_graph);
3126}
3127
3128int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,
3129                      struct annotation_options *options, struct arch **parch)
3130{
3131        struct symbol *sym = ms->sym;
3132        struct annotation *notes = symbol__annotation(sym);
3133        size_t size = symbol__size(sym);
3134        int nr_pcnt = 1, err;
3135
3136        notes->offsets = zalloc(size * sizeof(struct annotation_line *));
3137        if (notes->offsets == NULL)
3138                return ENOMEM;
3139
3140        if (evsel__is_group_event(evsel))
3141                nr_pcnt = evsel->core.nr_members;
3142
3143        err = symbol__annotate(ms, evsel, options, parch);
3144        if (err)
3145                goto out_free_offsets;
3146
3147        notes->options = options;
3148
3149        symbol__calc_percent(sym, evsel);
3150
3151        annotation__set_offsets(notes, size);
3152        annotation__mark_jump_targets(notes, sym);
3153        annotation__compute_ipc(notes, size);
3154        annotation__init_column_widths(notes, sym);
3155        notes->nr_events = nr_pcnt;
3156
3157        annotation__update_column_widths(notes);
3158        sym->annotate2 = 1;
3159
3160        return 0;
3161
3162out_free_offsets:
3163        zfree(&notes->offsets);
3164        return err;
3165}
3166
3167static int annotation__config(const char *var, const char *value, void *data)
3168{
3169        struct annotation_options *opt = data;
3170
3171        if (!strstarts(var, "annotate."))
3172                return 0;
3173
3174        if (!strcmp(var, "annotate.offset_level")) {
3175                perf_config_u8(&opt->offset_level, "offset_level", value);
3176
3177                if (opt->offset_level > ANNOTATION__MAX_OFFSET_LEVEL)
3178                        opt->offset_level = ANNOTATION__MAX_OFFSET_LEVEL;
3179                else if (opt->offset_level < ANNOTATION__MIN_OFFSET_LEVEL)
3180                        opt->offset_level = ANNOTATION__MIN_OFFSET_LEVEL;
3181        } else if (!strcmp(var, "annotate.hide_src_code")) {
3182                opt->hide_src_code = perf_config_bool("hide_src_code", value);
3183        } else if (!strcmp(var, "annotate.jump_arrows")) {
3184                opt->jump_arrows = perf_config_bool("jump_arrows", value);
3185        } else if (!strcmp(var, "annotate.show_linenr")) {
3186                opt->show_linenr = perf_config_bool("show_linenr", value);
3187        } else if (!strcmp(var, "annotate.show_nr_jumps")) {
3188                opt->show_nr_jumps = perf_config_bool("show_nr_jumps", value);
3189        } else if (!strcmp(var, "annotate.show_nr_samples")) {
3190                symbol_conf.show_nr_samples = perf_config_bool("show_nr_samples",
3191                                                                value);
3192        } else if (!strcmp(var, "annotate.show_total_period")) {
3193                symbol_conf.show_total_period = perf_config_bool("show_total_period",
3194                                                                value);
3195        } else if (!strcmp(var, "annotate.use_offset")) {
3196                opt->use_offset = perf_config_bool("use_offset", value);
3197        } else if (!strcmp(var, "annotate.disassembler_style")) {
3198                opt->disassembler_style = value;
3199        } else if (!strcmp(var, "annotate.demangle")) {
3200                symbol_conf.demangle = perf_config_bool("demangle", value);
3201        } else if (!strcmp(var, "annotate.demangle_kernel")) {
3202                symbol_conf.demangle_kernel = perf_config_bool("demangle_kernel", value);
3203        } else {
3204                pr_debug("%s variable unknown, ignoring...", var);
3205        }
3206
3207        return 0;
3208}
3209
3210void annotation_config__init(struct annotation_options *opt)
3211{
3212        perf_config(annotation__config, opt);
3213}
3214
3215static unsigned int parse_percent_type(char *str1, char *str2)
3216{
3217        unsigned int type = (unsigned int) -1;
3218
3219        if (!strcmp("period", str1)) {
3220                if (!strcmp("local", str2))
3221                        type = PERCENT_PERIOD_LOCAL;
3222                else if (!strcmp("global", str2))
3223                        type = PERCENT_PERIOD_GLOBAL;
3224        }
3225
3226        if (!strcmp("hits", str1)) {
3227                if (!strcmp("local", str2))
3228                        type = PERCENT_HITS_LOCAL;
3229                else if (!strcmp("global", str2))
3230                        type = PERCENT_HITS_GLOBAL;
3231        }
3232
3233        return type;
3234}
3235
3236int annotate_parse_percent_type(const struct option *opt, const char *_str,
3237                                int unset __maybe_unused)
3238{
3239        struct annotation_options *opts = opt->value;
3240        unsigned int type;
3241        char *str1, *str2;
3242        int err = -1;
3243
3244        str1 = strdup(_str);
3245        if (!str1)
3246                return -ENOMEM;
3247
3248        str2 = strchr(str1, '-');
3249        if (!str2)
3250                goto out;
3251
3252        *str2++ = 0;
3253
3254        type = parse_percent_type(str1, str2);
3255        if (type == (unsigned int) -1)
3256                type = parse_percent_type(str2, str1);
3257        if (type != (unsigned int) -1) {
3258                opts->percent_type = type;
3259                err = 0;
3260        }
3261
3262out:
3263        free(str1);
3264        return err;
3265}
3266
3267int annotate_check_args(struct annotation_options *args)
3268{
3269        if (args->prefix_strip && !args->prefix) {
3270                pr_err("--prefix-strip requires --prefix\n");
3271                return -1;
3272        }
3273        return 0;
3274}
3275