diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 78 |
1 files changed, 56 insertions, 22 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e7c7cdb851c2..a2e95ce1f223 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -121,7 +121,8 @@ struct dso *dso__new(const char *name) | |||
121 | self->find_symbol = dso__find_symbol; | 121 | self->find_symbol = dso__find_symbol; |
122 | self->slen_calculated = 0; | 122 | self->slen_calculated = 0; |
123 | self->origin = DSO__ORIG_NOT_FOUND; | 123 | self->origin = DSO__ORIG_NOT_FOUND; |
124 | self->loaded = false; | 124 | self->loaded = 0; |
125 | self->has_build_id = 0; | ||
125 | } | 126 | } |
126 | 127 | ||
127 | return self; | 128 | return self; |
@@ -148,6 +149,12 @@ void dso__delete(struct dso *self) | |||
148 | free(self); | 149 | free(self); |
149 | } | 150 | } |
150 | 151 | ||
152 | void dso__set_build_id(struct dso *self, void *build_id) | ||
153 | { | ||
154 | memcpy(self->build_id, build_id, sizeof(self->build_id)); | ||
155 | self->has_build_id = 1; | ||
156 | } | ||
157 | |||
151 | static void dso__insert_symbol(struct dso *self, struct symbol *sym) | 158 | static void dso__insert_symbol(struct dso *self, struct symbol *sym) |
152 | { | 159 | { |
153 | struct rb_node **p = &self->syms.rb_node; | 160 | struct rb_node **p = &self->syms.rb_node; |
@@ -190,11 +197,30 @@ struct symbol *dso__find_symbol(struct dso *self, u64 ip) | |||
190 | return NULL; | 197 | return NULL; |
191 | } | 198 | } |
192 | 199 | ||
193 | size_t dso__fprintf(struct dso *self, FILE *fp) | 200 | int build_id__sprintf(u8 *self, int len, char *bf) |
194 | { | 201 | { |
195 | size_t ret = fprintf(fp, "dso: %s\n", self->short_name); | 202 | char *bid = bf; |
203 | u8 *raw = self; | ||
204 | int i; | ||
196 | 205 | ||
206 | for (i = 0; i < len; ++i) { | ||
207 | sprintf(bid, "%02x", *raw); | ||
208 | ++raw; | ||
209 | bid += 2; | ||
210 | } | ||
211 | |||
212 | return raw - self; | ||
213 | } | ||
214 | |||
215 | size_t dso__fprintf(struct dso *self, FILE *fp) | ||
216 | { | ||
217 | char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | ||
197 | struct rb_node *nd; | 218 | struct rb_node *nd; |
219 | size_t ret; | ||
220 | |||
221 | build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id); | ||
222 | ret = fprintf(fp, "dso: %s (%s)\n", self->short_name, sbuild_id); | ||
223 | |||
198 | for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) { | 224 | for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) { |
199 | struct symbol *pos = rb_entry(nd, struct symbol, rb_node); | 225 | struct symbol *pos = rb_entry(nd, struct symbol, rb_node); |
200 | ret += symbol__fprintf(pos, fp); | 226 | ret += symbol__fprintf(pos, fp); |
@@ -825,8 +851,6 @@ out_close: | |||
825 | return err; | 851 | return err; |
826 | } | 852 | } |
827 | 853 | ||
828 | #define BUILD_ID_SIZE 20 | ||
829 | |||
830 | int filename__read_build_id(const char *filename, void *bf, size_t size) | 854 | int filename__read_build_id(const char *filename, void *bf, size_t size) |
831 | { | 855 | { |
832 | int fd, err = -1; | 856 | int fd, err = -1; |
@@ -845,7 +869,7 @@ int filename__read_build_id(const char *filename, void *bf, size_t size) | |||
845 | 869 | ||
846 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | 870 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); |
847 | if (elf == NULL) { | 871 | if (elf == NULL) { |
848 | pr_err("%s: cannot read %s ELF file.\n", __func__, filename); | 872 | pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename); |
849 | goto out_close; | 873 | goto out_close; |
850 | } | 874 | } |
851 | 875 | ||
@@ -874,9 +898,9 @@ out: | |||
874 | 898 | ||
875 | static char *dso__read_build_id(struct dso *self) | 899 | static char *dso__read_build_id(struct dso *self) |
876 | { | 900 | { |
877 | int i, len; | 901 | int len; |
878 | char *build_id = NULL, *bid; | 902 | char *build_id = NULL; |
879 | unsigned char rawbf[BUILD_ID_SIZE], *raw; | 903 | unsigned char rawbf[BUILD_ID_SIZE]; |
880 | 904 | ||
881 | len = filename__read_build_id(self->long_name, rawbf, sizeof(rawbf)); | 905 | len = filename__read_build_id(self->long_name, rawbf, sizeof(rawbf)); |
882 | if (len < 0) | 906 | if (len < 0) |
@@ -885,15 +909,8 @@ static char *dso__read_build_id(struct dso *self) | |||
885 | build_id = malloc(len * 2 + 1); | 909 | build_id = malloc(len * 2 + 1); |
886 | if (build_id == NULL) | 910 | if (build_id == NULL) |
887 | goto out; | 911 | goto out; |
888 | bid = build_id; | ||
889 | 912 | ||
890 | raw = rawbf; | 913 | build_id__sprintf(rawbf, len, build_id); |
891 | for (i = 0; i < len; ++i) { | ||
892 | sprintf(bid, "%02x", *raw); | ||
893 | ++raw; | ||
894 | bid += 2; | ||
895 | } | ||
896 | pr_debug2("%s(%s): %s\n", __func__, self->long_name, build_id); | ||
897 | out: | 914 | out: |
898 | return build_id; | 915 | return build_id; |
899 | } | 916 | } |
@@ -922,7 +939,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
922 | int ret = -1; | 939 | int ret = -1; |
923 | int fd; | 940 | int fd; |
924 | 941 | ||
925 | self->loaded = true; | 942 | self->loaded = 1; |
926 | 943 | ||
927 | if (!name) | 944 | if (!name) |
928 | return -1; | 945 | return -1; |
@@ -940,6 +957,8 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
940 | 957 | ||
941 | more: | 958 | more: |
942 | do { | 959 | do { |
960 | int berr = 0; | ||
961 | |||
943 | self->origin++; | 962 | self->origin++; |
944 | switch (self->origin) { | 963 | switch (self->origin) { |
945 | case DSO__ORIG_FEDORA: | 964 | case DSO__ORIG_FEDORA: |
@@ -956,8 +975,7 @@ more: | |||
956 | snprintf(name, size, | 975 | snprintf(name, size, |
957 | "/usr/lib/debug/.build-id/%.2s/%s.debug", | 976 | "/usr/lib/debug/.build-id/%.2s/%s.debug", |
958 | build_id, build_id + 2); | 977 | build_id, build_id + 2); |
959 | free(build_id); | 978 | goto compare_build_id; |
960 | break; | ||
961 | } | 979 | } |
962 | self->origin++; | 980 | self->origin++; |
963 | /* Fall thru */ | 981 | /* Fall thru */ |
@@ -969,6 +987,22 @@ more: | |||
969 | goto out; | 987 | goto out; |
970 | } | 988 | } |
971 | 989 | ||
990 | if (self->has_build_id) { | ||
991 | bool match; | ||
992 | build_id = malloc(BUILD_ID_SIZE); | ||
993 | if (build_id == NULL) | ||
994 | goto more; | ||
995 | berr = filename__read_build_id(name, build_id, | ||
996 | BUILD_ID_SIZE); | ||
997 | compare_build_id: | ||
998 | match = berr > 0 && memcmp(build_id, self->build_id, | ||
999 | sizeof(self->build_id)) == 0; | ||
1000 | free(build_id); | ||
1001 | build_id = NULL; | ||
1002 | if (!match) | ||
1003 | goto more; | ||
1004 | } | ||
1005 | |||
972 | fd = open(name, O_RDONLY); | 1006 | fd = open(name, O_RDONLY); |
973 | } while (fd < 0); | 1007 | } while (fd < 0); |
974 | 1008 | ||
@@ -1034,7 +1068,7 @@ static int dso__load_module_sym(struct dso *self, struct map *map, | |||
1034 | { | 1068 | { |
1035 | int err = 0, fd = open(self->long_name, O_RDONLY); | 1069 | int err = 0, fd = open(self->long_name, O_RDONLY); |
1036 | 1070 | ||
1037 | self->loaded = true; | 1071 | self->loaded = 1; |
1038 | 1072 | ||
1039 | if (fd < 0) { | 1073 | if (fd < 0) { |
1040 | pr_err("%s: cannot open %s\n", __func__, self->long_name); | 1074 | pr_err("%s: cannot open %s\n", __func__, self->long_name); |
@@ -1225,7 +1259,7 @@ static int dso__load_vmlinux(struct dso *self, struct map *map, | |||
1225 | { | 1259 | { |
1226 | int err, fd = open(vmlinux, O_RDONLY); | 1260 | int err, fd = open(vmlinux, O_RDONLY); |
1227 | 1261 | ||
1228 | self->loaded = true; | 1262 | self->loaded = 1; |
1229 | 1263 | ||
1230 | if (fd < 0) | 1264 | if (fd < 0) |
1231 | return -1; | 1265 | return -1; |