Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 155715
b: refs/heads/master
c: a25e46c
h: refs/heads/master
i:
  155713: 2a1589d
  155711: 8fbcd45
v: v3
  • Loading branch information
Arnaldo Carvalho de Melo authored and Ingo Molnar committed Jul 11, 2009
1 parent 24934b0 commit 0e82333
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 52 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 021191b35cdfb1b5ee6e78ed5ae010114a40902c
refs/heads/master: a25e46c46311316cd1b3f27f8bb036df1693c032
116 changes: 65 additions & 51 deletions trunk/tools/perf/util/symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,56 +374,81 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
idx < nr_entries; \
++idx, pos = gelf_getrela(reldata, idx, &pos_mem))

static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym,
GElf_Shdr *shdr_dynsym,
size_t dynsym_idx, int verbose)
/*
* We need to check if we have a .dynsym, so that we can handle the
* .plt, synthesizing its symbols, that aren't on the symtabs (be it
* .dynsym or .symtab).
* And always look at the original dso, not at debuginfo packages, that
* have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
*/
static int dso__synthesize_plt_symbols(struct dso *self, int verbose)
{
uint32_t nr_rel_entries, idx;
GElf_Sym sym;
u64 plt_offset;
GElf_Shdr shdr_plt;
struct symbol *f;
GElf_Shdr shdr_rel_plt;
GElf_Shdr shdr_rel_plt, shdr_dynsym;
Elf_Data *reldata, *syms, *symstrs;
Elf_Scn *scn_plt_rel, *scn_symstrs;
Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
size_t dynsym_idx;
GElf_Ehdr ehdr;
char sympltname[1024];
int nr = 0, symidx;
Elf *elf;
int nr = 0, symidx, fd, err = 0;

fd = open(self->name, O_RDONLY);
if (fd < 0)
goto out;

elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
if (elf == NULL)
goto out_close;

if (gelf_getehdr(elf, &ehdr) == NULL)
goto out_elf_end;

scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
".dynsym", &dynsym_idx);
if (scn_dynsym == NULL)
goto out_elf_end;

scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt,
scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
".rela.plt", NULL);
if (scn_plt_rel == NULL) {
scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt,
scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
".rel.plt", NULL);
if (scn_plt_rel == NULL)
return 0;
goto out_elf_end;
}

err = -1;

if (shdr_rel_plt.sh_link != dynsym_idx)
return 0;
goto out_elf_end;

if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL)
return 0;
if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
goto out_elf_end;

/*
* Fetch the relocation section to find the indexes to the GOT
* and the symbols in the .dynsym they refer to.
*/
reldata = elf_getdata(scn_plt_rel, NULL);
if (reldata == NULL)
return -1;
goto out_elf_end;

syms = elf_getdata(scn_dynsym, NULL);
if (syms == NULL)
return -1;
goto out_elf_end;

scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link);
scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
if (scn_symstrs == NULL)
return -1;
goto out_elf_end;

symstrs = elf_getdata(scn_symstrs, NULL);
if (symstrs == NULL)
return -1;
goto out_elf_end;

nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
plt_offset = shdr_plt.sh_offset;
Expand All @@ -442,7 +467,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
f = symbol__new(plt_offset, shdr_plt.sh_entsize,
sympltname, self->sym_priv_size, 0, verbose);
if (!f)
return -1;
goto out_elf_end;

dso__insert_symbol(self, f);
++nr;
Expand All @@ -460,19 +485,25 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
f = symbol__new(plt_offset, shdr_plt.sh_entsize,
sympltname, self->sym_priv_size, 0, verbose);
if (!f)
return -1;
goto out_elf_end;

dso__insert_symbol(self, f);
++nr;
}
} else {
/*
* TODO: There are still one more shdr_rel_plt.sh_type
* I have to investigate, but probably should be ignored.
*/
}

return nr;
err = 0;
out_elf_end:
elf_end(elf);
out_close:
close(fd);

if (err == 0)
return nr;
out:
fprintf(stderr, "%s: problems reading %s PLT info.\n",
__func__, self->name);
return 0;
}

static int dso__load_sym(struct dso *self, int fd, const char *name,
Expand All @@ -486,9 +517,8 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
GElf_Shdr shdr;
Elf_Data *syms;
GElf_Sym sym;
Elf_Scn *sec, *sec_dynsym, *sec_strndx;
Elf_Scn *sec, *sec_strndx;
Elf *elf;
size_t dynsym_idx;
int nr = 0;

elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
Expand All @@ -505,32 +535,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
goto out_elf_end;
}

/*
* We need to check if we have a .dynsym, so that we can handle the
* .plt, synthesizing its symbols, that aren't on the symtabs (be it
* .dynsym or .symtab)
*/
sec_dynsym = elf_section_by_name(elf, &ehdr, &shdr,
".dynsym", &dynsym_idx);
if (sec_dynsym != NULL) {
nr = dso__synthesize_plt_symbols(self, elf, &ehdr,
sec_dynsym, &shdr,
dynsym_idx, verbose);
if (nr < 0)
goto out_elf_end;
}

/*
* But if we have a full .symtab (that is a superset of .dynsym) we
* should add the symbols not in the .dynsyn
*/
sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
if (sec == NULL) {
if (sec_dynsym == NULL)
sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
if (sec == NULL)
goto out_elf_end;

sec = sec_dynsym;
gelf_getshdr(sec, &shdr);
}

syms = elf_getdata(sec, NULL);
Expand Down Expand Up @@ -669,6 +678,11 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
if (!ret)
goto more;

if (ret > 0) {
int nr_plt = dso__synthesize_plt_symbols(self, verbose);
if (nr_plt > 0)
ret += nr_plt;
}
out:
free(name);
return ret;
Expand Down

0 comments on commit 0e82333

Please sign in to comment.