perf symbol: Fix symbol parsing in certain cases: use the build-id as a symlink
In some cases distros have binaries and debuginfo in weird places: [root@doppio tuna]# ls -la /usr/lib64/{xulrunner-1.9.1/xulrunner-stub,firefox-3.5.2/firefox} -rwxr-xr-x 1 root root 90024 2009-08-03 19:45 /usr/lib64/firefox-3.5.2/firefox -rwxr-xr-x 1 root root 90024 2009-08-03 18:23 /usr/lib64/xulrunner-1.9.1/xulrunner-stub [root@doppio tuna]# sha1sum /usr/lib64/{xulrunner-1.9.1/xulrunner-stub,firefox-3.5.2/firefox} 19a858077d263d5de22c9c5da250d3e4396ae739 /usr/lib64/xulrunner-1.9.1/xulrunner-stub 19a858077d263d5de22c9c5da250d3e4396ae739 /usr/lib64/firefox-3.5.2/firefox [root@doppio tuna]# rpm -qf /usr/lib64/{xulrunner-1.9.1/xulrunner-stub,firefox-3.5.2/firefox} xulrunner-1.9.1.2-1.fc11.x86_64 firefox-3.5.2-2.fc11.x86_64 [root@doppio tuna]# ls -la /usr/lib/debug/{usr/lib64/xulrunner-1.9.1/xulrunner-stub,usr/lib64/firefox-3.5.2/firefox}.debug ls: cannot access /usr/lib/debug/usr/lib64/firefox-3.5.2/firefox.debug: No such file or directory -rwxr-xr-x 1 root root 403608 2009-08-03 18:22 /usr/lib/debug/usr/lib64/xulrunner-1.9.1/xulrunner-stub.debug Seemingly we don't have a .symtab when we actually can find it if we use the .note.gnu.build-id ELF section put in place by some distros. Use it and find the symbols we need. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Acked-by: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
e0d82a0a4e
commit
4d1e00a8af
1 changed files with 73 additions and 3 deletions
|
@ -661,10 +661,69 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
|
|||
return err;
|
||||
}
|
||||
|
||||
#define BUILD_ID_SIZE 128
|
||||
|
||||
static char *dso__read_build_id(struct dso *self, int verbose)
|
||||
{
|
||||
int i;
|
||||
GElf_Ehdr ehdr;
|
||||
GElf_Shdr shdr;
|
||||
Elf_Data *build_id_data;
|
||||
Elf_Scn *sec;
|
||||
char *build_id = NULL, *bid;
|
||||
unsigned char *raw;
|
||||
Elf *elf;
|
||||
int fd = open(self->name, O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
goto out;
|
||||
|
||||
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
|
||||
if (elf == NULL) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "%s: cannot read %s ELF file.\n",
|
||||
__func__, self->name);
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
if (gelf_getehdr(elf, &ehdr) == NULL) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "%s: cannot get elf header.\n", __func__);
|
||||
goto out_elf_end;
|
||||
}
|
||||
|
||||
sec = elf_section_by_name(elf, &ehdr, &shdr, ".note.gnu.build-id", NULL);
|
||||
if (sec == NULL)
|
||||
goto out_elf_end;
|
||||
|
||||
build_id_data = elf_getdata(sec, NULL);
|
||||
if (build_id_data == NULL)
|
||||
goto out_elf_end;
|
||||
build_id = malloc(BUILD_ID_SIZE);
|
||||
if (build_id == NULL)
|
||||
goto out_elf_end;
|
||||
raw = build_id_data->d_buf + 16;
|
||||
bid = build_id;
|
||||
|
||||
for (i = 0; i < 20; ++i) {
|
||||
sprintf(bid, "%02x", *raw);
|
||||
++raw;
|
||||
bid += 2;
|
||||
}
|
||||
if (verbose)
|
||||
printf("%s(%s): %s\n", __func__, self->name, build_id);
|
||||
out_elf_end:
|
||||
elf_end(elf);
|
||||
out_close:
|
||||
close(fd);
|
||||
out:
|
||||
return build_id;
|
||||
}
|
||||
|
||||
int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
|
||||
{
|
||||
int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug");
|
||||
char *name = malloc(size);
|
||||
int size = PATH_MAX;
|
||||
char *name = malloc(size), *build_id = NULL;
|
||||
int variant = 0;
|
||||
int ret = -1;
|
||||
int fd;
|
||||
|
@ -686,7 +745,18 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
|
|||
case 1: /* Ubuntu */
|
||||
snprintf(name, size, "/usr/lib/debug%s", self->name);
|
||||
break;
|
||||
case 2: /* Sane people */
|
||||
case 2:
|
||||
build_id = dso__read_build_id(self, verbose);
|
||||
if (build_id != NULL) {
|
||||
snprintf(name, size,
|
||||
"/usr/lib/debug/.build-id/%.2s/%s.debug",
|
||||
build_id, build_id + 2);
|
||||
free(build_id);
|
||||
break;
|
||||
}
|
||||
variant++;
|
||||
/* Fall thru */
|
||||
case 3: /* Sane people */
|
||||
snprintf(name, size, "%s", self->name);
|
||||
break;
|
||||
|
||||
|
|
Loading…
Reference in a new issue