Error on unsupported PowerPC ifuncs

Alan Modra amodra@gmail.com
Mon Aug 22 01:29:00 GMT 2016


The pr19784 tests fail on ppc32 due to a gcc bug.  The failure should
be noticed when building both libpr19784a.so and libpr19784b.so,
rather than ld building a buggy libpr19784a.so that fails at run time.
This patch fixes that by moving the @local ifunc check out of
check_relocs, where a call destination may not yet be known to be
ifunc.  The patch also adds a related error for -mbss-plt code.

	* elf32-ppc.c (ppc_elf_check_relocs): Move error for @local ifunc..
	(ppc_elf_relocate_section): ..to here.  Comment.  Error on
	detecting -mbss-plt -fPIC local ifuncs too.
	(ppc_elf_size_dynamic_sections): Comment on unnecessary glink
	branch table entries.

diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 8d5131a..92299bc 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -4390,15 +4390,6 @@ ppc_elf_check_relocs (bfd *abfd,
 	    }
 	  if (h != NULL && h->type == STT_GNU_IFUNC)
 	    {
-	      if (bfd_link_pic (info))
-		{
-		  info->callbacks->einfo
-		    (_("%P: %H: @local call to ifunc %s\n"),
-		     abfd, sec, rel->r_offset,
-		     h->root.root.string);
-		  bfd_set_error (bfd_error_bad_value);
-		  return FALSE;
-		}
 	      h->needs_plt = 1;
 	      if (!update_plt_info (abfd, &h->plt.plist, NULL, 0))
 		return FALSE;
@@ -6504,7 +6495,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
       && htab->elf.dynamic_sections_created)
     {
       htab->glink_pltresolve = htab->glink->size;
-      /* Space for the branch table.  */
+      /* Space for the branch table.  ??? We don't need entries for
+	 non-dynamic symbols in this table.  This case can arise with
+	 static ifuncs or forced local ifuncs.  */
       htab->glink->size += htab->glink->size / (GLINK_ENTRY_SIZE / 4) - 4;
       /* Pad out to align the start of PLTresolve.  */
       htab->glink->size += -htab->glink->size & (htab->params->ppc476_workaround
@@ -8308,6 +8301,26 @@ ppc_elf_relocate_section (bfd *output_bfd,
 	    }
 	  if (ent != NULL)
 	    {
+	      if (bfd_link_pic (info)
+		  && ent->sec != got2
+		  && htab->plt_type != PLT_NEW
+		  && (!htab->elf.dynamic_sections_created
+		      || h == NULL
+		      || h->dynindx == -1))
+		{
+		  /* Uh oh, we are going to create a pic glink stub
+		     for an ifunc (here for h == NULL and later in
+		     finish_dynamic_symbol for h != NULL), and
+		     apparently are using code compiled with
+		     -mbss-plt.  The difficulty is that -mbss-plt code
+		     gives no indication via a magic PLTREL24 addend
+		     whether r30 is equal to _GLOBAL_OFFSET_TABLE_ or
+		     is pointing into a .got2 section (and how far
+		     into .got2).  */
+		    info->callbacks->einfo
+		      (_("%X%P: %H: unsupported bss-plt -fPIC ifunc %s\n"),
+		       input_bfd, input_section, rel->r_offset, sym_name);
+		}
 	      if (h == NULL && (ent->plt.offset & 1) == 0)
 		{
 		  Elf_Internal_Rela rela;
@@ -8656,6 +8669,20 @@ ppc_elf_relocate_section (bfd *output_bfd,
 						    TRUE);
 	      goto copy_reloc;
 	    }
+	  if (h != NULL && h->type == STT_GNU_IFUNC && bfd_link_pic (info))
+	    {
+	      /* @local on an ifunc does not really make sense since
+		 the ifunc resolver can take you anywhere.  More
+		 seriously, calls to ifuncs must go through a plt call
+		 stub, and for pic the plt call stubs uses r30 to
+		 access the PLT.  The problem is that a call that is
+		 local won't have the +32k reloc addend trick marking
+		 -fPIC code, so the linker won't know whether r30 is
+		 _GLOBAL_OFFSET_TABLE_ or pointing into a .got2 section.  */
+	      info->callbacks->einfo (_("%X%P: %H: @local call to ifunc %s\n"),
+				      input_bfd, input_section, rel->r_offset,
+				      h->root.root.string);
+	    }
 	  break;
 
 	case R_PPC_DTPREL16:

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list