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