[PATCH] Introduce dwfl_module_getsym_info and dwfl_module_addrinfo.
Jan Kratochvil
jan.kratochvil at redhat.com
Thu Dec 12 21:11:27 UTC 2013
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 <mjw at 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 <mjw at 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 <mjw at 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.kratochvil at 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 <mjw at 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 <pmachata at 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
More information about the elfutils-devel
mailing list