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.c133
1 files changed, 117 insertions, 16 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 28106059bf12..5c0f42e6b33b 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -6,14 +6,18 @@
6#include <libelf.h> 6#include <libelf.h>
7#include <gelf.h> 7#include <gelf.h>
8#include <elf.h> 8#include <elf.h>
9#include <bfd.h>
10 9
11const char *sym_hist_filter; 10const char *sym_hist_filter;
12 11
13#ifndef DMGL_PARAMS 12enum dso_origin {
14#define DMGL_PARAMS (1 << 0) /* Include function args */ 13 DSO__ORIG_KERNEL = 0,
15#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ 14 DSO__ORIG_JAVA_JIT,
16#endif 15 DSO__ORIG_FEDORA,
16 DSO__ORIG_UBUNTU,
17 DSO__ORIG_BUILDID,
18 DSO__ORIG_DSO,
19 DSO__ORIG_NOT_FOUND,
20};
17 21
18static struct symbol *symbol__new(u64 start, u64 len, 22static struct symbol *symbol__new(u64 start, u64 len,
19 const char *name, unsigned int priv_size, 23 const char *name, unsigned int priv_size,
@@ -72,6 +76,7 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
72 self->sym_priv_size = sym_priv_size; 76 self->sym_priv_size = sym_priv_size;
73 self->find_symbol = dso__find_symbol; 77 self->find_symbol = dso__find_symbol;
74 self->slen_calculated = 0; 78 self->slen_calculated = 0;
79 self->origin = DSO__ORIG_NOT_FOUND;
75 } 80 }
76 81
77 return self; 82 return self;
@@ -565,7 +570,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
565 goto out_elf_end; 570 goto out_elf_end;
566 571
567 secstrs = elf_getdata(sec_strndx, NULL); 572 secstrs = elf_getdata(sec_strndx, NULL);
568 if (symstrs == NULL) 573 if (secstrs == NULL)
569 goto out_elf_end; 574 goto out_elf_end;
570 575
571 nr_syms = shdr.sh_size / shdr.sh_entsize; 576 nr_syms = shdr.sh_size / shdr.sh_entsize;
@@ -652,11 +657,85 @@ out_close:
652 return err; 657 return err;
653} 658}
654 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
655int dso__load(struct dso *self, symbol_filter_t filter, int verbose) 735int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
656{ 736{
657 int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug"); 737 int size = PATH_MAX;
658 char *name = malloc(size); 738 char *name = malloc(size), *build_id = NULL;
659 int variant = 0;
660 int ret = -1; 739 int ret = -1;
661 int fd; 740 int fd;
662 741
@@ -665,26 +744,43 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
665 744
666 self->adjust_symbols = 0; 745 self->adjust_symbols = 0;
667 746
668 if (strncmp(self->name, "/tmp/perf-", 10) == 0) 747 if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
669 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;
670 755
671more: 756more:
672 do { 757 do {
673 switch (variant) { 758 self->origin++;
674 case 0: /* Fedora */ 759 switch (self->origin) {
760 case DSO__ORIG_FEDORA:
675 snprintf(name, size, "/usr/lib/debug%s.debug", self->name); 761 snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
676 break; 762 break;
677 case 1: /* Ubuntu */ 763 case DSO__ORIG_UBUNTU:
678 snprintf(name, size, "/usr/lib/debug%s", self->name); 764 snprintf(name, size, "/usr/lib/debug%s", self->name);
679 break; 765 break;
680 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:
681 snprintf(name, size, "%s", self->name); 778 snprintf(name, size, "%s", self->name);
682 break; 779 break;
683 780
684 default: 781 default:
685 goto out; 782 goto out;
686 } 783 }
687 variant++;
688 784
689 fd = open(name, O_RDONLY); 785 fd = open(name, O_RDONLY);
690 } while (fd < 0); 786 } while (fd < 0);
@@ -705,6 +801,8 @@ more:
705 } 801 }
706out: 802out:
707 free(name); 803 free(name);
804 if (ret < 0 && strstr(self->name, " (deleted)") != NULL)
805 return 0;
708 return ret; 806 return ret;
709} 807}
710 808
@@ -820,6 +918,9 @@ int dso__load_kernel(struct dso *self, const char *vmlinux,
820 if (err <= 0) 918 if (err <= 0)
821 err = dso__load_kallsyms(self, filter, verbose); 919 err = dso__load_kallsyms(self, filter, verbose);
822 920
921 if (err > 0)
922 self->origin = DSO__ORIG_KERNEL;
923
823 return err; 924 return err;
824} 925}
825 926