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.c96
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
968static int dso__load_sym(struct dso *self, struct map *map, const char *name, 968static 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
1397more: 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 }
1436open_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 }
1454out: 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)