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]

Re: PowerPC STT_GNU_IFUNC support


On Mon, Aug 03, 2009 at 07:52:07PM +0930, Alan Modra wrote:
> With this patch, all the current
> glibc ifunc tests pass on powerpc (with my both my glibc patches
> applied of course).

I lied.  I'm sure I ran glibc "make check" without seeing any errors,
but a glibc "make check" doesn't even run tests if the test binaries
are up to date with respect to their sources and libc.so/libc.a etc.
This is fine if you're just working on glibc, but not so nice if
you're also messing with gcc and/or binutils, ie. when test binaries
have a dependency on other parts of the toolchain.  (Not that this is
news to me.  I guess I just forgot to rm test binaries.)

This patch really does cure the glibc ifunc test failures.

A note on the patch:  The powerpc backend doesn't set needs_plt on all
ifunc syms, as the x86 backend does (*).  needs_plt instead is used to
signify that the reloc type (eg. one used on a branch insn) implies
the possible need of a plt entry.  Thus the need for the elflink.c
patch.

*) x86 fails to do so reliably, because at the time check_relocs is
called you don't know for sure whether a symbol is ifunc or not.  An
undefined symbol might later turn out to be ifunc.  To reliably set
needs_plt on all ifunc syms via check_relocs, you'd need to set
needs_plt on all undefined syms too, but that would likely create
unnecessary plt entries.

	* elflink.c (_bfd_elf_adjust_dynamic_symbol): Don't clear plt
	info for STT_GNU_IFUNC.
	* elf32-ppc.c (ppc_elf_check_relocs): Count a needed plt entry
	on got refs in case the symbol turns out to be ifunc.
	(ppc_elf_gc_sweep_hook): Similarly.
	(ppc_elf_adjust_dynamic_symbol): Adjust assertion.
	(allocate_dynrelocs): Don't specially allocate got relocs for ifunc.
	(ppc_elf_size_dynamic_sections): Likewise.
	(ppc_elf_relocate_section): Likewise.

Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.350
diff -u -p -r1.350 elflink.c
--- bfd/elflink.c	23 Jul 2009 13:00:20 -0000	1.350
+++ bfd/elflink.c	10 Aug 2009 01:37:56 -0000
@@ -2605,6 +2605,7 @@ _bfd_elf_adjust_dynamic_symbol (struct e
      about symbols which are defined by one dynamic object and
      referenced by another one?  */
   if (!h->needs_plt
+      && h->type != STT_GNU_IFUNC
       && (h->def_regular
 	  || !h->def_dynamic
 	  || (!h->ref_regular
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.264
diff -u -p -r1.264 elf32-ppc.c
--- bfd/elf32-ppc.c	4 Aug 2009 08:03:35 -0000	1.264
+++ bfd/elf32-ppc.c	10 Aug 2009 01:37:58 -0000
@@ -3580,6 +3580,14 @@ ppc_elf_check_relocs (bfd *abfd,
 	    /* This is a global offset table entry for a local symbol.  */
 	    if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, tls_type))
 	      return FALSE;
+
+	  /* We may also need a plt entry if the symbol turns out to be
+	     an ifunc.  */
+	  if (h != NULL && !info->shared)
+	    {
+	      if (!update_plt_info (abfd, &h->plt.plist, NULL, 0))
+		return FALSE;
+	    }
 	  break;
 
 	  /* Indirect .sdata relocation.  */
@@ -4465,6 +4473,14 @@ ppc_elf_gc_sweep_hook (bfd *abfd,
 	    {
 	      if (h->got.refcount > 0)
 		h->got.refcount--;
+	      if (!info->shared)
+		{
+		  struct plt_entry *ent;
+
+		  ent = find_plt_ent (&h->plt.plist, NULL, 0);
+		  if (ent->plt.refcount > 0)
+		    ent->plt.refcount -= 1;
+		}
 	    }
 	  else if (local_got_refcounts != NULL)
 	    {
@@ -4827,6 +4843,7 @@ ppc_elf_adjust_dynamic_symbol (struct bf
   htab = ppc_elf_hash_table (info);
   BFD_ASSERT (htab->elf.dynobj != NULL
 	      && (h->needs_plt
+		  || h->type == STT_GNU_IFUNC
 		  || h->u.weakdef != NULL
 		  || (h->def_dynamic
 		      && h->ref_regular
@@ -5289,18 +5306,14 @@ allocate_dynrelocs (struct elf_link_hash
 	eh->elf.got.offset = (bfd_vma) -1;
       else
 	{
-	  asection *rsec = NULL;
 	  eh->elf.got.offset = allocate_got (htab, need);
 	  dyn = htab->elf.dynamic_sections_created;
 	  if ((info->shared
 	       || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf))
 	      && (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT
 		  || eh->elf.root.type != bfd_link_hash_undefweak))
-	    rsec = htab->relgot;
-	  else if (h->type == STT_GNU_IFUNC)
-	    rsec = htab->reliplt;
-	  if (rsec != NULL)
 	    {
+	      asection *rsec = htab->relgot;
 	      /* All the entries we allocated need relocs.
 		 Except LD only needs one.  */
 	      if ((eh->tls_mask & TLS_LD) != 0
@@ -5571,9 +5584,6 @@ ppc_elf_size_dynamic_sections (bfd *outp
 		if (info->shared)
 		  htab->relgot->size += (need
 					 * (sizeof (Elf32_External_Rela) / 4));
-		else if ((*lgot_masks & PLT_IFUNC) != 0)
-		  htab->reliplt->size += (need
-					  * (sizeof (Elf32_External_Rela) / 4));
 	      }
 	  }
 	else
@@ -7137,7 +7148,6 @@ ppc_elf_relocate_section (bfd *output_bf
 	      off &= ~1;
 	    else
 	      {
-		asection *rsec;
 		unsigned int tls_m = (tls_mask
 				      & (TLS_LD | TLS_GD | TLS_DTPREL
 					 | TLS_TPREL | TLS_TPRELGD));
@@ -7176,17 +7186,14 @@ ppc_elf_relocate_section (bfd *output_bf
 		      }
 
 		    /* Generate relocs for the dynamic linker.  */
-		    rsec = NULL;
 		    if ((info->shared || indx != 0)
 			&& (offp == &htab->tlsld_got.offset
 			    || h == NULL
 			    || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
 			    || h->root.type != bfd_link_hash_undefweak))
-		      rsec = htab->relgot;
-		    else if (ifunc != NULL)
-		      rsec = htab->reliplt;
-		    if (rsec != NULL)
 		      {
+			asection *rsec = htab->relgot;
+
 			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]