Skip to content

Commit

Permalink
perf symbols: Improve debug image search when loading symbols
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dave Martin authored and Arnaldo Carvalho de Melo committed Jul 30, 2010
1 parent 8b1389e commit 6da80ce
Showing 1 changed file with 61 additions and 35 deletions.
96 changes: 61 additions & 35 deletions tools/perf/util/symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,8 @@ static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
}

static int dso__load_sym(struct dso *self, struct map *map, const char *name,
int fd, symbol_filter_t filter, int kmodule)
int fd, symbol_filter_t filter, int kmodule,
int want_symtab)
{
struct kmap *kmap = self->kernel ? map__kmap(map) : NULL;
struct map *curr_map = map;
Expand Down Expand Up @@ -995,6 +996,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
goto out_elf_end;
}

/* Always reject images with a mismatched build-id: */
if (self->has_build_id) {
u8 build_id[BUILD_ID_SIZE];

Expand All @@ -1008,6 +1010,9 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,

sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
if (sec == NULL) {
if (want_symtab)
goto out_elf_end;

sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
if (sec == NULL)
goto out_elf_end;
Expand Down Expand Up @@ -1365,6 +1370,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
int fd;
struct machine *machine;
const char *root_dir;
int want_symtab;

dso__set_loaded(self, map->type);

Expand All @@ -1391,13 +1397,18 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
return ret;
}

self->origin = DSO__ORIG_BUILD_ID_CACHE;
if (dso__build_id_filename(self, name, size) != NULL)
goto open_file;
more:
do {
self->origin++;
/* Iterate over candidate debug images.
* On the first pass, only load images if they have a full symtab.
* Failing that, do a second pass where we accept .dynsym also
*/
for (self->origin = DSO__ORIG_BUILD_ID_CACHE, want_symtab = 1;
self->origin != DSO__ORIG_NOT_FOUND;
self->origin++) {
switch (self->origin) {
case DSO__ORIG_BUILD_ID_CACHE:
if (dso__build_id_filename(self, name, size) == NULL)
continue;
break;
case DSO__ORIG_FEDORA:
snprintf(name, size, "/usr/lib/debug%s.debug",
self->long_name);
Expand All @@ -1406,19 +1417,20 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
snprintf(name, size, "/usr/lib/debug%s",
self->long_name);
break;
case DSO__ORIG_BUILDID:
if (self->has_build_id) {
char build_id_hex[BUILD_ID_SIZE * 2 + 1];
build_id__sprintf(self->build_id,
sizeof(self->build_id),
build_id_hex);
snprintf(name, size,
"/usr/lib/debug/.build-id/%.2s/%s.debug",
build_id_hex, build_id_hex + 2);
break;
case DSO__ORIG_BUILDID: {
char build_id_hex[BUILD_ID_SIZE * 2 + 1];

if (!self->has_build_id)
continue;

build_id__sprintf(self->build_id,
sizeof(self->build_id),
build_id_hex);
snprintf(name, size,
"/usr/lib/debug/.build-id/%.2s/%s.debug",
build_id_hex, build_id_hex + 2);
}
self->origin++;
/* Fall thru */
break;
case DSO__ORIG_DSO:
snprintf(name, size, "%s", self->long_name);
break;
Expand All @@ -1431,27 +1443,41 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
break;

default:
goto out;
/*
* If we wanted a full symtab but no image had one,
* relax our requirements and repeat the search.
*/
if (want_symtab) {
want_symtab = 0;
self->origin = DSO__ORIG_BUILD_ID_CACHE;
} else
continue;
}
open_file:

/* Name is now the name of the next image to try */
fd = open(name, O_RDONLY);
} while (fd < 0);
if (fd < 0)
continue;

ret = dso__load_sym(self, map, name, fd, filter, 0);
close(fd);
ret = dso__load_sym(self, map, name, fd, filter, 0,
want_symtab);
close(fd);

/*
* Some people seem to have debuginfo files _WITHOUT_ debug info!?!?
*/
if (!ret)
goto more;
/*
* Some people seem to have debuginfo files _WITHOUT_ debug
* info!?!?
*/
if (!ret)
continue;

if (ret > 0) {
int nr_plt = dso__synthesize_plt_symbols(self, map, filter);
if (nr_plt > 0)
ret += nr_plt;
if (ret > 0) {
int nr_plt = dso__synthesize_plt_symbols(self, map, filter);
if (nr_plt > 0)
ret += nr_plt;
break;
}
}
out:

free(name);
if (ret < 0 && strstr(self->name, " (deleted)") != NULL)
return 0;
Expand Down Expand Up @@ -1715,7 +1741,7 @@ static int dso__load_vmlinux(struct dso *self, struct map *map,
return -1;

dso__set_loaded(self, map->type);
err = dso__load_sym(self, map, vmlinux, fd, filter, 0);
err = dso__load_sym(self, map, vmlinux, fd, filter, 0, 0);
close(fd);

if (err > 0)
Expand Down

0 comments on commit 6da80ce

Please sign in to comment.