[patch] Resolve ppc64 func descriptors as .func (via .opd)

Mark Wielaard mjw at redhat.com
Tue Dec 4 10:55:42 UTC 2012


Hi Jan,

I haven't read the backend bits yet, sorry. But here some feedback on
the frontend bits first to keep things moving.

On Tue, 2012-11-20 at 14:12 +0100, Jan Kratochvil wrote:
> > > extern const char *dwfl_module_func_addrname (Dwfl_Module *mod,
> > >                                               GElf_Addr address,
> > >                                               GElf_Addr *funcaddr);
> > 
> > Yes, or maybe an GElf_Off that provides the offset from the start of the
> > named code block associated with the given address. Since I think the name
> > and the offset from the start of the code block is what is usually needed.
> > One can of course derive one from the other, so it doesn't really matter
> > I think whether you provide the address or offset.
> 
> Chose GElf_Addr when you have left that option.

That is a fine option to pick. I just mentioned the offset because that
is what I see often used in backtraces. But one can calculate one from
the other, so it doesn't really matter much.

> > > Finding just function types is not useful in practice, we need to find any
> > > symbol type.  And then the new interface fully supersedes the old interface.
> > 
> > Maybe if we can express this generically as a "filter" that lets you select
> > which symbols you are interested in and how to transform the matching
> > function symbol value (through architecture specific hooks)?
> > But I do think this is a different function from the generic symbol (name)
> > one. This is to get code name/addresses.
> 
> Not sure what did you mean by the paragraph.  The code picks now arbitrary
> symbol type, the same like dwfl_module_addrname or dwfl_module_addrsym do.

I was just wondering if we could express this more generically. But I
admit to not immediately see how without adding complicating callbacks
as filter functions. The main point was that this function should IMHO
not be expressed in terms of filtering/transforming symbols through a
architecture backend function that gives you the name associated with a
code address.

> diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
> index 000d582..5eb585a 100644
> --- a/libdwfl/libdwfl.h
> +++ b/libdwfl/libdwfl.h
> @@ -424,12 +424,27 @@ extern const char *dwfl_module_getsym (Dwfl_Module *mod, int ndx,
>  /* 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 that ADDRESS lies inside, and return its name.
> +   Return also its starting code addrees *FUNCADDR.  This function can
> +   handle function descriptors, contrary to dwfl_module_addrname.  */
> +extern const char *dwfl_module_codename (Dwfl_Module *mod, GElf_Addr address,
> +                                        GElf_Addr *funcaddr);
> +
>  /* Find the symbol that ADDRESS lies inside, and return detailed
>     information as for dwfl_module_getsym (above).  */
>  extern const char *dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr address,
>                                         GElf_Sym *sym, GElf_Word *shndxp)
>    __nonnull_attribute__ (3);
>  
> +/* Find the symbol that ADDRESS lies inside, and return detailed
> +   information as for dwfl_module_getsym (above).  Return also its
> +   starting code addrees *FUNCADDR.  This function can handle function
> +   descriptors, contrary to dwfl_module_addrsym.  */
> +extern const char *dwfl_module_codesym (Dwfl_Module *mod, GElf_Addr address,
> +                                        GElf_Sym *sym, GElf_Word *shndxp,
> +                                       GElf_Addr *funcaddr)
> +  __nonnull_attribute__ (3);


Note two times 'addrees' -> 'address'. I would rephrase it as:
Return the name and starting address of the code that the given address
is closes too. Also returns detailed information as for
dwfl_module_getsym (above) for the symbol that is associated to this
code. Note that this function may depend on architecture dependent
information like the function descriptor table and not just the symbol
table.

Maybe also mention that shndxp will always point to an allocated and
executable section since this is just for symbols associated with code?

> -const char *
> -dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
> -		     GElf_Sym *closest_sym, GElf_Word *shndxp)
> +static const char *
> +addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Sym *closest_sym,
> +	 GElf_Word *shndxp, GElf_Addr *funcaddr_return, bool also_func_pc)

Rename also_func_pc to something more generic like code_only?
 
> +  /* Look through the symbol table for a matching symbol.  */
> +  inline void search_table (int start, int end)
> +    {
> +      for (int i = start; i < end; ++i)
> +	{
> +	  GElf_Sym sym;
> +	  GElf_Word shndx;
> +	  const char *name = INTUSE(dwfl_module_getsym) (mod, i, &sym, &shndx);
> +	  found_sym (&sym, shndx, name, sym.st_value);
> +	  if (!also_func_pc || name == NULL)
> +	    continue;
> +	  Dwfl_Error error = __libdwfl_module_getebl (mod);
> +	  if (error != DWFL_E_NOERROR)
> +	    continue;
> +	  GElf_Addr funcaddr;
> +	  name = ebl_get_func_pc (mod->ebl, mod, &sym, &funcaddr);
> +	  if (name == NULL)
> +	    continue;
> +	  shndx = get_section (funcaddr);
> +	  found_sym (&sym, shndx, name, funcaddr);
> +	}
> +    }

This seems to do a bit too much inside the loop.
The _libdwfl_module_getebl () can be moved outside.
You should also not call found_sym () twice and always give the backend
a chance to filter the symbols first if necessary, found_sym () also
already checks for a NULL name, so it can be simplified to something
like:

  const char *name = INTUSE(dwfl_module_getsym) (mod, i, &sym, &shndx);
  GElf_Addr ret_addr;
  if (code_only)
    name = ebl_get_func_pc (mod->ebl, mod, &sym, &ret_addr);
  else
    ret_addr = sym.st_value;
  shndx = get_section (ret_addr);
  found_sym (&sym, shndx, name, ret_addr);

Also normally I assume the name wouldn't be changed (if at all) in the
backend function, so you might want to pass that through so in the
normal case the backend function can just return the name as is (or NULL
when it decides this isn't a code symbol).

Cheers,

Mark



More information about the elfutils-devel mailing list