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