PPC64: always make synthetic .text symbols for GNU ifunc symbols
authorPedro Alves <palves@redhat.com>
Thu, 26 Apr 2018 12:01:27 +0000 (13:01 +0100)
committerPedro Alves <palves@redhat.com>
Thu, 26 Apr 2018 12:09:40 +0000 (13:09 +0100)
commitbfa5bd2ab31a8abb23cb442d51fe6c3836028880
treea1432300e4bc11c81a1b2251c897d1f42dddae36
parentf50776aad58a1df6b8f7f2a7d25a3b10aa074f7b
PPC64: always make synthetic .text symbols for GNU ifunc symbols

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.

bfd/ChangeLog:
2018-04-26  Pedro Alves  <palves@redhat.com>

* elf64-ppc.c (ppc64_elf_get_synthetic_symtab): Don't consider
ifunc and non-ifunc symbols duplicates.
bfd/ChangeLog
bfd/elf64-ppc.c
This page took 0.029494 seconds and 4 git commands to generate.