On Thu, 12 Dec 2013 11:51:37 +0100, Mark Wielaard wrote: > --- /dev/null > +++ b/backends/ppc64_resolve_sym.c > @@ -0,0 +1,63 @@ > +/* Resolve symbol values through .opd function descriptors. > + Copyright (C) 2013 Red Hat, Inc. > + This file is part of elfutils. > + > + This file is free software; you can redistribute it and/or modify > + it under the terms of either > + > + * the GNU Lesser General Public License as published by the Free > + Software Foundation; either version 3 of the License, or (at > + your option) any later version > + > + or > + > + * the GNU General Public License as published by the Free > + Software Foundation; either version 2 of the License, or (at > + your option) any later version > + > + or both in parallel, as here. > + > + elfutils is distributed in the hope that it will be useful, but > + WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + General Public License for more details. > + > + You should have received copies of the GNU General Public License and > + the GNU Lesser General Public License along with this program. If > + not, see <http://www.gnu.org/licenses/>. */ > + > +#ifdef HAVE_CONFIG_H > +# include <config.h> > +#endif > + > +#define BACKEND ppc64_ > +#include "libebl_CPU.h" > + > +/* Resolve a function descriptor if addr points into the .odp section. > + The .odp section contains function descriptors consisting of 3 addresses. > + function, toc and chain. We are just interested in the first. > + > http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-DES > + > + Returns true if the given address could be resolved, false otherwise. > +*/ > +bool > +ppc64_resolve_sym_value (Ebl *ebl, GElf_Addr *addr) > +{ > + if (ebl->fd_data != NULL && *addr >= ebl->fd_addr
> + && *addr < ebl->fd_addr + ebl->fd_data->d_size) && *addr + sizeof (Elf64_Addr) <= ebl->fd_addr + ebl->fd_data->d_size) > + { > + GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (ebl->elf, &ehdr_mem); > + if (ehdr != NULL) > + { > + Elf_Data opd_in, opd_out; > + opd_in.d_buf = ebl->fd_data->d_buf + (*addr - ebl->fd_addr); > + opd_out.d_buf = addr; > + opd_out.d_size = opd_in.d_size = sizeof (Elf64_Addr); > + opd_out.d_type = opd_in.d_type = ELF_T_ADDR; > + if (elf64_xlatetom (&opd_out, &opd_in, > + ehdr->e_ident[EI_DATA]) != NULL) > + return true; > + } > + } > + return false; > +} > diff --git a/libdw/ChangeLog b/libdw/ChangeLog > index 91e1083..1efe0dc 100644 > --- a/libdw/ChangeLog > +++ b/libdw/ChangeLog > @@ -1,3 +1,10 @@ > +2013-12-11 Mark Wielaard <m...@redhat.com> > + > + * libdw.map (ELFUTILS_0.158): Remove dwfl_module_addrsym_elf and > + dwfl_module_getsym_elf. Add dwfl_module_addrinfo, > + dwfl_module_addrinfo_elf, dwfl_module_getsym_info and > + dwfl_module_getsym_info_elf. > + > 2013-11-27 Mark Wielaard <m...@redhat.com> > > * libdw.map (ELFUTILS_0.158): Add dwfl_module_addrsym_elf and > diff --git a/libdw/libdw.map b/libdw/libdw.map > index 0438e24..6d21101 100644 > --- a/libdw/libdw.map > +++ b/libdw/libdw.map > @@ -284,6 +284,8 @@ ELFUTILS_0.158 { > dwfl_thread_getframes; > dwfl_frame_pc; > > - dwfl_module_addrsym_elf; > - dwfl_module_getsym_elf; > + dwfl_module_addrinfo; > + dwfl_module_addrinfo_elf; > + dwfl_module_getsym_info; > + dwfl_module_getsym_info_elf; FYI my opinion is that there is no benefit to have the functions dwfl_module_addrinfo and dwfl_module_getsym_info. One can use just the *_elf ones. > } ELFUTILS_0.157; > diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog > index 7e87e17..51027e4 100644 > --- a/libdwfl/ChangeLog > +++ b/libdwfl/ChangeLog > @@ -1,3 +1,39 @@ > +2013-12-11 Mark Wielaard <m...@redhat.com> > + > + * derelocate.c (__libdwfl_find_section_ndx): New internal function. > + * dwfl_module_addrname.c (dwfl_module_addrname): Use > + dwfl_module_addrinfo. > + * dwfl_module_addrsym.c (dwfl_module_addrsym_elf): Replace with... > + (__libdwfl_addrsym): ...this. Use __libdwfl_getsym, use value > + for comparisons, not st_value. Fill in off. > + (dwfl_module_addrsym): Implement using __libdwfl_addrsym. > + (dwfl_module_addrinfo): New function. > + (dwfl_module_addrinfo_elf): Likewise. > + * dwfl_module_getsym.c (dwfl_module_getsym_elf): Replace with... > + (__libdwfl_getsym): ...this. Use ebl_resolve_sym_value if requested > + and possible. Adjust sym->st_value only when requested. Fill in addr > + if available. > + (dwfl_module_getsym_info): New function. > + (dwfl_module_getsym_info_elf): New function. > + (dwfl_module_getsym): Use __libdwfl_getsym. > + * libdwfl.h (dwfl_module_getsym_elf): Removed. > + (dwfl_module_getsym_info): New function declaration. > + (dwfl_module_getsym_info_elf): Likewise. > + (dwfl_module_addrinfo): Likewise. > + (dwfl_module_addrinfo_elf): Likewise. > + (dwfl_module_addrsym): Add documentation describing differences > + with addrinfo variants. > + (dwfl_module_addrsym_elf): Removed. > + * libdwflP.h (__libdwfl_getsym): New internal function declaration. > + (__libdwfl_addrsym): Likewise. > + (__libdwfl_find_section_ndx): Likewise. > + (dwfl_module_addrinfo): New internal declaration. > + (dwfl_module_addrinfo_elf): Likewise. > + (dwfl_module_addrsym_elf): Removed. > + (dwfl_module_getsym_elf): Likewise. > + (dwfl_module_getsym_info): New internal declaration. > + (dwfl_module_getsym_info_elf): Likewise. > + > 2013-11-30 Jan Kratochvil <jan.kratoch...@redhat.com> > > Introduce process_attach_error. > diff --git a/libdwfl/derelocate.c b/libdwfl/derelocate.c > index 56f998c..da67908 100644 > --- a/libdwfl/derelocate.c > +++ b/libdwfl/derelocate.c > @@ -1,5 +1,5 @@ > /* Recover relocatibility for addresses computed from debug information. > - Copyright (C) 2005-2010 Red Hat, Inc. > + Copyright (C) 2005-2010, 2013 Red Hat, Inc. > This file is part of elfutils. > > This file is free software; you can redistribute it and/or modify > @@ -330,6 +330,17 @@ find_section (Dwfl_Module *mod, Dwarf_Addr *addr) > return -1; > } > > +size_t > +internal_function > +__libdwfl_find_section_ndx (Dwfl_Module *mod, Dwarf_Addr *addr) > +{ > + int idx = find_section (mod, addr); I see I did not know there is find_section (). > + if (unlikely (idx == -1)) > + return SHN_UNDEF; > + > + return elf_ndxscn (mod->reloc_info->refs[idx].scn); > +} > + > int > dwfl_module_relocate_address (Dwfl_Module *mod, Dwarf_Addr *addr) > { [...] > --- a/libdwfl/libdwfl.h > +++ b/libdwfl/libdwfl.h > @@ -445,34 +445,75 @@ extern const char *dwfl_module_getsym (Dwfl_Module > *mod, int ndx, > GElf_Sym *sym, GElf_Word *shndxp) > __nonnull_attribute__ (3); > > -/* Same as dwfl_module_getsym but also returns the ELF file, if not NULL, > - that the symbol came from so the section index can be reliably used. > - Fills in *BIAS, if not NULL, with the difference between addresses > - within the loaded module and those in symbol tables of the ELF file. */ > -extern const char *dwfl_module_getsym_elf (Dwfl_Module *mod, int ndx, > - GElf_Sym *sym, GElf_Word *shndxp, > - Elf **elfp, Dwarf_Addr *bias) > - __nonnull_attribute__ (3); > +/* Fetch one entry from the module's symbol table and the associated > + address value. On errors, returns NULL. If successful, fills in > + *SYM, *ADDR and returns the string for st_name. This works like > + gelf_getsym. *ADDR is set to the st_value adjusted to an absolute > + value based on the module's location, when the symbol is in an > + SHF_ALLOC section. For non-ET_REL files, if the arch uses function > + descriptors, and the st_value points to one, the value will be > + resolved to the actual function address. Note that since symbols > + can come from either the main, debug or auxiliary ELF symbol file > + (either dynsym or symtab) and the st_value itself isn't adjusted in > + any way (this is different from dwfl_module_getsym). */ The sentence is unfinished. > +extern const char *dwfl_module_getsym_info (Dwfl_Module *mod, int ndx, > + GElf_Sym *sym, GElf_Addr *addr) > + __nonnull_attribute__ (3, 4); > + > +/* Same as dwfl_module_getsym_info but also returns the section index, > + the ELF file and bias. If SHNDXP is non-null, it's set with the > + section index (whether from st_shndx or extended index table); in > + case of a symbol in a non-allocated section, *SHNDXP is instead set > + to -1. Fills in BIAS, if not NULL, with the difference between It is uint32_t so maybe the doc could say s/-1/0xffffffff/. But maybe it was intentional. > + addresses within the loaded module and those in symbol tables of > + the ELF file. Note that the address associated with the symbol > + might be a different section (and ELF file) than the returned > + symbol. That section, in the main elf file, can be found with > + dwfl_module_address_section. */ > +extern const char *dwfl_module_getsym_info_elf (Dwfl_Module *mod, int ndx, > + GElf_Sym *sym, GElf_Addr *addr, > + GElf_Word *shndxp, > + Elf **elfp, Dwarf_Addr *bias) > + __nonnull_attribute__ (3, 4); > > /* Find the symbol that ADDRESS lies inside, and return its name. */ > extern const char *dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr > address); > > +/* Find the symbol associated with ADDRESS, return its name, the > + OFFSET that ADDRESS is from the start and optionally the originally I cannot parse the sentence. s/from the start/from the address of returned SYM/ ? s/originally// ? > + SYM associated with the ADDRESS. Note that the address is matched > + against the, possibly resolved (for function descriptor symbols), > + and adjusted st_value for the Dwfl_Module location. The SYM->st_value > + itself isn't changed. */ > +extern const char *dwfl_module_addrinfo (Dwfl_Module *mod, GElf_Addr address, > + GElf_Off *offset, GElf_Sym *sym) > + __nonnull_attribute__ (3, 4); > + > +/* Same as dwfl_module_addrinfo but also returns the ELF file, if not > + NULL, that the symbol originally came from. If SHNDXP is non-null, > + it's set with the section index (whether from st_shndx or extended > + index table); in case of a symbol in a non-allocated section, > + *SHNDXP is instead set to -1. Fills in *BIAS, if not NULL, with It is uint32_t so maybe the doc could say s/-1/0xffffffff/. But maybe it was intentional. > + the difference between addresses within the loaded module and those > + in the symbol table of the ELF file. */ > +extern const char *dwfl_module_addrinfo_elf (Dwfl_Module *mod, > + GElf_Addr address, > + GElf_Off *offset, > + GElf_Sym *sym, > + GElf_Word *shndxp, > + Elf **elfp, Dwarf_Addr *bias) > + __nonnull_attribute__ (3); > + > /* Find the symbol that ADDRESS lies inside, and return detailed > - information as for dwfl_module_getsym (above). */ > + information as for dwfl_module_getsym (above). Note that unlike > + dwfl_module_addrname and dwfl_module_addrinfo this matches ADDRESS > + against the adjusted SYM->ST_VALUE directly, so might depending on > + whether the architecture uses indirections like function descriptors, > + not match against actual function addresses. */ I cannot parse the sentence, I hope it is clear it is formed incorrectly. It would be good to know whether it finds function entry addresses and whether it finds function descriptor addresses. > extern const char *dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr address, > GElf_Sym *sym, GElf_Word *shndxp) > __nonnull_attribute__ (3); > > -/* Same as dwfl_module_addrsym but also returns the ELF file, if not NULL, > - that the symbol came from so the section index can be reliably used. > - Fills in *BIAS, if not NULL, with the difference between addresses > - within the loaded module and those in symbol tables of the ELF file. */ > -extern const char *dwfl_module_addrsym_elf (Dwfl_Module *mod, > - GElf_Addr address, GElf_Sym *sym, > - GElf_Word *shndxp, Elf **elfp, > - Dwarf_Addr *bias) > - __nonnull_attribute__ (3); > - > /* Find the ELF section that *ADDRESS lies inside and return it. > On success, adjusts *ADDRESS to be relative to the section, > and sets *BIAS to the difference between addresses used in > diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h > index ba1c758..d931eac 100644 > --- a/libdwfl/libdwflP.h > +++ b/libdwfl/libdwflP.h > @@ -388,6 +388,22 @@ struct dwfl_arange > }; > > > +/* Internal wrapper for old dwfl_module_getsym and new > dwfl_module_getsym_info. > + adjust_st_value set to true returns adjusted SYM st_value, set to false > + it will not adjust SYM at all, but does match against resolved *ADDR. */ > +extern const char *__libdwfl_getsym (Dwfl_Module *mod, int ndx, GElf_Sym > *sym, > + GElf_Addr *addr, GElf_Word *shndxp, > + Elf **elfp, Dwarf_Addr *biasp, > + bool adjust_st_value) internal_function; > + > +/* Internal wrapper for old dwfl_module_addrsym and new dwfl_module_addrinfo. > + adjust_st_value set to true returns adjusted SYM st_value, set to false > + it will not adjust SYM at all, but does match against resolved values. */ > +extern const char *__libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, > + GElf_Off *off, GElf_Sym *sym, > + GElf_Word *shndxp, Elf **elfp, > + Dwarf_Addr *bias, > + bool adjust_st_value) internal_function; > > extern void __libdwfl_module_free (Dwfl_Module *mod) internal_function; > > @@ -404,6 +420,12 @@ extern void __libdwfl_getelf (Dwfl_Module *mod) > internal_function; > extern Dwfl_Error __libdwfl_relocate (Dwfl_Module *mod, Elf *file, bool > debug) > internal_function; > > +/* Find the section index in mod->main.elf that contains the given > + *ADDR. Adjusts *ADDR to be section relative on success, returns > + SHN_UNDEF on failure. */ > +extern size_t __libdwfl_find_section_ndx (Dwfl_Module *mod, Dwarf_Addr *addr) > + internal_function; > + > /* Process (simple) relocations in arbitrary section TSCN of an ET_REL file. > RELOCSCN is SHT_REL or SHT_RELA and TSCN is its sh_info target section. > */ > extern Dwfl_Error __libdwfl_relocate_section (Dwfl_Module *mod, Elf > *relocated, > @@ -638,13 +660,15 @@ INTDECL (dwfl_core_file_report) > INTDECL (dwfl_getmodules) > INTDECL (dwfl_module_addrdie) > INTDECL (dwfl_module_address_section) > +INTDECL (dwfl_module_addrinfo) > +INTDECL (dwfl_module_addrinfo_elf) > INTDECL (dwfl_module_addrsym) > -INTDECL (dwfl_module_addrsym_elf) > INTDECL (dwfl_module_build_id) > INTDECL (dwfl_module_getdwarf) > INTDECL (dwfl_module_getelf) > INTDECL (dwfl_module_getsym) > -INTDECL (dwfl_module_getsym_elf) > +INTDECL (dwfl_module_getsym_info) > +INTDECL (dwfl_module_getsym_info_elf) > INTDECL (dwfl_module_getsymtab) > INTDECL (dwfl_module_getsrc) > INTDECL (dwfl_module_report_build_id) > diff --git a/libebl/ChangeLog b/libebl/ChangeLog > index a5c9dae..0144c4e 100644 > --- a/libebl/ChangeLog > +++ b/libebl/ChangeLog > @@ -1,3 +1,12 @@ > +2013-12-11 Mark Wielaard <m...@redhat.com> > + > + * Makefile.am (gen_SOURCES): Add eblresolvesym.c. > + * ebl-hooks.h (resolve_sym_value): New entry. > + * eblresolvesym.c: New file. > + * libebl.h (ebl_resolve_sym_value): New definition. > + * libeblP.h (fd_addr): New field. > + (fd_data): Likewise. > + > 2013-11-25 Petr Machata <pmach...@redhat.com> > > * eblopenbackend.c (machines): Add entry for AArch64. > diff --git a/libebl/Makefile.am b/libebl/Makefile.am > index 4487c5f..5322315 100644 > --- a/libebl/Makefile.am > +++ b/libebl/Makefile.am > @@ -54,7 +54,7 @@ gen_SOURCES = eblopenbackend.c eblclosebackend.c > eblstrtab.c \ > eblreginfo.c eblnonerelocp.c eblrelativerelocp.c \ > eblsysvhashentrysize.c eblauxvinfo.c eblcheckobjattr.c \ > ebl_check_special_section.c ebl_syscall_abi.c eblabicfi.c \ > - eblstother.c eblinitreg.c > + eblstother.c eblinitreg.c eblresolvesym.c > > libebl_a_SOURCES = $(gen_SOURCES) > > diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h > index cb52fee..7cbbb8f 100644 > --- a/libebl/ebl-hooks.h > +++ b/libebl/ebl-hooks.h > @@ -162,5 +162,10 @@ bool EBLHOOK(set_initial_registers_tid) (pid_t tid, > ebl_tid_registers_t *setfunc, > void *arg); > > +/* Returns true if the value can be resolved to an address in an > + allocated section, which will be returned in *SHNDXP. > + (e.g. function descriptor resolving). */ | probably an excessive dot ^ > +bool EBLHOOK(resolve_sym_value) (Ebl *ebl, GElf_Addr *addr); > + > /* Destructor for ELF backend handle. */ > void EBLHOOK(destr) (struct ebl *); > diff --git a/libdwfl/dwfl_module_addrname.c b/libebl/eblresolvesym.c > similarity index 72% > copy from libdwfl/dwfl_module_addrname.c > copy to libebl/eblresolvesym.c > index 6ae0123..470f6f0 100644 > --- a/libdwfl/dwfl_module_addrname.c > +++ b/libebl/eblresolvesym.c > @@ -1,5 +1,5 @@ > -/* Find debugging and symbol information for a module in libdwfl. > - Copyright (C) 2005, 2006, 2007 Red Hat, Inc. > +/* Resolve a symbol value to an allocated section of the Elf file. > + Copyright (C) 2013 Red Hat, Inc. > This file is part of elfutils. > > This file is free software; you can redistribute it and/or modify > @@ -26,11 +26,18 @@ > the GNU Lesser General Public License along with this program. If > not, see <http://www.gnu.org/licenses/>. */ > > -#include "libdwflP.h" > +#ifdef HAVE_CONFIG_H > +# include <config.h> > +#endif > > -const char * > -dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr addr) > +#include <libeblP.h> > +#include <assert.h> > + > +bool > +ebl_resolve_sym_value (Ebl *ebl, GElf_Addr *addr) > { > - GElf_Sym sym; > - return INTUSE(dwfl_module_addrsym) (mod, addr, &sym, NULL); > + if (ebl == NULL || ebl->resolve_sym_value == NULL) > + return false; > + > + return ebl->resolve_sym_value (ebl, addr); > } > diff --git a/libebl/libebl.h b/libebl/libebl.h > index 045a198..eea6700 100644 > --- a/libebl/libebl.h > +++ b/libebl/libebl.h > @@ -402,6 +402,12 @@ extern bool ebl_set_initial_registers_tid (Ebl *ebl, > extern size_t ebl_frame_nregs (Ebl *ebl) > __nonnull_attribute__ (1); > > +/* Returns true if the value can be resolved to an address in an > + allocated section, which will be returned in *ADDR > + (e.g. function descriptor resolving). */ | probably an excessive dot ^ > +extern bool ebl_resolve_sym_value (Ebl *ebl, GElf_Addr *addr) > + __nonnull_attribute__ (2); > + > #ifdef __cplusplus > } > #endif [...] Thanks, Jan