ppc32 -fPIC and ifunc

Alan Modra amodra@gmail.com
Mon Mar 4 12:11:00 GMT 2013


I noticed today that ppc32 -fPIC code calling STT_GNU_IFUNC functions
was seriously broken by BFD ld, with the branch and link to the plt
call stub missing the stub by 32k.  Fixed by ensuring the addend on
R_PPC_PLTREL24 relocs is zeroed before applying.

The first hunk of this patch also tweaks ld -r adjustment of these
addends, for consistency with other code.  The addends are either zero
or >= 32768, so there is no real functional change there.

Applying mainline and 2.23

	* elf32-ppc.c (ppc_elf_relocate_section <R_PPC_PLTREL24>): Adjust
	non-zero addends when relocatable, rather than addends >= 32768.
	Always zero "addend" before applying relocation.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.326
diff -u -p -r1.326 elf32-ppc.c
--- bfd/elf32-ppc.c	21 Feb 2013 03:02:29 -0000	1.326
+++ bfd/elf32-ppc.c	4 Mar 2013 10:03:56 -0000
@@ -7472,7 +7472,7 @@ ppc_elf_relocate_section (bfd *output_bf
 	{
 	  if (got2 != NULL
 	      && r_type == R_PPC_PLTREL24
-	      && rel->r_addend >= 32768)
+	      && rel->r_addend != 0)
 	    {
 	      /* R_PPC_PLTREL24 is rather special.  If non-zero, the
 		 addend specifies the GOT pointer offset within .got2.  */
@@ -8477,33 +8477,37 @@ ppc_elf_relocate_section (bfd *output_bf
 	  break;
 
 	case R_PPC_PLTREL24:
-	  if (h == NULL || ifunc != NULL)
-	    break;
-	  /* Relocation is to the entry for this symbol in the
-	     procedure linkage table.  */
-	  {
-	    struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2,
-						  info->shared ? addend : 0);
-	    addend = 0;
-	    if (ent == NULL
-		|| htab->plt == NULL)
-	      {
-		/* We didn't make a PLT entry for this symbol.  This
-		   happens when statically linking PIC code, or when
-		   using -Bsymbolic.  */
-		break;
-	      }
+	  if (h != NULL && ifunc == NULL)
+	    {
+	      struct plt_entry *ent = find_plt_ent (&h->plt.plist, got2,
+						    info->shared ? addend : 0);
+	      if (ent == NULL
+		  || htab->plt == NULL)
+		{
+		  /* We didn't make a PLT entry for this symbol.  This
+		     happens when statically linking PIC code, or when
+		     using -Bsymbolic.  */
+		}
+	      else
+		{
+		  /* Relocation is to the entry for this symbol in the
+		     procedure linkage table.  */
+		  unresolved_reloc = FALSE;
+		  if (htab->plt_type == PLT_NEW)
+		    relocation = (htab->glink->output_section->vma
+				  + htab->glink->output_offset
+				  + ent->glink_offset);
+		  else
+		    relocation = (htab->plt->output_section->vma
+				  + htab->plt->output_offset
+				  + ent->plt.offset);
+		}
+	    }
 
-	    unresolved_reloc = FALSE;
-	    if (htab->plt_type == PLT_NEW)
-	      relocation = (htab->glink->output_section->vma
-			    + htab->glink->output_offset
-			    + ent->glink_offset);
-	    else
-	      relocation = (htab->plt->output_section->vma
-			    + htab->plt->output_offset
-			    + ent->plt.offset);
-	  }
+	  /* R_PPC_PLTREL24 is rather special.  If non-zero, the
+	     addend specifies the GOT pointer offset within .got2.
+	     Don't apply it to the relocation field.  */
+	  addend = 0;
 	  break;
 
 	  /* Relocate against _SDA_BASE_.  */

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list