From 0bed072fb1753bd88fa624f88b2fd7aeeaf2f3be Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 27 Mar 2013 13:25:48 +0000 Subject: [PATCH] * 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. --- bfd/ChangeLog | 8 ++++++++ bfd/elf32-ppc.c | 37 ++++++++++++++++++++++++------------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 6d3e973..6253a24 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2013-03-27 Alan Modra + + * 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. + 2013-03-27 Will Newton * elf32-arm.c (elf32_arm_final_link_relocate): Avoid emitting a diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index c05f2f0..05d6e35 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -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_entry *h, void *inf) || 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 *output_bfd ATTRIBUTE_UNUSED, { *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_bfd, 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); -- 2.7.4