This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
GNU ld ifunc dynamic relocation order
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org
- Date: Wed, 27 Mar 2013 23:54:30 +1030
- Subject: GNU ld ifunc dynamic relocation order
This patch series is aimed at fixing STT_GNU_IFUNC dynamic relocation
order within a single powerpc binary. Ideally, you'd like ld.so to
apply ifunc relocations last, so that ifunc resolver functions in the
binary can access variables via the GOT. The first part here takes
care to lay out relocations in the proper order in the backend.
* elf32-ppc.c (ppc_elf_check_relocs): Set PLT_IFUNC in local got
masks for all local ifunc syms.
(allocate_dynrelocs): Don't use htab->relgot for ifunc.
(ppc_elf_size_dynamic_sections): Likewise.
(ppc_elf_relocate_section): Likewise.
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.327
diff -u -p -r1.327 elf32-ppc.c
--- bfd/elf32-ppc.c 4 Mar 2013 12:12:11 -0000 1.327
+++ bfd/elf32-ppc.c 27 Mar 2013 10:50:56 -0000
@@ -3921,13 +3921,11 @@ ppc_elf_check_relocs (bfd *abfd,
if (isym == NULL)
return FALSE;
- if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC
- && (!info->shared
- || is_branch_reloc (r_type)))
+ if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
{
struct plt_entry **ifunc;
- bfd_vma addend;
+ /* Set PLT_IFUNC flag for this sym, no GOT entry yet. */
ifunc = update_local_sym_info (abfd, symtab_hdr, r_symndx,
PLT_IFUNC);
if (ifunc == NULL)
@@ -3936,15 +3934,19 @@ ppc_elf_check_relocs (bfd *abfd,
/* STT_GNU_IFUNC symbols must have a PLT entry;
In a non-pie executable even when there are
no plt calls. */
- addend = 0;
- if (r_type == R_PPC_PLTREL24)
+ if (!info->shared
+ || is_branch_reloc (r_type))
{
- ppc_elf_tdata (abfd)->makes_plt_call = 1;
- if (info->shared)
- addend = rel->r_addend;
+ bfd_vma addend = 0;
+ if (r_type == R_PPC_PLTREL24)
+ {
+ ppc_elf_tdata (abfd)->makes_plt_call = 1;
+ if (info->shared)
+ addend = rel->r_addend;
+ }
+ if (!update_plt_info (abfd, ifunc, got2, addend))
+ return FALSE;
}
- if (!update_plt_info (abfd, ifunc, got2, addend))
- return FALSE;
}
}
@@ -5901,6 +5903,9 @@ allocate_dynrelocs (struct elf_link_hash
|| eh->elf.root.type != bfd_link_hash_undefweak))
{
asection *rsec = htab->relgot;
+
+ if (eh->elf.type == STT_GNU_IFUNC)
+ rsec = htab->reliplt;
/* All the entries we allocated need relocs.
Except LD only needs one. */
if ((eh->tls_mask & TLS_LD) != 0
@@ -6181,8 +6186,12 @@ ppc_elf_size_dynamic_sections (bfd *outp
{
*local_got = allocate_got (htab, need);
if (info->shared)
- htab->relgot->size += (need
- * (sizeof (Elf32_External_Rela) / 4));
+ {
+ asection *srel = htab->relgot;
+ if ((*lgot_masks & PLT_IFUNC) != 0)
+ srel = htab->reliplt;
+ srel->size += need * (sizeof (Elf32_External_Rela) / 4);
+ }
}
}
else
@@ -7987,6 +7996,8 @@ ppc_elf_relocate_section (bfd *output_bf
asection *rsec = htab->relgot;
bfd_byte * loc;
+ if (ifunc != NULL)
+ rsec = htab->reliplt;
outrel.r_offset = (htab->got->output_section->vma
+ htab->got->output_offset
+ off);
--
Alan Modra
Australia Development Lab, IBM