linux/tools/perf/util/annotate.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
   3 *
   4 * Parts came from builtin-annotate.c, see those files for further
   5 * copyright notes.
   6 *
   7 * Released under the GPL v2. (and only v2, not any later version)
   8 */
   9
  10#include "util.h"
  11#include "ui/ui.h"
  12#include "sort.h"
  13#include "build-id.h"
  14#include "color.h"
  15#include "cache.h"
  16#include "symbol.h"
  17#include "debug.h"
  18#include "annotate.h"
  19#include "evsel.h"
  20#include <regex.h>
  21#include <pthread.h>
  22#include <linux/bitops.h>
  23
  24const char      *disassembler_style;
  25const char      *objdump_path;
  26static regex_t   file_lineno;
  27
  28static struct ins *ins__find(const char *name);
  29static int disasm_line__parse(char *line, char **namep, char **rawp);
  30
  31static void ins__delete(struct ins_operands *ops)
  32{
  33        if (ops == NULL)
  34                return;
  35        zfree(&ops->source.raw);
  36        zfree(&ops->source.name);
  37        zfree(&ops->target.raw);
  38        zfree(&ops->target.name);
  39}
  40
  41static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
  42                              struct ins_operands *ops)
  43{
  44        return scnprintf(bf, size, "%-6.6s %s", ins->name, ops->raw);
  45}
  46
  47int ins__scnprintf(struct ins *ins, char *bf, size_t size,
  48                  struct ins_operands *ops)
  49{
  50        if (ins->ops->scnprintf)
  51                return ins->ops->scnprintf(ins, bf, size, ops);
  52
  53        return ins__raw_scnprintf(ins, bf, size, ops);
  54}
  55
  56static int call__parse(struct ins_operands *ops)
  57{
  58        char *endptr, *tok, *name;
  59
  60        ops->target.addr = strtoull(ops->raw, &endptr, 16);
  61
  62        name = strchr(endptr, '<');
  63        if (name == NULL)
  64                goto indirect_call;
  65
  66        name++;
  67
  68#ifdef __arm__
  69        if (strchr(name, '+'))
  70                return -1;
  71#endif
  72
  73        tok = strchr(name, '>');
  74        if (tok == NULL)
  75                return -1;
  76
  77        *tok = '\0';
  78        ops->target.name = strdup(name);
  79        *tok = '>';
  80
  81        return ops->target.name == NULL ? -1 : 0;
  82
  83indirect_call:
  84        tok = strchr(endptr, '(');
  85        if (tok != NULL) {
  86                ops->target.addr = 0;
  87                return 0;
  88        }
  89
  90        tok = strchr(endptr, '*');
  91        if (tok == NULL)
  92                return -1;
  93
  94        ops->target.addr = strtoull(tok + 1, NULL, 16);
  95        return 0;
  96}
  97
  98static int call__scnprintf(struct ins *ins, char *bf, size_t size,
  99                           struct ins_operands *ops)
 100{
 101        if (ops->target.name)
 102                return scnprintf(bf, size, "%-6.6s %s", ins->name, ops->target.name);
 103
 104        if (ops->target.addr == 0)
 105                return ins__raw_scnprintf(ins, bf, size, ops);
 106
 107        return scnprintf(bf, size, "%-6.6s *%" PRIx64, ins->name, ops->target.addr);
 108}
 109
 110static struct ins_ops call_ops = {
 111        .parse     = call__parse,
 112        .scnprintf = call__scnprintf,
 113};
 114
 115bool ins__is_call(const struct ins *ins)
 116{
 117        return ins->ops == &call_ops;
 118}
 119
 120static int jump__parse(struct ins_operands *ops)
 121{
 122        const char *s = strchr(ops->raw, '+');
 123
 124        ops->target.addr = strtoull(ops->raw, NULL, 16);
 125
 126        if (s++ != NULL)
 127                ops->target.offset = strtoull(s, NULL, 16);
 128        else
 129                ops->target.offset = UINT64_MAX;
 130
 131        return 0;
 132}
 133
 134static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
 135                           struct ins_operands *ops)
 136{
 137        return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset);
 138}
 139
 140static struct ins_ops jump_ops = {
 141        .parse     = jump__parse,
 142        .scnprintf = jump__scnprintf,
 143};
 144
 145bool ins__is_jump(const struct ins *ins)
 146{
 147        return ins->ops == &jump_ops;
 148}
 149
 150static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
 151{
 152        char *endptr, *name, *t;
 153
 154        if (strstr(raw, "(%rip)") == NULL)
 155                return 0;
 156
 157        *addrp = strtoull(comment, &endptr, 16);
 158        name = strchr(endptr, '<');
 159        if (name == NULL)
 160                return -1;
 161
 162        name++;
 163
 164        t = strchr(name, '>');
 165        if (t == NULL)
 166                return 0;
 167
 168        *t = '\0';
 169        *namep = strdup(name);
 170        *t = '>';
 171
 172        return 0;
 173}
 174
 175static int lock__parse(struct ins_operands *ops)
 176{
 177        char *name;
 178
 179        ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
 180        if (ops->locked.ops == NULL)
 181                return 0;
 182
 183        if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0)
 184                goto out_free_ops;
 185
 186        ops->locked.ins = ins__find(name);
 187        free(name);
 188
 189        if (ops->locked.ins == NULL)
 190                goto out_free_ops;
 191
 192        if (!ops->locked.ins->ops)
 193                return 0;
 194
 195        if (ops->locked.ins->ops->parse &&
 196            ops->locked.ins->ops->parse(ops->locked.ops) < 0)
 197                goto out_free_ops;
 198
 199        return 0;
 200
 201out_free_ops:
 202        zfree(&ops->locked.ops);
 203        return 0;
 204}
 205
 206static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
 207                           struct ins_operands *ops)
 208{
 209        int printed;
 210
 211        if (ops->locked.ins == NULL)
 212                return ins__raw_scnprintf(ins, bf, size, ops);
 213
 214        printed = scnprintf(bf, size, "%-6.6s ", ins->name);
 215        return printed + ins__scnprintf(ops->locked.ins, bf + printed,
 216                                        size - printed, ops->locked.ops);
 217}
 218
 219static void lock__delete(struct ins_operands *ops)
 220{
 221        struct ins *ins = ops->locked.ins;
 222
 223        if (ins && ins->ops->free)
 224                ins->ops->free(ops->locked.ops);
 225        else
 226                ins__delete(ops->locked.ops);
 227
 228        zfree(&ops->locked.ops);
 229        zfree(&ops->target.raw);
 230        zfree(&ops->target.name);
 231}
 232
 233static struct ins_ops lock_ops = {
 234        .free      = lock__delete,
 235        .parse     = lock__parse,
 236        .scnprintf = lock__scnprintf,
 237};
 238
 239static int mov__parse(struct ins_operands *ops)
 240{
 241        char *s = strchr(ops->raw, ','), *target, *comment, prev;
 242
 243        if (s == NULL)
 244                return -1;
 245
 246        *s = '\0';
 247        ops->source.raw = strdup(ops->raw);
 248        *s = ',';
 249
 250        if (ops->source.raw == NULL)
 251                return -1;
 252
 253        target = ++s;
 254#ifdef __arm__
 255        comment = strchr(s, ';');
 256#else
 257        comment = strchr(s, '#');
 258#endif
 259
 260        if (comment != NULL)
 261                s = comment - 1;
 262        else
 263                s = strchr(s, '\0') - 1;
 264
 265        while (s > target && isspace(s[0]))
 266                --s;
 267        s++;
 268        prev = *s;
 269        *s = '\0';
 270
 271        ops->target.raw = strdup(target);
 272        *s = prev;
 273
 274        if (ops->target.raw == NULL)
 275                goto out_free_source;
 276
 277        if (comment == NULL)
 278                return 0;
 279
 280        while (comment[0] != '\0' && isspace(comment[0]))
 281                ++comment;
 282
 283        comment__symbol(ops->source.raw, comment, &ops->source.addr, &ops->source.name);
 284        comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name);
 285
 286        return 0;
 287
 288out_free_source:
 289        zfree(&ops->source.raw);
 290        return -1;
 291}
 292
 293static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
 294                           struct ins_operands *ops)
 295{
 296        return scnprintf(bf, size, "%-6.6s %s,%s", ins->name,
 297                         ops->source.name ?: ops->source.raw,
 298                         ops->target.name ?: ops->target.raw);
 299}
 300
 301static struct ins_ops mov_ops = {
 302        .parse     = mov__parse,
 303        .scnprintf = mov__scnprintf,
 304};
 305
 306static int dec__parse(struct ins_operands *ops)
 307{
 308        char *target, *comment, *s, prev;
 309
 310        target = s = ops->raw;
 311
 312        while (s[0] != '\0' && !isspace(s[0]))
 313                ++s;
 314        prev = *s;
 315        *s = '\0';
 316
 317        ops->target.raw = strdup(target);
 318        *s = prev;
 319
 320        if (ops->target.raw == NULL)
 321                return -1;
 322
 323        comment = strchr(s, '#');
 324        if (comment == NULL)
 325                return 0;
 326
 327        while (comment[0] != '\0' && isspace(comment[0]))
 328                ++comment;
 329
 330        comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name);
 331
 332        return 0;
 333}
 334
 335static int dec__scnprintf(struct ins *ins, char *bf, size_t size,
 336                           struct ins_operands *ops)
 337{
 338        return scnprintf(bf, size, "%-6.6s %s", ins->name,
 339                         ops->target.name ?: ops->target.raw);
 340}
 341
 342static struct ins_ops dec_ops = {
 343        .parse     = dec__parse,
 344        .scnprintf = dec__scnprintf,
 345};
 346
 347static int nop__scnprintf(struct ins *ins __maybe_unused, char *bf, size_t size,
 348                          struct ins_operands *ops __maybe_unused)
 349{
 350        return scnprintf(bf, size, "%-6.6s", "nop");
 351}
 352
 353static struct ins_ops nop_ops = {
 354        .scnprintf = nop__scnprintf,
 355};
 356
 357static struct ins_ops ret_ops = {
 358        .scnprintf = ins__raw_scnprintf,
 359};
 360
 361bool ins__is_ret(const struct ins *ins)
 362{
 363        return ins->ops == &ret_ops;
 364}
 365
 366static struct ins instructions[] = {
 367        { .name = "add",   .ops  = &mov_ops, },
 368        { .name = "addl",  .ops  = &mov_ops, },
 369        { .name = "addq",  .ops  = &mov_ops, },
 370        { .name = "addw",  .ops  = &mov_ops, },
 371        { .name = "and",   .ops  = &mov_ops, },
 372#ifdef __arm__
 373        { .name = "b",     .ops  = &jump_ops, }, // might also be a call
 374        { .name = "bcc",   .ops  = &jump_ops, },
 375        { .name = "bcs",   .ops  = &jump_ops, },
 376        { .name = "beq",   .ops  = &jump_ops, },
 377        { .name = "bge",   .ops  = &jump_ops, },
 378        { .name = "bgt",   .ops  = &jump_ops, },
 379        { .name = "bhi",   .ops  = &jump_ops, },
 380        { .name = "bl",    .ops  = &call_ops, },
 381        { .name = "bls",   .ops  = &jump_ops, },
 382        { .name = "blt",   .ops  = &jump_ops, },
 383        { .name = "blx",   .ops  = &call_ops, },
 384        { .name = "bne",   .ops  = &jump_ops, },
 385#endif
 386        { .name = "bts",   .ops  = &mov_ops, },
 387        { .name = "call",  .ops  = &call_ops, },
 388        { .name = "callq", .ops  = &call_ops, },
 389        { .name = "cmp",   .ops  = &mov_ops, },
 390        { .name = "cmpb",  .ops  = &mov_ops, },
 391        { .name = "cmpl",  .ops  = &mov_ops, },
 392        { .name = "cmpq",  .ops  = &mov_ops, },
 393        { .name = "cmpw",  .ops  = &mov_ops, },
 394        { .name = "cmpxch", .ops  = &mov_ops, },
 395        { .name = "dec",   .ops  = &dec_ops, },
 396        { .name = "decl",  .ops  = &dec_ops, },
 397        { .name = "imul",  .ops  = &mov_ops, },
 398        { .name = "inc",   .ops  = &dec_ops, },
 399        { .name = "incl",  .ops  = &dec_ops, },
 400        { .name = "ja",    .ops  = &jump_ops, },
 401        { .name = "jae",   .ops  = &jump_ops, },
 402        { .name = "jb",    .ops  = &jump_ops, },
 403        { .name = "jbe",   .ops  = &jump_ops, },
 404        { .name = "jc",    .ops  = &jump_ops, },
 405        { .name = "jcxz",  .ops  = &jump_ops, },
 406        { .name = "je",    .ops  = &jump_ops, },
 407        { .name = "jecxz", .ops  = &jump_ops, },
 408        { .name = "jg",    .ops  = &jump_ops, },
 409        { .name = "jge",   .ops  = &jump_ops, },
 410        { .name = "jl",    .ops  = &jump_ops, },
 411        { .name = "jle",   .ops  = &jump_ops, },
 412        { .name = "jmp",   .ops  = &jump_ops, },
 413        { .name = "jmpq",  .ops  = &jump_ops, },
 414        { .name = "jna",   .ops  = &jump_ops, },
 415        { .name = "jnae",  .ops  = &jump_ops, },
 416        { .name = "jnb",   .ops  = &jump_ops, },
 417        { .name = "jnbe",  .ops  = &jump_ops, },
 418        { .name = "jnc",   .ops  = &jump_ops, },
 419        { .name = "jne",   .ops  = &jump_ops, },
 420        { .name = "jng",   .ops  = &jump_ops, },
 421        { .name = "jnge",  .ops  = &jump_ops, },
 422        { .name = "jnl",   .ops  = &jump_ops, },
 423        { .name = "jnle",  .ops  = &jump_ops, },
 424        { .name = "jno",   .ops  = &jump_ops, },
 425        { .name = "jnp",   .ops  = &jump_ops, },
 426        { .name = "jns",   .ops  = &jump_ops, },
 427        { .name = "jnz",   .ops  = &jump_ops, },
 428        { .name = "jo",    .ops  = &jump_ops, },
 429        { .name = "jp",    .ops  = &jump_ops, },
 430        { .name = "jpe",   .ops  = &jump_ops, },
 431        { .name = "jpo",   .ops  = &jump_ops, },
 432        { .name = "jrcxz", .ops  = &jump_ops, },
 433        { .name = "js",    .ops  = &jump_ops, },
 434        { .name = "jz",    .ops  = &jump_ops, },
 435        { .name = "lea",   .ops  = &mov_ops, },
 436        { .name = "lock",  .ops  = &lock_ops, },
 437        { .name = "mov",   .ops  = &mov_ops, },
 438        { .name = "movb",  .ops  = &mov_ops, },
 439        { .name = "movdqa",.ops  = &mov_ops, },
 440        { .name = "movl",  .ops  = &mov_ops, },
 441        { .name = "movq",  .ops  = &mov_ops, },
 442        { .name = "movslq", .ops  = &mov_ops, },
 443        { .name = "movzbl", .ops  = &mov_ops, },
 444        { .name = "movzwl", .ops  = &mov_ops, },
 445        { .name = "nop",   .ops  = &nop_ops, },
 446        { .name = "nopl",  .ops  = &nop_ops, },
 447        { .name = "nopw",  .ops  = &nop_ops, },
 448        { .name = "or",    .ops  = &mov_ops, },
 449        { .name = "orl",   .ops  = &mov_ops, },
 450        { .name = "test",  .ops  = &mov_ops, },
 451        { .name = "testb", .ops  = &mov_ops, },
 452        { .name = "testl", .ops  = &mov_ops, },
 453        { .name = "xadd",  .ops  = &mov_ops, },
 454        { .name = "xbeginl", .ops  = &jump_ops, },
 455        { .name = "xbeginq", .ops  = &jump_ops, },
 456        { .name = "retq",  .ops  = &ret_ops, },
 457};
 458
 459static int ins__key_cmp(const void *name, const void *insp)
 460{
 461        const struct ins *ins = insp;
 462
 463        return strcmp(name, ins->name);
 464}
 465
 466static int ins__cmp(const void *a, const void *b)
 467{
 468        const struct ins *ia = a;
 469        const struct ins *ib = b;
 470
 471        return strcmp(ia->name, ib->name);
 472}
 473
 474static void ins__sort(void)
 475{
 476        const int nmemb = ARRAY_SIZE(instructions);
 477
 478        qsort(instructions, nmemb, sizeof(struct ins), ins__cmp);
 479}
 480
 481static struct ins *ins__find(const char *name)
 482{
 483        const int nmemb = ARRAY_SIZE(instructions);
 484        static bool sorted;
 485
 486        if (!sorted) {
 487                ins__sort();
 488                sorted = true;
 489        }
 490
 491        return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp);
 492}
 493
 494int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym)
 495{
 496        struct annotation *notes = symbol__annotation(sym);
 497        pthread_mutex_init(&notes->lock, NULL);
 498        return 0;
 499}
 500
 501int symbol__alloc_hist(struct symbol *sym)
 502{
 503        struct annotation *notes = symbol__annotation(sym);
 504        const size_t size = symbol__size(sym);
 505        size_t sizeof_sym_hist;
 506
 507        /* Check for overflow when calculating sizeof_sym_hist */
 508        if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(u64))
 509                return -1;
 510
 511        sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64));
 512
 513        /* Check for overflow in zalloc argument */
 514        if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src))
 515                                / symbol_conf.nr_events)
 516                return -1;
 517
 518        notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist);
 519        if (notes->src == NULL)
 520                return -1;
 521        notes->src->sizeof_sym_hist = sizeof_sym_hist;
 522        notes->src->nr_histograms   = symbol_conf.nr_events;
 523        INIT_LIST_HEAD(&notes->src->source);
 524        return 0;
 525}
 526
 527/* The cycles histogram is lazily allocated. */
 528static int symbol__alloc_hist_cycles(struct symbol *sym)
 529{
 530        struct annotation *notes = symbol__annotation(sym);
 531        const size_t size = symbol__size(sym);
 532
 533        notes->src->cycles_hist = calloc(size, sizeof(struct cyc_hist));
 534        if (notes->src->cycles_hist == NULL)
 535                return -1;
 536        return 0;
 537}
 538
 539void symbol__annotate_zero_histograms(struct symbol *sym)
 540{
 541        struct annotation *notes = symbol__annotation(sym);
 542
 543        pthread_mutex_lock(&notes->lock);
 544        if (notes->src != NULL) {
 545                memset(notes->src->histograms, 0,
 546                       notes->src->nr_histograms * notes->src->sizeof_sym_hist);
 547                if (notes->src->cycles_hist)
 548                        memset(notes->src->cycles_hist, 0,
 549                                symbol__size(sym) * sizeof(struct cyc_hist));
 550        }
 551        pthread_mutex_unlock(&notes->lock);
 552}
 553
 554static int __symbol__account_cycles(struct annotation *notes,
 555                                    u64 start,
 556                                    unsigned offset, unsigned cycles,
 557                                    unsigned have_start)
 558{
 559        struct cyc_hist *ch;
 560
 561        ch = notes->src->cycles_hist;
 562        /*
 563         * For now we can only account one basic block per
 564         * final jump. But multiple could be overlapping.
 565         * Always account the longest one. So when
 566         * a shorter one has been already seen throw it away.
 567         *
 568         * We separately always account the full cycles.
 569         */
 570        ch[offset].num_aggr++;
 571        ch[offset].cycles_aggr += cycles;
 572
 573        if (!have_start && ch[offset].have_start)
 574                return 0;
 575        if (ch[offset].num) {
 576                if (have_start && (!ch[offset].have_start ||
 577                                   ch[offset].start > start)) {
 578                        ch[offset].have_start = 0;
 579                        ch[offset].cycles = 0;
 580                        ch[offset].num = 0;
 581                        if (ch[offset].reset < 0xffff)
 582                                ch[offset].reset++;
 583                } else if (have_start &&
 584                           ch[offset].start < start)
 585                        return 0;
 586        }
 587        ch[offset].have_start = have_start;
 588        ch[offset].start = start;
 589        ch[offset].cycles += cycles;
 590        ch[offset].num++;
 591        return 0;
 592}
 593
 594static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
 595                                      struct annotation *notes, int evidx, u64 addr)
 596{
 597        unsigned offset;
 598        struct sym_hist *h;
 599
 600        pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
 601
 602        if (addr < sym->start || addr >= sym->end) {
 603                pr_debug("%s(%d): ERANGE! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 "\n",
 604                       __func__, __LINE__, sym->name, sym->start, addr, sym->end);
 605                return -ERANGE;
 606        }
 607
 608        offset = addr - sym->start;
 609        h = annotation__histogram(notes, evidx);
 610        h->sum++;
 611        h->addr[offset]++;
 612
 613        pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
 614                  ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name,
 615                  addr, addr - sym->start, evidx, h->addr[offset]);
 616        return 0;
 617}
 618
 619static struct annotation *symbol__get_annotation(struct symbol *sym, bool cycles)
 620{
 621        struct annotation *notes = symbol__annotation(sym);
 622
 623        if (notes->src == NULL) {
 624                if (symbol__alloc_hist(sym) < 0)
 625                        return NULL;
 626        }
 627        if (!notes->src->cycles_hist && cycles) {
 628                if (symbol__alloc_hist_cycles(sym) < 0)
 629                        return NULL;
 630        }
 631        return notes;
 632}
 633
 634static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
 635                                    int evidx, u64 addr)
 636{
 637        struct annotation *notes;
 638
 639        if (sym == NULL)
 640                return 0;
 641        notes = symbol__get_annotation(sym, false);
 642        if (notes == NULL)
 643                return -ENOMEM;
 644        return __symbol__inc_addr_samples(sym, map, notes, evidx, addr);
 645}
 646
 647static int symbol__account_cycles(u64 addr, u64 start,
 648                                  struct symbol *sym, unsigned cycles)
 649{
 650        struct annotation *notes;
 651        unsigned offset;
 652
 653        if (sym == NULL)
 654                return 0;
 655        notes = symbol__get_annotation(sym, true);
 656        if (notes == NULL)
 657                return -ENOMEM;
 658        if (addr < sym->start || addr >= sym->end)
 659                return -ERANGE;
 660
 661        if (start) {
 662                if (start < sym->start || start >= sym->end)
 663                        return -ERANGE;
 664                if (start >= addr)
 665                        start = 0;
 666        }
 667        offset = addr - sym->start;
 668        return __symbol__account_cycles(notes,
 669                                        start ? start - sym->start : 0,
 670                                        offset, cycles,
 671                                        !!start);
 672}
 673
 674int addr_map_symbol__account_cycles(struct addr_map_symbol *ams,
 675                                    struct addr_map_symbol *start,
 676                                    unsigned cycles)
 677{
 678        u64 saddr = 0;
 679        int err;
 680
 681        if (!cycles)
 682                return 0;
 683
 684        /*
 685         * Only set start when IPC can be computed. We can only
 686         * compute it when the basic block is completely in a single
 687         * function.
 688         * Special case the case when the jump is elsewhere, but
 689         * it starts on the function start.
 690         */
 691        if (start &&
 692                (start->sym == ams->sym ||
 693                 (ams->sym &&
 694                   start->addr == ams->sym->start + ams->map->start)))
 695                saddr = start->al_addr;
 696        if (saddr == 0)
 697                pr_debug2("BB with bad start: addr %"PRIx64" start %"PRIx64" sym %"PRIx64" saddr %"PRIx64"\n",
 698                        ams->addr,
 699                        start ? start->addr : 0,
 700                        ams->sym ? ams->sym->start + ams->map->start : 0,
 701                        saddr);
 702        err = symbol__account_cycles(ams->al_addr, saddr, ams->sym, cycles);
 703        if (err)
 704                pr_debug2("account_cycles failed %d\n", err);
 705        return err;
 706}
 707
 708int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx)
 709{
 710        return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr);
 711}
 712
 713int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
 714{
 715        return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
 716}
 717
 718static void disasm_line__init_ins(struct disasm_line *dl)
 719{
 720        dl->ins = ins__find(dl->name);
 721
 722        if (dl->ins == NULL)
 723                return;
 724
 725        if (!dl->ins->ops)
 726                return;
 727
 728        if (dl->ins->ops->parse && dl->ins->ops->parse(&dl->ops) < 0)
 729                dl->ins = NULL;
 730}
 731
 732static int disasm_line__parse(char *line, char **namep, char **rawp)
 733{
 734        char *name = line, tmp;
 735
 736        while (isspace(name[0]))
 737                ++name;
 738
 739        if (name[0] == '\0')
 740                return -1;
 741
 742        *rawp = name + 1;
 743
 744        while ((*rawp)[0] != '\0' && !isspace((*rawp)[0]))
 745                ++*rawp;
 746
 747        tmp = (*rawp)[0];
 748        (*rawp)[0] = '\0';
 749        *namep = strdup(name);
 750
 751        if (*namep == NULL)
 752                goto out_free_name;
 753
 754        (*rawp)[0] = tmp;
 755
 756        if ((*rawp)[0] != '\0') {
 757                (*rawp)++;
 758                while (isspace((*rawp)[0]))
 759                        ++(*rawp);
 760        }
 761
 762        return 0;
 763
 764out_free_name:
 765        zfree(namep);
 766        return -1;
 767}
 768
 769static struct disasm_line *disasm_line__new(s64 offset, char *line,
 770                                        size_t privsize, int line_nr)
 771{
 772        struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
 773
 774        if (dl != NULL) {
 775                dl->offset = offset;
 776                dl->line = strdup(line);
 777                dl->line_nr = line_nr;
 778                if (dl->line == NULL)
 779                        goto out_delete;
 780
 781                if (offset != -1) {
 782                        if (disasm_line__parse(dl->line, &dl->name, &dl->ops.raw) < 0)
 783                                goto out_free_line;
 784
 785                        disasm_line__init_ins(dl);
 786                }
 787        }
 788
 789        return dl;
 790
 791out_free_line:
 792        zfree(&dl->line);
 793out_delete:
 794        free(dl);
 795        return NULL;
 796}
 797
 798void disasm_line__free(struct disasm_line *dl)
 799{
 800        zfree(&dl->line);
 801        zfree(&dl->name);
 802        if (dl->ins && dl->ins->ops->free)
 803                dl->ins->ops->free(&dl->ops);
 804        else
 805                ins__delete(&dl->ops);
 806        free(dl);
 807}
 808
 809int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw)
 810{
 811        if (raw || !dl->ins)
 812                return scnprintf(bf, size, "%-6.6s %s", dl->name, dl->ops.raw);
 813
 814        return ins__scnprintf(dl->ins, bf, size, &dl->ops);
 815}
 816
 817static void disasm__add(struct list_head *head, struct disasm_line *line)
 818{
 819        list_add_tail(&line->node, head);
 820}
 821
 822struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos)
 823{
 824        list_for_each_entry_continue(pos, head, node)
 825                if (pos->offset >= 0)
 826                        return pos;
 827
 828        return NULL;
 829}
 830
 831double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
 832                            s64 end, const char **path, u64 *nr_samples)
 833{
 834        struct source_line *src_line = notes->src->lines;
 835        double percent = 0.0;
 836        *nr_samples = 0;
 837
 838        if (src_line) {
 839                size_t sizeof_src_line = sizeof(*src_line) +
 840                                sizeof(src_line->samples) * (src_line->nr_pcnt - 1);
 841
 842                while (offset < end) {
 843                        src_line = (void *)notes->src->lines +
 844                                        (sizeof_src_line * offset);
 845
 846                        if (*path == NULL)
 847                                *path = src_line->path;
 848
 849                        percent += src_line->samples[evidx].percent;
 850                        *nr_samples += src_line->samples[evidx].nr;
 851                        offset++;
 852                }
 853        } else {
 854                struct sym_hist *h = annotation__histogram(notes, evidx);
 855                unsigned int hits = 0;
 856
 857                while (offset < end)
 858                        hits += h->addr[offset++];
 859
 860                if (h->sum) {
 861                        *nr_samples = hits;
 862                        percent = 100.0 * hits / h->sum;
 863                }
 864        }
 865
 866        return percent;
 867}
 868
 869static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 start,
 870                      struct perf_evsel *evsel, u64 len, int min_pcnt, int printed,
 871                      int max_lines, struct disasm_line *queue)
 872{
 873        static const char *prev_line;
 874        static const char *prev_color;
 875
 876        if (dl->offset != -1) {
 877                const char *path = NULL;
 878                u64 nr_samples;
 879                double percent, max_percent = 0.0;
 880                double *ppercents = &percent;
 881                u64 *psamples = &nr_samples;
 882                int i, nr_percent = 1;
 883                const char *color;
 884                struct annotation *notes = symbol__annotation(sym);
 885                s64 offset = dl->offset;
 886                const u64 addr = start + offset;
 887                struct disasm_line *next;
 888
 889                next = disasm__get_next_ip_line(&notes->src->source, dl);
 890
 891                if (perf_evsel__is_group_event(evsel)) {
 892                        nr_percent = evsel->nr_members;
 893                        ppercents = calloc(nr_percent, sizeof(double));
 894                        psamples = calloc(nr_percent, sizeof(u64));
 895                        if (ppercents == NULL || psamples == NULL) {
 896                                return -1;
 897                        }
 898                }
 899
 900                for (i = 0; i < nr_percent; i++) {
 901                        percent = disasm__calc_percent(notes,
 902                                        notes->src->lines ? i : evsel->idx + i,
 903                                        offset,
 904                                        next ? next->offset : (s64) len,
 905                                        &path, &nr_samples);
 906
 907                        ppercents[i] = percent;
 908                        psamples[i] = nr_samples;
 909                        if (percent > max_percent)
 910                                max_percent = percent;
 911                }
 912
 913                if (max_percent < min_pcnt)
 914                        return -1;
 915
 916                if (max_lines && printed >= max_lines)
 917                        return 1;
 918
 919                if (queue != NULL) {
 920                        list_for_each_entry_from(queue, &notes->src->source, node) {
 921                                if (queue == dl)
 922                                        break;
 923                                disasm_line__print(queue, sym, start, evsel, len,
 924                                                    0, 0, 1, NULL);
 925                        }
 926                }
 927
 928                color = get_percent_color(max_percent);
 929
 930                /*
 931                 * Also color the filename and line if needed, with
 932                 * the same color than the percentage. Don't print it
 933                 * twice for close colored addr with the same filename:line
 934                 */
 935                if (path) {
 936                        if (!prev_line || strcmp(prev_line, path)
 937                                       || color != prev_color) {
 938                                color_fprintf(stdout, color, " %s", path);
 939                                prev_line = path;
 940                                prev_color = color;
 941                        }
 942                }
 943
 944                for (i = 0; i < nr_percent; i++) {
 945                        percent = ppercents[i];
 946                        nr_samples = psamples[i];
 947                        color = get_percent_color(percent);
 948
 949                        if (symbol_conf.show_total_period)
 950                                color_fprintf(stdout, color, " %7" PRIu64,
 951                                              nr_samples);
 952                        else
 953                                color_fprintf(stdout, color, " %7.2f", percent);
 954                }
 955
 956                printf(" :      ");
 957                color_fprintf(stdout, PERF_COLOR_MAGENTA, "  %" PRIx64 ":", addr);
 958                color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", dl->line);
 959
 960                if (ppercents != &percent)
 961                        free(ppercents);
 962
 963                if (psamples != &nr_samples)
 964                        free(psamples);
 965
 966        } else if (max_lines && printed >= max_lines)
 967                return 1;
 968        else {
 969                int width = 8;
 970
 971                if (queue)
 972                        return -1;
 973
 974                if (perf_evsel__is_group_event(evsel))
 975                        width *= evsel->nr_members;
 976
 977                if (!*dl->line)
 978                        printf(" %*s:\n", width, " ");
 979                else
 980                        printf(" %*s:   %s\n", width, " ", dl->line);
 981        }
 982
 983        return 0;
 984}
 985
 986/*
 987 * symbol__parse_objdump_line() parses objdump output (with -d --no-show-raw)
 988 * which looks like following
 989 *
 990 *  0000000000415500 <_init>:
 991 *    415500:       sub    $0x8,%rsp
 992 *    415504:       mov    0x2f5ad5(%rip),%rax        # 70afe0 <_DYNAMIC+0x2f8>
 993 *    41550b:       test   %rax,%rax
 994 *    41550e:       je     415515 <_init+0x15>
 995 *    415510:       callq  416e70 <__gmon_start__@plt>
 996 *    415515:       add    $0x8,%rsp
 997 *    415519:       retq
 998 *
 999 * it will be parsed and saved into struct disasm_line as
1000 *  <offset>       <name>  <ops.raw>
1001 *
1002 * The offset will be a relative offset from the start of the symbol and -1
1003 * means that it's not a disassembly line so should be treated differently.
1004 * The ops.raw part will be parsed further according to type of the instruction.
1005 */
1006static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
1007                                      FILE *file, size_t privsize,
1008                                      int *line_nr)
1009{
1010        struct annotation *notes = symbol__annotation(sym);
1011        struct disasm_line *dl;
1012        char *line = NULL, *parsed_line, *tmp, *tmp2, *c;
1013        size_t line_len;
1014        s64 line_ip, offset = -1;
1015        regmatch_t match[2];
1016
1017        if (getline(&line, &line_len, file) < 0)
1018                return -1;
1019
1020        if (!line)
1021                return -1;
1022
1023        while (line_len != 0 && isspace(line[line_len - 1]))
1024                line[--line_len] = '\0';
1025
1026        c = strchr(line, '\n');
1027        if (c)
1028                *c = 0;
1029
1030        line_ip = -1;
1031        parsed_line = line;
1032
1033        /* /filename:linenr ? Save line number and ignore. */
1034        if (regexec(&file_lineno, line, 2, match, 0) == 0) {
1035                *line_nr = atoi(line + match[1].rm_so);
1036                return 0;
1037        }
1038
1039        /*
1040         * Strip leading spaces:
1041         */
1042        tmp = line;
1043        while (*tmp) {
1044                if (*tmp != ' ')
1045                        break;
1046                tmp++;
1047        }
1048
1049        if (*tmp) {
1050                /*
1051                 * Parse hexa addresses followed by ':'
1052                 */
1053                line_ip = strtoull(tmp, &tmp2, 16);
1054                if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0')
1055                        line_ip = -1;
1056        }
1057
1058        if (line_ip != -1) {
1059                u64 start = map__rip_2objdump(map, sym->start),
1060                    end = map__rip_2objdump(map, sym->end);
1061
1062                offset = line_ip - start;
1063                if ((u64)line_ip < start || (u64)line_ip >= end)
1064                        offset = -1;
1065                else
1066                        parsed_line = tmp2 + 1;
1067        }
1068
1069        dl = disasm_line__new(offset, parsed_line, privsize, *line_nr);
1070        free(line);
1071        (*line_nr)++;
1072
1073        if (dl == NULL)
1074                return -1;
1075
1076        if (dl->ops.target.offset == UINT64_MAX)
1077                dl->ops.target.offset = dl->ops.target.addr -
1078                                        map__rip_2objdump(map, sym->start);
1079
1080        /* kcore has no symbols, so add the call target name */
1081        if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) {
1082                struct addr_map_symbol target = {
1083                        .map = map,
1084                        .addr = dl->ops.target.addr,
1085                };
1086
1087                if (!map_groups__find_ams(&target, NULL) &&
1088                    target.sym->start == target.al_addr)
1089                        dl->ops.target.name = strdup(target.sym->name);
1090        }
1091
1092        disasm__add(&notes->src->source, dl);
1093
1094        return 0;
1095}
1096
1097static __attribute__((constructor)) void symbol__init_regexpr(void)
1098{
1099        regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED);
1100}
1101
1102static void delete_last_nop(struct symbol *sym)
1103{
1104        struct annotation *notes = symbol__annotation(sym);
1105        struct list_head *list = &notes->src->source;
1106        struct disasm_line *dl;
1107
1108        while (!list_empty(list)) {
1109                dl = list_entry(list->prev, struct disasm_line, node);
1110
1111                if (dl->ins && dl->ins->ops) {
1112                        if (dl->ins->ops != &nop_ops)
1113                                return;
1114                } else {
1115                        if (!strstr(dl->line, " nop ") &&
1116                            !strstr(dl->line, " nopl ") &&
1117                            !strstr(dl->line, " nopw "))
1118                                return;
1119                }
1120
1121                list_del(&dl->node);
1122                disasm_line__free(dl);
1123        }
1124}
1125
1126int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map,
1127                              int errnum, char *buf, size_t buflen)
1128{
1129        struct dso *dso = map->dso;
1130
1131        BUG_ON(buflen == 0);
1132
1133        if (errnum >= 0) {
1134                str_error_r(errnum, buf, buflen);
1135                return 0;
1136        }
1137
1138        switch (errnum) {
1139        case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: {
1140                char bf[SBUILD_ID_SIZE + 15] = " with build id ";
1141                char *build_id_msg = NULL;
1142
1143                if (dso->has_build_id) {
1144                        build_id__sprintf(dso->build_id,
1145                                          sizeof(dso->build_id), bf + 15);
1146                        build_id_msg = bf;
1147                }
1148                scnprintf(buf, buflen,
1149                          "No vmlinux file%s\nwas found in the path.\n\n"
1150                          "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"
1151                          "Please use:\n\n"
1152                          "  perf buildid-cache -vu vmlinux\n\n"
1153                          "or:\n\n"
1154                          "  --vmlinux vmlinux\n", build_id_msg ?: "");
1155        }
1156                break;
1157        default:
1158                scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum);
1159                break;
1160        }
1161
1162        return 0;
1163}
1164
1165int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize)
1166{
1167        struct dso *dso = map->dso;
1168        char *filename = dso__build_id_filename(dso, NULL, 0);
1169        bool free_filename = true;
1170        char command[PATH_MAX * 2];
1171        FILE *file;
1172        int err = 0;
1173        char symfs_filename[PATH_MAX];
1174        struct kcore_extract kce;
1175        bool delete_extract = false;
1176        int stdout_fd[2];
1177        int lineno = 0;
1178        int nline;
1179        pid_t pid;
1180
1181        if (filename)
1182                symbol__join_symfs(symfs_filename, filename);
1183
1184        if (filename == NULL) {
1185                if (dso->has_build_id)
1186                        return ENOMEM;
1187                goto fallback;
1188        } else if (dso__is_kcore(dso) ||
1189                   readlink(symfs_filename, command, sizeof(command)) < 0 ||
1190                   strstr(command, DSO__NAME_KALLSYMS) ||
1191                   access(symfs_filename, R_OK)) {
1192                free(filename);
1193fallback:
1194                /*
1195                 * If we don't have build-ids or the build-id file isn't in the
1196                 * cache, or is just a kallsyms file, well, lets hope that this
1197                 * DSO is the same as when 'perf record' ran.
1198                 */
1199                filename = (char *)dso->long_name;
1200                symbol__join_symfs(symfs_filename, filename);
1201                free_filename = false;
1202        }
1203
1204        if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1205            !dso__is_kcore(dso)) {
1206                err = SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
1207                goto out_free_filename;
1208        }
1209
1210        pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
1211                 filename, sym->name, map->unmap_ip(map, sym->start),
1212                 map->unmap_ip(map, sym->end));
1213
1214        pr_debug("annotating [%p] %30s : [%p] %30s\n",
1215                 dso, dso->long_name, sym, sym->name);
1216
1217        if (dso__is_kcore(dso)) {
1218                kce.kcore_filename = symfs_filename;
1219                kce.addr = map__rip_2objdump(map, sym->start);
1220                kce.offs = sym->start;
1221                kce.len = sym->end - sym->start;
1222                if (!kcore_extract__create(&kce)) {
1223                        delete_extract = true;
1224                        strlcpy(symfs_filename, kce.extract_filename,
1225                                sizeof(symfs_filename));
1226                        if (free_filename) {
1227                                free(filename);
1228                                free_filename = false;
1229                        }
1230                        filename = symfs_filename;
1231                }
1232        } else if (dso__needs_decompress(dso)) {
1233                char tmp[PATH_MAX];
1234                struct kmod_path m;
1235                int fd;
1236                bool ret;
1237
1238                if (kmod_path__parse_ext(&m, symfs_filename))
1239                        goto out_free_filename;
1240
1241                snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX");
1242
1243                fd = mkstemp(tmp);
1244                if (fd < 0) {
1245                        free(m.ext);
1246                        goto out_free_filename;
1247                }
1248
1249                ret = decompress_to_file(m.ext, symfs_filename, fd);
1250
1251                if (ret)
1252                        pr_err("Cannot decompress %s %s\n", m.ext, symfs_filename);
1253
1254                free(m.ext);
1255                close(fd);
1256
1257                if (!ret)
1258                        goto out_free_filename;
1259
1260                strcpy(symfs_filename, tmp);
1261        }
1262
1263        snprintf(command, sizeof(command),
1264                 "%s %s%s --start-address=0x%016" PRIx64
1265                 " --stop-address=0x%016" PRIx64
1266                 " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand",
1267                 objdump_path ? objdump_path : "objdump",
1268                 disassembler_style ? "-M " : "",
1269                 disassembler_style ? disassembler_style : "",
1270                 map__rip_2objdump(map, sym->start),
1271                 map__rip_2objdump(map, sym->end),
1272                 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
1273                 symbol_conf.annotate_src ? "-S" : "",
1274                 symfs_filename, filename);
1275
1276        pr_debug("Executing: %s\n", command);
1277
1278        err = -1;
1279        if (pipe(stdout_fd) < 0) {
1280                pr_err("Failure creating the pipe to run %s\n", command);
1281                goto out_remove_tmp;
1282        }
1283
1284        pid = fork();
1285        if (pid < 0) {
1286                pr_err("Failure forking to run %s\n", command);
1287                goto out_close_stdout;
1288        }
1289
1290        if (pid == 0) {
1291                close(stdout_fd[0]);
1292                dup2(stdout_fd[1], 1);
1293                close(stdout_fd[1]);
1294                execl("/bin/sh", "sh", "-c", command, NULL);
1295                perror(command);
1296                exit(-1);
1297        }
1298
1299        close(stdout_fd[1]);
1300
1301        file = fdopen(stdout_fd[0], "r");
1302        if (!file) {
1303                pr_err("Failure creating FILE stream for %s\n", command);
1304                /*
1305                 * If we were using debug info should retry with
1306                 * original binary.
1307                 */
1308                goto out_remove_tmp;
1309        }
1310
1311        nline = 0;
1312        while (!feof(file)) {
1313                if (symbol__parse_objdump_line(sym, map, file, privsize,
1314                            &lineno) < 0)
1315                        break;
1316                nline++;
1317        }
1318
1319        if (nline == 0)
1320                pr_err("No output from %s\n", command);
1321
1322        /*
1323         * kallsyms does not have symbol sizes so there may a nop at the end.
1324         * Remove it.
1325         */
1326        if (dso__is_kcore(dso))
1327                delete_last_nop(sym);
1328
1329        fclose(file);
1330        err = 0;
1331out_remove_tmp:
1332        close(stdout_fd[0]);
1333
1334        if (dso__needs_decompress(dso))
1335                unlink(symfs_filename);
1336out_free_filename:
1337        if (delete_extract)
1338                kcore_extract__delete(&kce);
1339        if (free_filename)
1340                free(filename);
1341        return err;
1342
1343out_close_stdout:
1344        close(stdout_fd[1]);
1345        goto out_remove_tmp;
1346}
1347
1348static void insert_source_line(struct rb_root *root, struct source_line *src_line)
1349{
1350        struct source_line *iter;
1351        struct rb_node **p = &root->rb_node;
1352        struct rb_node *parent = NULL;
1353        int i, ret;
1354
1355        while (*p != NULL) {
1356                parent = *p;
1357                iter = rb_entry(parent, struct source_line, node);
1358
1359                ret = strcmp(iter->path, src_line->path);
1360                if (ret == 0) {
1361                        for (i = 0; i < src_line->nr_pcnt; i++)
1362                                iter->samples[i].percent_sum += src_line->samples[i].percent;
1363                        return;
1364                }
1365
1366                if (ret < 0)
1367                        p = &(*p)->rb_left;
1368                else
1369                        p = &(*p)->rb_right;
1370        }
1371
1372        for (i = 0; i < src_line->nr_pcnt; i++)
1373                src_line->samples[i].percent_sum = src_line->samples[i].percent;
1374
1375        rb_link_node(&src_line->node, parent, p);
1376        rb_insert_color(&src_line->node, root);
1377}
1378
1379static int cmp_source_line(struct source_line *a, struct source_line *b)
1380{
1381        int i;
1382
1383        for (i = 0; i < a->nr_pcnt; i++) {
1384                if (a->samples[i].percent_sum == b->samples[i].percent_sum)
1385                        continue;
1386                return a->samples[i].percent_sum > b->samples[i].percent_sum;
1387        }
1388
1389        return 0;
1390}
1391
1392static void __resort_source_line(struct rb_root *root, struct source_line *src_line)
1393{
1394        struct source_line *iter;
1395        struct rb_node **p = &root->rb_node;
1396        struct rb_node *parent = NULL;
1397
1398        while (*p != NULL) {
1399                parent = *p;
1400                iter = rb_entry(parent, struct source_line, node);
1401
1402                if (cmp_source_line(src_line, iter))
1403                        p = &(*p)->rb_left;
1404                else
1405                        p = &(*p)->rb_right;
1406        }
1407
1408        rb_link_node(&src_line->node, parent, p);
1409        rb_insert_color(&src_line->node, root);
1410}
1411
1412static void resort_source_line(struct rb_root *dest_root, struct rb_root *src_root)
1413{
1414        struct source_line *src_line;
1415        struct rb_node *node;
1416
1417        node = rb_first(src_root);
1418        while (node) {
1419                struct rb_node *next;
1420
1421                src_line = rb_entry(node, struct source_line, node);
1422                next = rb_next(node);
1423                rb_erase(node, src_root);
1424
1425                __resort_source_line(dest_root, src_line);
1426                node = next;
1427        }
1428}
1429
1430static void symbol__free_source_line(struct symbol *sym, int len)
1431{
1432        struct annotation *notes = symbol__annotation(sym);
1433        struct source_line *src_line = notes->src->lines;
1434        size_t sizeof_src_line;
1435        int i;
1436
1437        sizeof_src_line = sizeof(*src_line) +
1438                          (sizeof(src_line->samples) * (src_line->nr_pcnt - 1));
1439
1440        for (i = 0; i < len; i++) {
1441                free_srcline(src_line->path);
1442                src_line = (void *)src_line + sizeof_src_line;
1443        }
1444
1445        zfree(&notes->src->lines);
1446}
1447
1448/* Get the filename:line for the colored entries */
1449static int symbol__get_source_line(struct symbol *sym, struct map *map,
1450                                   struct perf_evsel *evsel,
1451                                   struct rb_root *root, int len)
1452{
1453        u64 start;
1454        int i, k;
1455        int evidx = evsel->idx;
1456        struct source_line *src_line;
1457        struct annotation *notes = symbol__annotation(sym);
1458        struct sym_hist *h = annotation__histogram(notes, evidx);
1459        struct rb_root tmp_root = RB_ROOT;
1460        int nr_pcnt = 1;
1461        u64 h_sum = h->sum;
1462        size_t sizeof_src_line = sizeof(struct source_line);
1463
1464        if (perf_evsel__is_group_event(evsel)) {
1465                for (i = 1; i < evsel->nr_members; i++) {
1466                        h = annotation__histogram(notes, evidx + i);
1467                        h_sum += h->sum;
1468                }
1469                nr_pcnt = evsel->nr_members;
1470                sizeof_src_line += (nr_pcnt - 1) * sizeof(src_line->samples);
1471        }
1472
1473        if (!h_sum)
1474                return 0;
1475
1476        src_line = notes->src->lines = calloc(len, sizeof_src_line);
1477        if (!notes->src->lines)
1478                return -1;
1479
1480        start = map__rip_2objdump(map, sym->start);
1481
1482        for (i = 0; i < len; i++) {
1483                u64 offset;
1484                double percent_max = 0.0;
1485
1486                src_line->nr_pcnt = nr_pcnt;
1487
1488                for (k = 0; k < nr_pcnt; k++) {
1489                        h = annotation__histogram(notes, evidx + k);
1490                        src_line->samples[k].percent = 100.0 * h->addr[i] / h->sum;
1491
1492                        if (src_line->samples[k].percent > percent_max)
1493                                percent_max = src_line->samples[k].percent;
1494                }
1495
1496                if (percent_max <= 0.5)
1497                        goto next;
1498
1499                offset = start + i;
1500                src_line->path = get_srcline(map->dso, offset, NULL, false);
1501                insert_source_line(&tmp_root, src_line);
1502
1503        next:
1504                src_line = (void *)src_line + sizeof_src_line;
1505        }
1506
1507        resort_source_line(root, &tmp_root);
1508        return 0;
1509}
1510
1511static void print_summary(struct rb_root *root, const char *filename)
1512{
1513        struct source_line *src_line;
1514        struct rb_node *node;
1515
1516        printf("\nSorted summary for file %s\n", filename);
1517        printf("----------------------------------------------\n\n");
1518
1519        if (RB_EMPTY_ROOT(root)) {
1520                printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
1521                return;
1522        }
1523
1524        node = rb_first(root);
1525        while (node) {
1526                double percent, percent_max = 0.0;
1527                const char *color;
1528                char *path;
1529                int i;
1530
1531                src_line = rb_entry(node, struct source_line, node);
1532                for (i = 0; i < src_line->nr_pcnt; i++) {
1533                        percent = src_line->samples[i].percent_sum;
1534                        color = get_percent_color(percent);
1535                        color_fprintf(stdout, color, " %7.2f", percent);
1536
1537                        if (percent > percent_max)
1538                                percent_max = percent;
1539                }
1540
1541                path = src_line->path;
1542                color = get_percent_color(percent_max);
1543                color_fprintf(stdout, color, " %s\n", path);
1544
1545                node = rb_next(node);
1546        }
1547}
1548
1549static void symbol__annotate_hits(struct symbol *sym, struct perf_evsel *evsel)
1550{
1551        struct annotation *notes = symbol__annotation(sym);
1552        struct sym_hist *h = annotation__histogram(notes, evsel->idx);
1553        u64 len = symbol__size(sym), offset;
1554
1555        for (offset = 0; offset < len; ++offset)
1556                if (h->addr[offset] != 0)
1557                        printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
1558                               sym->start + offset, h->addr[offset]);
1559        printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
1560}
1561
1562int symbol__annotate_printf(struct symbol *sym, struct map *map,
1563                            struct perf_evsel *evsel, bool full_paths,
1564                            int min_pcnt, int max_lines, int context)
1565{
1566        struct dso *dso = map->dso;
1567        char *filename;
1568        const char *d_filename;
1569        const char *evsel_name = perf_evsel__name(evsel);
1570        struct annotation *notes = symbol__annotation(sym);
1571        struct sym_hist *h = annotation__histogram(notes, evsel->idx);
1572        struct disasm_line *pos, *queue = NULL;
1573        u64 start = map__rip_2objdump(map, sym->start);
1574        int printed = 2, queue_len = 0;
1575        int more = 0;
1576        u64 len;
1577        int width = 8;
1578        int graph_dotted_len;
1579
1580        filename = strdup(dso->long_name);
1581        if (!filename)
1582                return -ENOMEM;
1583
1584        if (full_paths)
1585                d_filename = filename;
1586        else
1587                d_filename = basename(filename);
1588
1589        len = symbol__size(sym);
1590
1591        if (perf_evsel__is_group_event(evsel))
1592                width *= evsel->nr_members;
1593
1594        graph_dotted_len = printf(" %-*.*s|     Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n",
1595               width, width, "Percent", d_filename, evsel_name, h->sum);
1596
1597        printf("%-*.*s----\n",
1598               graph_dotted_len, graph_dotted_len, graph_dotted_line);
1599
1600        if (verbose)
1601                symbol__annotate_hits(sym, evsel);
1602
1603        list_for_each_entry(pos, &notes->src->source, node) {
1604                if (context && queue == NULL) {
1605                        queue = pos;
1606                        queue_len = 0;
1607                }
1608
1609                switch (disasm_line__print(pos, sym, start, evsel, len,
1610                                            min_pcnt, printed, max_lines,
1611                                            queue)) {
1612                case 0:
1613                        ++printed;
1614                        if (context) {
1615                                printed += queue_len;
1616                                queue = NULL;
1617                                queue_len = 0;
1618                        }
1619                        break;
1620                case 1:
1621                        /* filtered by max_lines */
1622                        ++more;
1623                        break;
1624                case -1:
1625                default:
1626                        /*
1627                         * Filtered by min_pcnt or non IP lines when
1628                         * context != 0
1629                         */
1630                        if (!context)
1631                                break;
1632                        if (queue_len == context)
1633                                queue = list_entry(queue->node.next, typeof(*queue), node);
1634                        else
1635                                ++queue_len;
1636                        break;
1637                }
1638        }
1639
1640        free(filename);
1641
1642        return more;
1643}
1644
1645void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
1646{
1647        struct annotation *notes = symbol__annotation(sym);
1648        struct sym_hist *h = annotation__histogram(notes, evidx);
1649
1650        memset(h, 0, notes->src->sizeof_sym_hist);
1651}
1652
1653void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
1654{
1655        struct annotation *notes = symbol__annotation(sym);
1656        struct sym_hist *h = annotation__histogram(notes, evidx);
1657        int len = symbol__size(sym), offset;
1658
1659        h->sum = 0;
1660        for (offset = 0; offset < len; ++offset) {
1661                h->addr[offset] = h->addr[offset] * 7 / 8;
1662                h->sum += h->addr[offset];
1663        }
1664}
1665
1666void disasm__purge(struct list_head *head)
1667{
1668        struct disasm_line *pos, *n;
1669
1670        list_for_each_entry_safe(pos, n, head, node) {
1671                list_del(&pos->node);
1672                disasm_line__free(pos);
1673        }
1674}
1675
1676static size_t disasm_line__fprintf(struct disasm_line *dl, FILE *fp)
1677{
1678        size_t printed;
1679
1680        if (dl->offset == -1)
1681                return fprintf(fp, "%s\n", dl->line);
1682
1683        printed = fprintf(fp, "%#" PRIx64 " %s", dl->offset, dl->name);
1684
1685        if (dl->ops.raw[0] != '\0') {
1686                printed += fprintf(fp, "%.*s %s\n", 6 - (int)printed, " ",
1687                                   dl->ops.raw);
1688        }
1689
1690        return printed + fprintf(fp, "\n");
1691}
1692
1693size_t disasm__fprintf(struct list_head *head, FILE *fp)
1694{
1695        struct disasm_line *pos;
1696        size_t printed = 0;
1697
1698        list_for_each_entry(pos, head, node)
1699                printed += disasm_line__fprintf(pos, fp);
1700
1701        return printed;
1702}
1703
1704int symbol__tty_annotate(struct symbol *sym, struct map *map,
1705                         struct perf_evsel *evsel, bool print_lines,
1706                         bool full_paths, int min_pcnt, int max_lines)
1707{
1708        struct dso *dso = map->dso;
1709        struct rb_root source_line = RB_ROOT;
1710        u64 len;
1711
1712        if (symbol__disassemble(sym, map, 0) < 0)
1713                return -1;
1714
1715        len = symbol__size(sym);
1716
1717        if (print_lines) {
1718                srcline_full_filename = full_paths;
1719                symbol__get_source_line(sym, map, evsel, &source_line, len);
1720                print_summary(&source_line, dso->long_name);
1721        }
1722
1723        symbol__annotate_printf(sym, map, evsel, full_paths,
1724                                min_pcnt, max_lines, 0);
1725        if (print_lines)
1726                symbol__free_source_line(sym, len);
1727
1728        disasm__purge(&symbol__annotation(sym)->src->source);
1729
1730        return 0;
1731}
1732
1733bool ui__has_annotation(void)
1734{
1735        return use_browser == 1 && perf_hpp_list.sym;
1736}
1737