S/390: ifunc: Handle GOTOFF relocs on ifunc symbols.

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.
This commit is contained in:
Andreas Krebbel 2015-10-16 21:07:17 +02:00
parent 0f042c67a0
commit 01a5358479
2 changed files with 31 additions and 2 deletions

View File

@ -1,3 +1,12 @@
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

View 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