diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 96 |
1 files changed, 61 insertions, 35 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e0d9480dc371..d99497ec52aa 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -966,7 +966,8 @@ static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr) | |||
966 | } | 966 | } |
967 | 967 | ||
968 | static int dso__load_sym(struct dso *self, struct map *map, const char *name, | 968 | static int dso__load_sym(struct dso *self, struct map *map, const char *name, |
969 | int fd, symbol_filter_t filter, int kmodule) | 969 | int fd, symbol_filter_t filter, int kmodule, |
970 | int want_symtab) | ||
970 | { | 971 | { |
971 | struct kmap *kmap = self->kernel ? map__kmap(map) : NULL; | 972 | struct kmap *kmap = self->kernel ? map__kmap(map) : NULL; |
972 | struct map *curr_map = map; | 973 | struct map *curr_map = map; |
@@ -995,6 +996,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
995 | goto out_elf_end; | 996 | goto out_elf_end; |
996 | } | 997 | } |
997 | 998 | ||
999 | /* Always reject images with a mismatched build-id: */ | ||
998 | if (self->has_build_id) { | 1000 | if (self->has_build_id) { |
999 | u8 build_id[BUILD_ID_SIZE]; | 1001 | u8 build_id[BUILD_ID_SIZE]; |
1000 | 1002 | ||
@@ -1008,6 +1010,9 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
1008 | 1010 | ||
1009 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); | 1011 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); |
1010 | if (sec == NULL) { | 1012 | if (sec == NULL) { |
1013 | if (want_symtab) | ||
1014 | goto out_elf_end; | ||
1015 | |||
1011 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); | 1016 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); |
1012 | if (sec == NULL) | 1017 | if (sec == NULL) |
1013 | goto out_elf_end; | 1018 | goto out_elf_end; |
@@ -1365,6 +1370,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1365 | int fd; | 1370 | int fd; |
1366 | struct machine *machine; | 1371 | struct machine *machine; |
1367 | const char *root_dir; | 1372 | const char *root_dir; |
1373 | int want_symtab; | ||
1368 | 1374 | ||
1369 | dso__set_loaded(self, map->type); | 1375 | dso__set_loaded(self, map->type); |
1370 | 1376 | ||
@@ -1391,13 +1397,18 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1391 | return ret; | 1397 | return ret; |
1392 | } | 1398 | } |
1393 | 1399 | ||
1394 | self->origin = DSO__ORIG_BUILD_ID_CACHE; | 1400 | /* Iterate over candidate debug images. |
1395 | if (dso__build_id_filename(self, name, size) != NULL) | 1401 | * On the first pass, only load images if they have a full symtab. |
1396 | goto open_file; | 1402 | * Failing that, do a second pass where we accept .dynsym also |
1397 | more: | 1403 | */ |
1398 | do { | 1404 | for (self->origin = DSO__ORIG_BUILD_ID_CACHE, want_symtab = 1; |
1399 | self->origin++; | 1405 | self->origin != DSO__ORIG_NOT_FOUND; |
1406 | self->origin++) { | ||
1400 | switch (self->origin) { | 1407 | switch (self->origin) { |
1408 | case DSO__ORIG_BUILD_ID_CACHE: | ||
1409 | if (dso__build_id_filename(self, name, size) == NULL) | ||
1410 | continue; | ||
1411 | break; | ||
1401 | case DSO__ORIG_FEDORA: | 1412 | case DSO__ORIG_FEDORA: |
1402 | snprintf(name, size, "/usr/lib/debug%s.debug", | 1413 | snprintf(name, size, "/usr/lib/debug%s.debug", |
1403 | self->long_name); | 1414 | self->long_name); |
@@ -1406,19 +1417,20 @@ more: | |||
1406 | snprintf(name, size, "/usr/lib/debug%s", | 1417 | snprintf(name, size, "/usr/lib/debug%s", |
1407 | self->long_name); | 1418 | self->long_name); |
1408 | break; | 1419 | break; |
1409 | case DSO__ORIG_BUILDID: | 1420 | case DSO__ORIG_BUILDID: { |
1410 | if (self->has_build_id) { | 1421 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; |
1411 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; | 1422 | |
1412 | build_id__sprintf(self->build_id, | 1423 | if (!self->has_build_id) |
1413 | sizeof(self->build_id), | 1424 | continue; |
1414 | build_id_hex); | 1425 | |
1415 | snprintf(name, size, | 1426 | build_id__sprintf(self->build_id, |
1416 | "/usr/lib/debug/.build-id/%.2s/%s.debug", | 1427 | sizeof(self->build_id), |
1417 | build_id_hex, build_id_hex + 2); | 1428 | build_id_hex); |
1418 | break; | 1429 | snprintf(name, size, |
1430 | "/usr/lib/debug/.build-id/%.2s/%s.debug", | ||
1431 | build_id_hex, build_id_hex + 2); | ||
1419 | } | 1432 | } |
1420 | self->origin++; | 1433 | break; |
1421 | /* Fall thru */ | ||
1422 | case DSO__ORIG_DSO: | 1434 | case DSO__ORIG_DSO: |
1423 | snprintf(name, size, "%s", self->long_name); | 1435 | snprintf(name, size, "%s", self->long_name); |
1424 | break; | 1436 | break; |
@@ -1431,27 +1443,41 @@ more: | |||
1431 | break; | 1443 | break; |
1432 | 1444 | ||
1433 | default: | 1445 | default: |
1434 | goto out; | 1446 | /* |
1447 | * If we wanted a full symtab but no image had one, | ||
1448 | * relax our requirements and repeat the search. | ||
1449 | */ | ||
1450 | if (want_symtab) { | ||
1451 | want_symtab = 0; | ||
1452 | self->origin = DSO__ORIG_BUILD_ID_CACHE; | ||
1453 | } else | ||
1454 | continue; | ||
1435 | } | 1455 | } |
1436 | open_file: | 1456 | |
1457 | /* Name is now the name of the next image to try */ | ||
1437 | fd = open(name, O_RDONLY); | 1458 | fd = open(name, O_RDONLY); |
1438 | } while (fd < 0); | 1459 | if (fd < 0) |
1460 | continue; | ||
1439 | 1461 | ||
1440 | ret = dso__load_sym(self, map, name, fd, filter, 0); | 1462 | ret = dso__load_sym(self, map, name, fd, filter, 0, |
1441 | close(fd); | 1463 | want_symtab); |
1464 | close(fd); | ||
1442 | 1465 | ||
1443 | /* | 1466 | /* |
1444 | * Some people seem to have debuginfo files _WITHOUT_ debug info!?!? | 1467 | * Some people seem to have debuginfo files _WITHOUT_ debug |
1445 | */ | 1468 | * info!?!? |
1446 | if (!ret) | 1469 | */ |
1447 | goto more; | 1470 | if (!ret) |
1471 | continue; | ||
1448 | 1472 | ||
1449 | if (ret > 0) { | 1473 | if (ret > 0) { |
1450 | int nr_plt = dso__synthesize_plt_symbols(self, map, filter); | 1474 | int nr_plt = dso__synthesize_plt_symbols(self, map, filter); |
1451 | if (nr_plt > 0) | 1475 | if (nr_plt > 0) |
1452 | ret += nr_plt; | 1476 | ret += nr_plt; |
1477 | break; | ||
1478 | } | ||
1453 | } | 1479 | } |
1454 | out: | 1480 | |
1455 | free(name); | 1481 | free(name); |
1456 | if (ret < 0 && strstr(self->name, " (deleted)") != NULL) | 1482 | if (ret < 0 && strstr(self->name, " (deleted)") != NULL) |
1457 | return 0; | 1483 | return 0; |
@@ -1715,7 +1741,7 @@ static int dso__load_vmlinux(struct dso *self, struct map *map, | |||
1715 | return -1; | 1741 | return -1; |
1716 | 1742 | ||
1717 | dso__set_loaded(self, map->type); | 1743 | dso__set_loaded(self, map->type); |
1718 | err = dso__load_sym(self, map, vmlinux, fd, filter, 0); | 1744 | err = dso__load_sym(self, map, vmlinux, fd, filter, 0, 0); |
1719 | close(fd); | 1745 | close(fd); |
1720 | 1746 | ||
1721 | if (err > 0) | 1747 | if (err > 0) |