Add PowerPC64 function descriptor support for dt_link.c

Summary:
PowerPC64 uses function descriptors in a section .opd, exporting the descriptors
to the symbol table.  This adds support for these into dt_link.c so that dtrace
USDT probes can be compiled.

Test Plan:
Tested only on powerpc64.  No regression testing has been performed, so I want
someone with x86 hardware to regression test this.

Tested on amd64 by markj

Reviewers: #dtrace, markj

Reviewed By: #dtrace, markj

Subscribers: markj

Differential Revision: https://reviews.freebsd.org/D1267

MFC after:	3 weeks
This commit is contained in:
Justin Hibbits 2014-12-28 06:41:13 +00:00
parent 1a5934ef8e
commit b08e2b04fe
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=276326

View File

@ -685,8 +685,8 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
elf_file.ehdr.e_machine = EM_ARM; elf_file.ehdr.e_machine = EM_ARM;
#elif defined(__mips__) #elif defined(__mips__)
elf_file.ehdr.e_machine = EM_MIPS; elf_file.ehdr.e_machine = EM_MIPS;
#elif defined(__powerpc__) #elif defined(__powerpc64__)
elf_file.ehdr.e_machine = EM_PPC; elf_file.ehdr.e_machine = EM_PPC64;
#elif defined(__sparc) #elif defined(__sparc)
elf_file.ehdr.e_machine = EM_SPARCV9; elf_file.ehdr.e_machine = EM_SPARCV9;
#elif defined(__i386) || defined(__amd64) #elif defined(__i386) || defined(__amd64)
@ -784,21 +784,32 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd)
static int static int
dt_symtab_lookup(Elf_Data *data_sym, int nsym, uintptr_t addr, uint_t shn, dt_symtab_lookup(Elf_Data *data_sym, int nsym, uintptr_t addr, uint_t shn,
GElf_Sym *sym) GElf_Sym *sym, int uses_funcdesc, Elf *elf)
{ {
int i, ret = -1; int i, ret = -1;
Elf64_Addr symval;
Elf_Scn *opd_scn;
Elf_Data *opd_desc;
GElf_Sym s; GElf_Sym s;
for (i = 0; i < nsym && gelf_getsym(data_sym, i, sym) != NULL; i++) { for (i = 0; i < nsym && gelf_getsym(data_sym, i, sym) != NULL; i++) {
if (GELF_ST_TYPE(sym->st_info) == STT_FUNC && if (GELF_ST_TYPE(sym->st_info) == STT_FUNC) {
shn == sym->st_shndx && symval = sym->st_value;
sym->st_value <= addr && if (uses_funcdesc) {
addr < sym->st_value + sym->st_size) { opd_scn = elf_getscn(elf, sym->st_shndx);
if (GELF_ST_BIND(sym->st_info) == STB_GLOBAL) opd_desc = elf_rawdata(opd_scn, NULL);
return (0); symval =
*(uint64_t*)((char *)opd_desc->d_buf + symval);
}
if ((uses_funcdesc || shn == sym->st_shndx) &&
symval <= addr &&
addr < symval + sym->st_size) {
if (GELF_ST_BIND(sym->st_info) == STB_GLOBAL)
return (0);
ret = 0; ret = 0;
s = *sym; s = *sym;
}
} }
} }
@ -1375,7 +1386,8 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
continue; continue;
if (dt_symtab_lookup(data_sym, isym, rela.r_offset, if (dt_symtab_lookup(data_sym, isym, rela.r_offset,
shdr_rel.sh_info, &fsym) != 0) { shdr_rel.sh_info, &fsym,
(emachine1 == EM_PPC64), elf) != 0) {
dt_strtab_destroy(strtab); dt_strtab_destroy(strtab);
goto err; goto err;
} }
@ -1536,7 +1548,8 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
p = strhyphenate(p + 3); /* strlen("___") */ p = strhyphenate(p + 3); /* strlen("___") */
if (dt_symtab_lookup(data_sym, isym, rela.r_offset, if (dt_symtab_lookup(data_sym, isym, rela.r_offset,
shdr_rel.sh_info, &fsym) != 0) shdr_rel.sh_info, &fsym,
(emachine1 == EM_PPC64), elf) != 0)
goto err; goto err;
if (fsym.st_name > data_str->d_size) if (fsym.st_name > data_str->d_size)