This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH v2 13/15] PPC64: always make synthetic .text symbols for GNU ifunc symbols


Dear binutils friends,

This is a bfd patch that is part of a larger gdb patch series,
whose cover letter is found here:
  https://sourceware.org/ml/gdb-patches/2018-03/msg00504.html

Thanks,
Pedro Alves

On 03/25/2018 08:19 PM, Pedro Alves wrote:
> If you create an ifunc using GCC's __attribute__ ifunc, like:
> 
>  extern int gnu_ifunc (int arg);
>  static int gnu_ifunc_target (int arg) { return 0; }
>  __typeof (gnu_ifunc) *gnu_ifunc_resolver (unsigned long hwcap) { return gnu_ifunc_target; }
>  __typeof (gnu_ifunc) gnu_ifunc __attribute__ ((ifunc ("gnu_ifunc_resolver")));
> 
> then you end up with two (function descriptor) symbols, one for the
> ifunc itself, and another for the resolver:
> 
>    (...)
>    12: 0000000000020060    104 FUNC    GLOBAL DEFAULT       18 gnu_ifunc_resolver
>    (...)
>    16: 0000000000020060    104 GNU_IFUNC GLOBAL DEFAULT       18 gnu_ifunc
>    (...)
> 
> Both ifunc and resolver symbols have the same address/value, so
> ppc64_elf_get_synthetic_symtab only creates a synthetic text symbol
> for one of them.  In the case above, it ends up being created for the
> resolver, only:
> 
>   (gdb) maint print msymbols
>   (...)
>   [ 7] t 0x980 .frame_dummy section .text
>   [ 8] T 0x9e4 .gnu_ifunc_resolver section .text
>   [ 9] T 0xa58 __glink_PLTresolve section .text
>   (...)
> 
> GDB needs to know when a program stepped into an ifunc resolver, so
> that it can know whether to step past the resolver into the target
> function without the user noticing.  The way GDB does it is my
> checking whether the current PC points to an ifunc symbol (since
> resolver and ifunc have the same address by design).
> 
> The problem is then that ppc64_elf_get_synthetic_symtab never creates
> the synchetic symbol for the ifunc, so GDB stops stepping at the
> resolver (in a test added by the following patch):
> 
>   (gdb) step
>   gnu_ifunc_resolver (hwcap=21) at gdb/testsuite/gdb.base/gnu-ifunc-lib.c:33
>   33      {
>   (gdb) FAIL: gdb.base/gnu-ifunc.exp: resolver_attr=1: resolver_debug=1: final_debug=0: step
> 
> After this commit, we get:
> 
>   [ 8] i 0x9e4 .gnu_ifunc section .text
>   [ 9] T 0x9e4 .gnu_ifunc_resolver section .text
> 
> And stepping an ifunc call takes to the final function:
>   (gdb) step
>   0x00000000100009e8 in .final ()
>   (gdb) PASS: gdb.base/gnu-ifunc.exp: resolver_attr=1: resolver_debug=1: final_debug=0: step
> 
> An alternative to touching bfd I considered was for GDB to check
> whether there's an ifunc data symbol / function descriptor that points
> to the current PC, whenever the program stops, but discarded it
> because we'd have to do a linear scan over .opd over an over to find a
> matching function descriptor for the current PC.  At that point I
> considered caching that info, but quickly dismissed it as then that
> has no advantage (memory or performance) over just creating the
> synthetic ifunc text symbol in the first place.
> 
> I ran the binutils and ld testsuites on PPC64 ELFv1 (machine gcc110 on
> the GCC compile farm), and saw no regressions.  This commit is part of
> a GDB patch series that includes GDB tests that fail without this fix.
> 
> OK to apply?
> 
> bfd/ChangeLog:
> yyyy-mm-dd  Pedro Alves  <palves@redhat.com>
> 
> 	* elf64-ppc.c (ppc64_elf_get_synthetic_symtab): Don't consider
> 	ifunc and non-ifunc symbols duplicates.
> ---
>  bfd/elf64-ppc.c | 22 ++++++++++++++++------
>  1 file changed, 16 insertions(+), 6 deletions(-)
> 
> diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
> index 751ad778b26..791ec49b73d 100644
> --- a/bfd/elf64-ppc.c
> +++ b/bfd/elf64-ppc.c
> @@ -3330,13 +3330,23 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
>  
>        if (!relocatable && symcount > 1)
>  	{
> -	  /* Trim duplicate syms, since we may have merged the normal and
> -	     dynamic symbols.  Actually, we only care about syms that have
> -	     different values, so trim any with the same value.  */
> +	  /* Trim duplicate syms, since we may have merged the normal
> +	     and dynamic symbols.  Actually, we only care about syms
> +	     that have different values, so trim any with the same
> +	     value.  Don't consider ifunc and ifunc resolver symbols
> +	     duplicates however, because GDB wants to know whether a
> +	     text symbol is an ifunc resolver.  */
>  	  for (i = 1, j = 1; i < symcount; ++i)
> -	    if (syms[i - 1]->value + syms[i - 1]->section->vma
> -		!= syms[i]->value + syms[i]->section->vma)
> -	      syms[j++] = syms[i];
> +	    {
> +	      const asymbol *s0 = syms[i - 1];
> +	      const asymbol *s1 = syms[i];
> +
> +	      if ((s0->value + s0->section->vma
> +		   != s1->value + s1->section->vma)
> +		  || ((s0->flags & BSF_GNU_INDIRECT_FUNCTION)
> +		      != (s1->flags & BSF_GNU_INDIRECT_FUNCTION)))
> +		syms[j++] = syms[i];
> +	    }
>  	  symcount = j;
>  	}
>  
> 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]