diff options
-rw-r--r-- | tools/perf/util/symbol.c | 80 |
1 files changed, 47 insertions, 33 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 242d2b216f46..b812ace91c60 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #define NT_GNU_BUILD_ID 3 | 26 | #define NT_GNU_BUILD_ID 3 |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | static bool dso__build_id_equal(const struct dso *self, u8 *build_id); | ||
30 | static int elf_read_build_id(Elf *elf, void *bf, size_t size); | ||
29 | static void dsos__add(struct list_head *head, struct dso *dso); | 31 | static void dsos__add(struct list_head *head, struct dso *dso); |
30 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); | 32 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); |
31 | static int dso__load_kernel_sym(struct dso *self, struct map *map, | 33 | static int dso__load_kernel_sym(struct dso *self, struct map *map, |
@@ -993,6 +995,17 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
993 | goto out_elf_end; | 995 | goto out_elf_end; |
994 | } | 996 | } |
995 | 997 | ||
998 | if (self->has_build_id) { | ||
999 | u8 build_id[BUILD_ID_SIZE]; | ||
1000 | |||
1001 | if (elf_read_build_id(elf, build_id, | ||
1002 | BUILD_ID_SIZE) != BUILD_ID_SIZE) | ||
1003 | goto out_elf_end; | ||
1004 | |||
1005 | if (!dso__build_id_equal(self, build_id)) | ||
1006 | goto out_elf_end; | ||
1007 | } | ||
1008 | |||
996 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); | 1009 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); |
997 | if (sec == NULL) { | 1010 | if (sec == NULL) { |
998 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); | 1011 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); |
@@ -1193,37 +1206,26 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits) | |||
1193 | */ | 1206 | */ |
1194 | #define NOTE_ALIGN(n) (((n) + 3) & -4U) | 1207 | #define NOTE_ALIGN(n) (((n) + 3) & -4U) |
1195 | 1208 | ||
1196 | int filename__read_build_id(const char *filename, void *bf, size_t size) | 1209 | static int elf_read_build_id(Elf *elf, void *bf, size_t size) |
1197 | { | 1210 | { |
1198 | int fd, err = -1; | 1211 | int err = -1; |
1199 | GElf_Ehdr ehdr; | 1212 | GElf_Ehdr ehdr; |
1200 | GElf_Shdr shdr; | 1213 | GElf_Shdr shdr; |
1201 | Elf_Data *data; | 1214 | Elf_Data *data; |
1202 | Elf_Scn *sec; | 1215 | Elf_Scn *sec; |
1203 | Elf_Kind ek; | 1216 | Elf_Kind ek; |
1204 | void *ptr; | 1217 | void *ptr; |
1205 | Elf *elf; | ||
1206 | 1218 | ||
1207 | if (size < BUILD_ID_SIZE) | 1219 | if (size < BUILD_ID_SIZE) |
1208 | goto out; | 1220 | goto out; |
1209 | 1221 | ||
1210 | fd = open(filename, O_RDONLY); | ||
1211 | if (fd < 0) | ||
1212 | goto out; | ||
1213 | |||
1214 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
1215 | if (elf == NULL) { | ||
1216 | pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename); | ||
1217 | goto out_close; | ||
1218 | } | ||
1219 | |||
1220 | ek = elf_kind(elf); | 1222 | ek = elf_kind(elf); |
1221 | if (ek != ELF_K_ELF) | 1223 | if (ek != ELF_K_ELF) |
1222 | goto out_elf_end; | 1224 | goto out; |
1223 | 1225 | ||
1224 | if (gelf_getehdr(elf, &ehdr) == NULL) { | 1226 | if (gelf_getehdr(elf, &ehdr) == NULL) { |
1225 | pr_err("%s: cannot get elf header.\n", __func__); | 1227 | pr_err("%s: cannot get elf header.\n", __func__); |
1226 | goto out_elf_end; | 1228 | goto out; |
1227 | } | 1229 | } |
1228 | 1230 | ||
1229 | sec = elf_section_by_name(elf, &ehdr, &shdr, | 1231 | sec = elf_section_by_name(elf, &ehdr, &shdr, |
@@ -1232,12 +1234,12 @@ int filename__read_build_id(const char *filename, void *bf, size_t size) | |||
1232 | sec = elf_section_by_name(elf, &ehdr, &shdr, | 1234 | sec = elf_section_by_name(elf, &ehdr, &shdr, |
1233 | ".notes", NULL); | 1235 | ".notes", NULL); |
1234 | if (sec == NULL) | 1236 | if (sec == NULL) |
1235 | goto out_elf_end; | 1237 | goto out; |
1236 | } | 1238 | } |
1237 | 1239 | ||
1238 | data = elf_getdata(sec, NULL); | 1240 | data = elf_getdata(sec, NULL); |
1239 | if (data == NULL) | 1241 | if (data == NULL) |
1240 | goto out_elf_end; | 1242 | goto out; |
1241 | 1243 | ||
1242 | ptr = data->d_buf; | 1244 | ptr = data->d_buf; |
1243 | while (ptr < (data->d_buf + data->d_size)) { | 1245 | while (ptr < (data->d_buf + data->d_size)) { |
@@ -1259,7 +1261,31 @@ int filename__read_build_id(const char *filename, void *bf, size_t size) | |||
1259 | } | 1261 | } |
1260 | ptr += descsz; | 1262 | ptr += descsz; |
1261 | } | 1263 | } |
1262 | out_elf_end: | 1264 | |
1265 | out: | ||
1266 | return err; | ||
1267 | } | ||
1268 | |||
1269 | int filename__read_build_id(const char *filename, void *bf, size_t size) | ||
1270 | { | ||
1271 | int fd, err = -1; | ||
1272 | Elf *elf; | ||
1273 | |||
1274 | if (size < BUILD_ID_SIZE) | ||
1275 | goto out; | ||
1276 | |||
1277 | fd = open(filename, O_RDONLY); | ||
1278 | if (fd < 0) | ||
1279 | goto out; | ||
1280 | |||
1281 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
1282 | if (elf == NULL) { | ||
1283 | pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename); | ||
1284 | goto out_close; | ||
1285 | } | ||
1286 | |||
1287 | err = elf_read_build_id(elf, bf, size); | ||
1288 | |||
1263 | elf_end(elf); | 1289 | elf_end(elf); |
1264 | out_close: | 1290 | out_close: |
1265 | close(fd); | 1291 | close(fd); |
@@ -1335,7 +1361,6 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1335 | { | 1361 | { |
1336 | int size = PATH_MAX; | 1362 | int size = PATH_MAX; |
1337 | char *name; | 1363 | char *name; |
1338 | u8 build_id[BUILD_ID_SIZE]; | ||
1339 | int ret = -1; | 1364 | int ret = -1; |
1340 | int fd; | 1365 | int fd; |
1341 | struct machine *machine; | 1366 | struct machine *machine; |
@@ -1382,16 +1407,14 @@ more: | |||
1382 | self->long_name); | 1407 | self->long_name); |
1383 | break; | 1408 | break; |
1384 | case DSO__ORIG_BUILDID: | 1409 | case DSO__ORIG_BUILDID: |
1385 | if (filename__read_build_id(self->long_name, build_id, | 1410 | if (self->has_build_id) { |
1386 | sizeof(build_id))) { | ||
1387 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; | 1411 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; |
1388 | build_id__sprintf(build_id, sizeof(build_id), | 1412 | build_id__sprintf(self->build_id, |
1413 | sizeof(self->build_id), | ||
1389 | build_id_hex); | 1414 | build_id_hex); |
1390 | snprintf(name, size, | 1415 | snprintf(name, size, |
1391 | "/usr/lib/debug/.build-id/%.2s/%s.debug", | 1416 | "/usr/lib/debug/.build-id/%.2s/%s.debug", |
1392 | build_id_hex, build_id_hex + 2); | 1417 | build_id_hex, build_id_hex + 2); |
1393 | if (self->has_build_id) | ||
1394 | goto compare_build_id; | ||
1395 | break; | 1418 | break; |
1396 | } | 1419 | } |
1397 | self->origin++; | 1420 | self->origin++; |
@@ -1410,15 +1433,6 @@ more: | |||
1410 | default: | 1433 | default: |
1411 | goto out; | 1434 | goto out; |
1412 | } | 1435 | } |
1413 | |||
1414 | if (self->has_build_id) { | ||
1415 | if (filename__read_build_id(name, build_id, | ||
1416 | sizeof(build_id)) < 0) | ||
1417 | goto more; | ||
1418 | compare_build_id: | ||
1419 | if (!dso__build_id_equal(self, build_id)) | ||
1420 | goto more; | ||
1421 | } | ||
1422 | open_file: | 1436 | open_file: |
1423 | fd = open(name, O_RDONLY); | 1437 | fd = open(name, O_RDONLY); |
1424 | } while (fd < 0); | 1438 | } while (fd < 0); |