S/390: ifunc: Handle GOTOFF relocs on ifunc symbols.
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Fri, 16 Oct 2015 19:07:17 +0000 (21:07 +0200)
committerAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Thu, 22 Oct 2015 08:11:57 +0000 (10:11 +0200)
Normally a GOTOFF reloc only uses the GOT pointer to address something
relativ to it without actually requiring a GOT or PLT slot.  Things
change if the target is an ifunc symbol though.

bfd/ChangeLog:

* elf32-s390.c (elf_s390_check_relocs): Fallthrough to the PLT
slot allocating code for GOTOFF relocs on ifunc symbols.
(elf_s390_gc_sweep_hook): Decrement plt refcount for GOTOFF relocs
on ifunc symbols.
(elf_s390_relocate_section): Redirect a GOTOFF reloc to an iplt
slot.

bfd/ChangeLog
bfd/elf32-s390.c

index 0ab1aed..86a8ce8 100644 (file)
@@ -1,5 +1,14 @@
 2015-10-22  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
+       * elf32-s390.c (elf_s390_check_relocs): Fallthrough to the PLT
+       slot allocating code for GOTOFF relocs on ifunc symbols.
+       (elf_s390_gc_sweep_hook): Decrement plt refcount for GOTOFF relocs
+       on ifunc symbols.
+       (elf_s390_relocate_section): Redirect a GOTOFF reloc to an iplt
+       slot.
+
+2015-10-22  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
+
        PR ld/18841
        * elf32-s390.c (elf_s390_reloc_type_class): Return
        reloc_class_ifunc for ifunc symbols.
index b1f9dbc..fcdade0 100644 (file)
@@ -1112,8 +1112,6 @@ elf_s390_check_relocs (bfd *abfd,
        }
       switch (r_type)
        {
-       case R_390_GOTOFF16:
-       case R_390_GOTOFF32:
        case R_390_GOTPC:
        case R_390_GOTPCDBL:
          /* These relocs do not need a GOT slot.  They just load the
@@ -1121,6 +1119,10 @@ elf_s390_check_relocs (bfd *abfd,
             the GOT.  Since the GOT pointer has been set up above we
             are done.  */
          break;
+       case R_390_GOTOFF16:
+       case R_390_GOTOFF32:
+         if (h == NULL || !s390_is_ifunc_symbol_p (h) || !h->def_regular)
+           break;
 
        case R_390_PLT12DBL:
        case R_390_PLT16DBL:
@@ -1529,6 +1531,12 @@ elf_s390_gc_sweep_hook (bfd *abfd,
 
        case R_390_GOTOFF16:
        case R_390_GOTOFF32:
+         if (s390_is_ifunc_symbol_p (h) && h->def_regular)
+           {
+             h->plt.refcount--;
+             break;
+           }
+
        case R_390_GOTPC:
        case R_390_GOTPCDBL:
          break;
@@ -2640,6 +2648,18 @@ elf_s390_relocate_section (bfd *output_bfd,
          /* Relocation is relative to the start of the global offset
             table.  */
 
+         if (h != NULL
+             && s390_is_ifunc_symbol_p (h)
+             && h->def_regular
+             && !bfd_link_executable (info))
+           {
+             relocation = (htab->elf.iplt->output_section->vma
+                           + htab->elf.iplt->output_offset
+                           + h->plt.offset
+                           - htab->elf.sgot->output_section->vma);
+             goto do_relocation;
+           }
+
          /* Note that sgot->output_offset is not involved in this
             calculation.  We always want the start of .got.  If we
             defined _GLOBAL_OFFSET_TABLE in a different way, as is