aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r--tools/perf/util/symbol.c268
1 files changed, 202 insertions, 66 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 4683b67b5ee4..5c0f42e6b33b 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -9,6 +9,16 @@
9 9
10const char *sym_hist_filter; 10const char *sym_hist_filter;
11 11
12enum dso_origin {
13 DSO__ORIG_KERNEL = 0,
14 DSO__ORIG_JAVA_JIT,
15 DSO__ORIG_FEDORA,
16 DSO__ORIG_UBUNTU,
17 DSO__ORIG_BUILDID,
18 DSO__ORIG_DSO,
19 DSO__ORIG_NOT_FOUND,
20};
21
12static struct symbol *symbol__new(u64 start, u64 len, 22static struct symbol *symbol__new(u64 start, u64 len,
13 const char *name, unsigned int priv_size, 23 const char *name, unsigned int priv_size,
14 u64 obj_start, int verbose) 24 u64 obj_start, int verbose)
@@ -65,6 +75,8 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
65 self->syms = RB_ROOT; 75 self->syms = RB_ROOT;
66 self->sym_priv_size = sym_priv_size; 76 self->sym_priv_size = sym_priv_size;
67 self->find_symbol = dso__find_symbol; 77 self->find_symbol = dso__find_symbol;
78 self->slen_calculated = 0;
79 self->origin = DSO__ORIG_NOT_FOUND;
68 } 80 }
69 81
70 return self; 82 return self;
@@ -373,36 +385,61 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
373 idx < nr_entries; \ 385 idx < nr_entries; \
374 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) 386 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
375 387
376static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, 388/*
377 GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym, 389 * We need to check if we have a .dynsym, so that we can handle the
378 GElf_Shdr *shdr_dynsym, 390 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
379 size_t dynsym_idx, int verbose) 391 * .dynsym or .symtab).
392 * And always look at the original dso, not at debuginfo packages, that
393 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
394 */
395static int dso__synthesize_plt_symbols(struct dso *self, int verbose)
380{ 396{
381 uint32_t nr_rel_entries, idx; 397 uint32_t nr_rel_entries, idx;
382 GElf_Sym sym; 398 GElf_Sym sym;
383 u64 plt_offset; 399 u64 plt_offset;
384 GElf_Shdr shdr_plt; 400 GElf_Shdr shdr_plt;
385 struct symbol *f; 401 struct symbol *f;
386 GElf_Shdr shdr_rel_plt; 402 GElf_Shdr shdr_rel_plt, shdr_dynsym;
387 Elf_Data *reldata, *syms, *symstrs; 403 Elf_Data *reldata, *syms, *symstrs;
388 Elf_Scn *scn_plt_rel, *scn_symstrs; 404 Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
405 size_t dynsym_idx;
406 GElf_Ehdr ehdr;
389 char sympltname[1024]; 407 char sympltname[1024];
390 int nr = 0, symidx; 408 Elf *elf;
409 int nr = 0, symidx, fd, err = 0;
410
411 fd = open(self->name, O_RDONLY);
412 if (fd < 0)
413 goto out;
391 414
392 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 415 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
416 if (elf == NULL)
417 goto out_close;
418
419 if (gelf_getehdr(elf, &ehdr) == NULL)
420 goto out_elf_end;
421
422 scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
423 ".dynsym", &dynsym_idx);
424 if (scn_dynsym == NULL)
425 goto out_elf_end;
426
427 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
393 ".rela.plt", NULL); 428 ".rela.plt", NULL);
394 if (scn_plt_rel == NULL) { 429 if (scn_plt_rel == NULL) {
395 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 430 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
396 ".rel.plt", NULL); 431 ".rel.plt", NULL);
397 if (scn_plt_rel == NULL) 432 if (scn_plt_rel == NULL)
398 return 0; 433 goto out_elf_end;
399 } 434 }
400 435
436 err = -1;
437
401 if (shdr_rel_plt.sh_link != dynsym_idx) 438 if (shdr_rel_plt.sh_link != dynsym_idx)
402 return 0; 439 goto out_elf_end;
403 440
404 if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL) 441 if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
405 return 0; 442 goto out_elf_end;
406 443
407 /* 444 /*
408 * Fetch the relocation section to find the indexes to the GOT 445 * Fetch the relocation section to find the indexes to the GOT
@@ -410,19 +447,19 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
410 */ 447 */
411 reldata = elf_getdata(scn_plt_rel, NULL); 448 reldata = elf_getdata(scn_plt_rel, NULL);
412 if (reldata == NULL) 449 if (reldata == NULL)
413 return -1; 450 goto out_elf_end;
414 451
415 syms = elf_getdata(scn_dynsym, NULL); 452 syms = elf_getdata(scn_dynsym, NULL);
416 if (syms == NULL) 453 if (syms == NULL)
417 return -1; 454 goto out_elf_end;
418 455
419 scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link); 456 scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
420 if (scn_symstrs == NULL) 457 if (scn_symstrs == NULL)
421 return -1; 458 goto out_elf_end;
422 459
423 symstrs = elf_getdata(scn_symstrs, NULL); 460 symstrs = elf_getdata(scn_symstrs, NULL);
424 if (symstrs == NULL) 461 if (symstrs == NULL)
425 return -1; 462 goto out_elf_end;
426 463
427 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; 464 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
428 plt_offset = shdr_plt.sh_offset; 465 plt_offset = shdr_plt.sh_offset;
@@ -441,7 +478,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
441 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 478 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
442 sympltname, self->sym_priv_size, 0, verbose); 479 sympltname, self->sym_priv_size, 0, verbose);
443 if (!f) 480 if (!f)
444 return -1; 481 goto out_elf_end;
445 482
446 dso__insert_symbol(self, f); 483 dso__insert_symbol(self, f);
447 ++nr; 484 ++nr;
@@ -459,19 +496,25 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
459 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 496 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
460 sympltname, self->sym_priv_size, 0, verbose); 497 sympltname, self->sym_priv_size, 0, verbose);
461 if (!f) 498 if (!f)
462 return -1; 499 goto out_elf_end;
463 500
464 dso__insert_symbol(self, f); 501 dso__insert_symbol(self, f);
465 ++nr; 502 ++nr;
466 } 503 }
467 } else {
468 /*
469 * TODO: There are still one more shdr_rel_plt.sh_type
470 * I have to investigate, but probably should be ignored.
471 */
472 } 504 }
473 505
474 return nr; 506 err = 0;
507out_elf_end:
508 elf_end(elf);
509out_close:
510 close(fd);
511
512 if (err == 0)
513 return nr;
514out:
515 fprintf(stderr, "%s: problems reading %s PLT info.\n",
516 __func__, self->name);
517 return 0;
475} 518}
476 519
477static int dso__load_sym(struct dso *self, int fd, const char *name, 520static int dso__load_sym(struct dso *self, int fd, const char *name,
@@ -485,10 +528,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
485 GElf_Shdr shdr; 528 GElf_Shdr shdr;
486 Elf_Data *syms; 529 Elf_Data *syms;
487 GElf_Sym sym; 530 GElf_Sym sym;
488 Elf_Scn *sec, *sec_dynsym, *sec_strndx; 531 Elf_Scn *sec, *sec_strndx;
489 Elf *elf; 532 Elf *elf;
490 size_t dynsym_idx; 533 int nr = 0, kernel = !strcmp("[kernel]", self->name);
491 int nr = 0;
492 534
493 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 535 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
494 if (elf == NULL) { 536 if (elf == NULL) {
@@ -504,32 +546,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
504 goto out_elf_end; 546 goto out_elf_end;
505 } 547 }
506 548
507 /*
508 * We need to check if we have a .dynsym, so that we can handle the
509 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
510 * .dynsym or .symtab)
511 */
512 sec_dynsym = elf_section_by_name(elf, &ehdr, &shdr,
513 ".dynsym", &dynsym_idx);
514 if (sec_dynsym != NULL) {
515 nr = dso__synthesize_plt_symbols(self, elf, &ehdr,
516 sec_dynsym, &shdr,
517 dynsym_idx, verbose);
518 if (nr < 0)
519 goto out_elf_end;
520 }
521
522 /*
523 * But if we have a full .symtab (that is a superset of .dynsym) we
524 * should add the symbols not in the .dynsyn
525 */
526 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); 549 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
527 if (sec == NULL) { 550 if (sec == NULL) {
528 if (sec_dynsym == NULL) 551 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
552 if (sec == NULL)
529 goto out_elf_end; 553 goto out_elf_end;
530
531 sec = sec_dynsym;
532 gelf_getshdr(sec, &shdr);
533 } 554 }
534 555
535 syms = elf_getdata(sec, NULL); 556 syms = elf_getdata(sec, NULL);
@@ -549,18 +570,23 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
549 goto out_elf_end; 570 goto out_elf_end;
550 571
551 secstrs = elf_getdata(sec_strndx, NULL); 572 secstrs = elf_getdata(sec_strndx, NULL);
552 if (symstrs == NULL) 573 if (secstrs == NULL)
553 goto out_elf_end; 574 goto out_elf_end;
554 575
555 nr_syms = shdr.sh_size / shdr.sh_entsize; 576 nr_syms = shdr.sh_size / shdr.sh_entsize;
556 577
557 memset(&sym, 0, sizeof(sym)); 578 memset(&sym, 0, sizeof(sym));
558 self->adjust_symbols = (ehdr.e_type == ET_EXEC || 579 if (!kernel) {
580 self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
559 elf_section_by_name(elf, &ehdr, &shdr, 581 elf_section_by_name(elf, &ehdr, &shdr,
560 ".gnu.prelink_undo", 582 ".gnu.prelink_undo",
561 NULL) != NULL); 583 NULL) != NULL);
584 } else self->adjust_symbols = 0;
585
562 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 586 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
563 struct symbol *f; 587 struct symbol *f;
588 const char *name;
589 char *demangled;
564 u64 obj_start; 590 u64 obj_start;
565 struct section *section = NULL; 591 struct section *section = NULL;
566 int is_label = elf_sym__is_label(&sym); 592 int is_label = elf_sym__is_label(&sym);
@@ -599,10 +625,19 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
599 goto out_elf_end; 625 goto out_elf_end;
600 } 626 }
601 } 627 }
628 /*
629 * We need to figure out if the object was created from C++ sources
630 * DWARF DW_compile_unit has this, but we don't always have access
631 * to it...
632 */
633 name = elf_sym__name(&sym, symstrs);
634 demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI);
635 if (demangled != NULL)
636 name = demangled;
602 637
603 f = symbol__new(sym.st_value, sym.st_size, 638 f = symbol__new(sym.st_value, sym.st_size, name,
604 elf_sym__name(&sym, symstrs),
605 self->sym_priv_size, obj_start, verbose); 639 self->sym_priv_size, obj_start, verbose);
640 free(demangled);
606 if (!f) 641 if (!f)
607 goto out_elf_end; 642 goto out_elf_end;
608 643
@@ -622,11 +657,85 @@ out_close:
622 return err; 657 return err;
623} 658}
624 659
660#define BUILD_ID_SIZE 128
661
662static char *dso__read_build_id(struct dso *self, int verbose)
663{
664 int i;
665 GElf_Ehdr ehdr;
666 GElf_Shdr shdr;
667 Elf_Data *build_id_data;
668 Elf_Scn *sec;
669 char *build_id = NULL, *bid;
670 unsigned char *raw;
671 Elf *elf;
672 int fd = open(self->name, O_RDONLY);
673
674 if (fd < 0)
675 goto out;
676
677 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
678 if (elf == NULL) {
679 if (verbose)
680 fprintf(stderr, "%s: cannot read %s ELF file.\n",
681 __func__, self->name);
682 goto out_close;
683 }
684
685 if (gelf_getehdr(elf, &ehdr) == NULL) {
686 if (verbose)
687 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
688 goto out_elf_end;
689 }
690
691 sec = elf_section_by_name(elf, &ehdr, &shdr, ".note.gnu.build-id", NULL);
692 if (sec == NULL)
693 goto out_elf_end;
694
695 build_id_data = elf_getdata(sec, NULL);
696 if (build_id_data == NULL)
697 goto out_elf_end;
698 build_id = malloc(BUILD_ID_SIZE);
699 if (build_id == NULL)
700 goto out_elf_end;
701 raw = build_id_data->d_buf + 16;
702 bid = build_id;
703
704 for (i = 0; i < 20; ++i) {
705 sprintf(bid, "%02x", *raw);
706 ++raw;
707 bid += 2;
708 }
709 if (verbose >= 2)
710 printf("%s(%s): %s\n", __func__, self->name, build_id);
711out_elf_end:
712 elf_end(elf);
713out_close:
714 close(fd);
715out:
716 return build_id;
717}
718
719char dso__symtab_origin(const struct dso *self)
720{
721 static const char origin[] = {
722 [DSO__ORIG_KERNEL] = 'k',
723 [DSO__ORIG_JAVA_JIT] = 'j',
724 [DSO__ORIG_FEDORA] = 'f',
725 [DSO__ORIG_UBUNTU] = 'u',
726 [DSO__ORIG_BUILDID] = 'b',
727 [DSO__ORIG_DSO] = 'd',
728 };
729
730 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
731 return '!';
732 return origin[self->origin];
733}
734
625int dso__load(struct dso *self, symbol_filter_t filter, int verbose) 735int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
626{ 736{
627 int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug"); 737 int size = PATH_MAX;
628 char *name = malloc(size); 738 char *name = malloc(size), *build_id = NULL;
629 int variant = 0;
630 int ret = -1; 739 int ret = -1;
631 int fd; 740 int fd;
632 741
@@ -635,26 +744,43 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
635 744
636 self->adjust_symbols = 0; 745 self->adjust_symbols = 0;
637 746
638 if (strncmp(self->name, "/tmp/perf-", 10) == 0) 747 if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
639 return dso__load_perf_map(self, filter, verbose); 748 ret = dso__load_perf_map(self, filter, verbose);
749 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
750 DSO__ORIG_NOT_FOUND;
751 return ret;
752 }
753
754 self->origin = DSO__ORIG_FEDORA - 1;
640 755
641more: 756more:
642 do { 757 do {
643 switch (variant) { 758 self->origin++;
644 case 0: /* Fedora */ 759 switch (self->origin) {
760 case DSO__ORIG_FEDORA:
645 snprintf(name, size, "/usr/lib/debug%s.debug", self->name); 761 snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
646 break; 762 break;
647 case 1: /* Ubuntu */ 763 case DSO__ORIG_UBUNTU:
648 snprintf(name, size, "/usr/lib/debug%s", self->name); 764 snprintf(name, size, "/usr/lib/debug%s", self->name);
649 break; 765 break;
650 case 2: /* Sane people */ 766 case DSO__ORIG_BUILDID:
767 build_id = dso__read_build_id(self, verbose);
768 if (build_id != NULL) {
769 snprintf(name, size,
770 "/usr/lib/debug/.build-id/%.2s/%s.debug",
771 build_id, build_id + 2);
772 free(build_id);
773 break;
774 }
775 self->origin++;
776 /* Fall thru */
777 case DSO__ORIG_DSO:
651 snprintf(name, size, "%s", self->name); 778 snprintf(name, size, "%s", self->name);
652 break; 779 break;
653 780
654 default: 781 default:
655 goto out; 782 goto out;
656 } 783 }
657 variant++;
658 784
659 fd = open(name, O_RDONLY); 785 fd = open(name, O_RDONLY);
660 } while (fd < 0); 786 } while (fd < 0);
@@ -668,8 +794,15 @@ more:
668 if (!ret) 794 if (!ret)
669 goto more; 795 goto more;
670 796
797 if (ret > 0) {
798 int nr_plt = dso__synthesize_plt_symbols(self, verbose);
799 if (nr_plt > 0)
800 ret += nr_plt;
801 }
671out: 802out:
672 free(name); 803 free(name);
804 if (ret < 0 && strstr(self->name, " (deleted)") != NULL)
805 return 0;
673 return ret; 806 return ret;
674} 807}
675 808
@@ -785,6 +918,9 @@ int dso__load_kernel(struct dso *self, const char *vmlinux,
785 if (err <= 0) 918 if (err <= 0)
786 err = dso__load_kallsyms(self, filter, verbose); 919 err = dso__load_kallsyms(self, filter, verbose);
787 920
921 if (err > 0)
922 self->origin = DSO__ORIG_KERNEL;
923
788 return err; 924 return err;
789} 925}
790 926