diff options
| -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) |
