This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]