diff options
author | jhibbits <jhibbits@FreeBSD.org> | 2014-12-28 06:41:13 +0000 |
---|---|---|
committer | jhibbits <jhibbits@FreeBSD.org> | 2014-12-28 06:41:13 +0000 |
commit | 7f4508f63265e7edce9cbc78bebfcb2765856ea2 (patch) | |
tree | de34bed8463cf950d6b8d0d18febd19cdfec8b7e /cddl | |
parent | baa3b938e58001d933f7fc4c3a089d30cf78d14c (diff) | |
download | FreeBSD-src-7f4508f63265e7edce9cbc78bebfcb2765856ea2.zip FreeBSD-src-7f4508f63265e7edce9cbc78bebfcb2765856ea2.tar.gz |
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
Diffstat (limited to 'cddl')
-rw-r--r-- | cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c index 597fef4..771f1ae 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c @@ -685,8 +685,8 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd) elf_file.ehdr.e_machine = EM_ARM; #elif defined(__mips__) elf_file.ehdr.e_machine = EM_MIPS; -#elif defined(__powerpc__) - elf_file.ehdr.e_machine = EM_PPC; +#elif defined(__powerpc64__) + elf_file.ehdr.e_machine = EM_PPC64; #elif defined(__sparc) elf_file.ehdr.e_machine = EM_SPARCV9; #elif defined(__i386) || defined(__amd64) @@ -784,21 +784,32 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd) static int 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; + Elf64_Addr symval; + Elf_Scn *opd_scn; + Elf_Data *opd_desc; GElf_Sym s; for (i = 0; i < nsym && gelf_getsym(data_sym, i, sym) != NULL; i++) { - if (GELF_ST_TYPE(sym->st_info) == STT_FUNC && - shn == sym->st_shndx && - sym->st_value <= addr && - addr < sym->st_value + sym->st_size) { - if (GELF_ST_BIND(sym->st_info) == STB_GLOBAL) - return (0); - - ret = 0; - s = *sym; + if (GELF_ST_TYPE(sym->st_info) == STT_FUNC) { + symval = sym->st_value; + if (uses_funcdesc) { + opd_scn = elf_getscn(elf, sym->st_shndx); + opd_desc = elf_rawdata(opd_scn, NULL); + 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; + s = *sym; + } } } @@ -1375,7 +1386,8 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) continue; 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); goto err; } @@ -1536,7 +1548,8 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) p = strhyphenate(p + 3); /* strlen("___") */ 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; if (fsym.st_name > data_str->d_size) |