aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorDave Martin <dave.martin@linaro.org>2010-07-30 08:50:09 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-07-30 08:54:49 -0400
commit6da80ce8c43ddda153208cbb46b75290cf566fac (patch)
tree6a242c17ccbfacb237c4552a22593bd67b786b1b /tools/perf
parent8b1389ef93b36621c6acdeb623bd85aee3c405c9 (diff)
perf symbols: Improve debug image search when loading symbols
Changes: * Simplification of the main search loop on dso__load() * Replace the search with a 2-pass search: * First, try to find an image with a proper symtab. * Second, repeat the search, accepting dynsym. A second scan should only ever happen when needed debug images are missing from the buildid cache or stale, i.e., when the cache is out of sync. Currently, the second scan also happens when using separated debug images, since the caching logic doesn't currently know how to cache those. Improvements to the cache behaviour ought to solve that. Signed-off-by: Dave Martin <dave.martin@linaro.org> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-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)