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]

PowerpC pointer_equality_needed optimisation


This implements Jakub's pointer_equality_needed optimisation for
PowerPC.  x86 and x86_64 maintainers might like to copy the warning
I added for weak symbols in ppc_elf_finish_dynamic_symbol.

	* elf32-ppc.c (ppc_elf_copy_indirect_symbol): Copy
	pointer_equality_needed.
	(ppc_elf_check_relocs): Split out non-branch relocs from others
	that might emit dynamic relocs.  Set pointer_equality_needed
	for their symbols.  Don't set non_got_ref on branch reloc symbols.
	(ppc_elf_hash_symbol): New function.
	(elf_backend_hash_symbol): Define.
	(ppc_elf_finish_dynamic_symbol): Handle pointer_equality_needed.
	Error if pointer_equality_needed on weak plt symbol.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.229
diff -u -p -r1.229 elf32-ppc.c
--- bfd/elf32-ppc.c	20 Feb 2008 17:42:35 -0000	1.229
+++ bfd/elf32-ppc.c	23 Feb 2008 01:41:44 -0000
@@ -2696,6 +2696,7 @@ ppc_elf_copy_indirect_symbol (struct bfd
   edir->elf.ref_regular |= eind->elf.ref_regular;
   edir->elf.ref_regular_nonweak |= eind->elf.ref_regular_nonweak;
   edir->elf.needs_plt |= eind->elf.needs_plt;
+  edir->elf.pointer_equality_needed |= eind->elf.pointer_equality_needed;
 
   /* If we were called to copy over info for a weak sym, that's all.  */
   if (eind->elf.root.type != bfd_link_hash_indirect)
@@ -3388,6 +3389,26 @@ ppc_elf_check_relocs (bfd *abfd,
 	    info->flags |= DF_STATIC_TLS;
 	  goto dodyn;
 
+	case R_PPC_ADDR32:
+	case R_PPC_ADDR16:
+	case R_PPC_ADDR16_LO:
+	case R_PPC_ADDR16_HI:
+	case R_PPC_ADDR16_HA:
+	case R_PPC_UADDR32:
+	case R_PPC_UADDR16:
+	  if (h != NULL && !info->shared)
+	    {
+	      /* We may need a plt entry if the symbol turns out to be
+		 a function defined in a dynamic object.  */
+	      if (!update_plt_info (abfd, h, NULL, 0))
+		return FALSE;
+
+	      /* We may need a copy reloc too.  */
+	      h->non_got_ref = 1;
+	      h->pointer_equality_needed = 1;
+	    }
+	  goto dodyn;
+
 	case R_PPC_REL32:
 	  if (h == NULL
 	      && got2 != NULL
@@ -3432,17 +3453,10 @@ ppc_elf_check_relocs (bfd *abfd,
 	    }
 	  /* fall through */
 
-	case R_PPC_ADDR32:
 	case R_PPC_ADDR24:
-	case R_PPC_ADDR16:
-	case R_PPC_ADDR16_LO:
-	case R_PPC_ADDR16_HI:
-	case R_PPC_ADDR16_HA:
 	case R_PPC_ADDR14:
 	case R_PPC_ADDR14_BRTAKEN:
 	case R_PPC_ADDR14_BRNTAKEN:
-	case R_PPC_UADDR32:
-	case R_PPC_UADDR16:
 	dodyn1:
 	  if (h != NULL && !info->shared)
 	    {
@@ -3450,9 +3464,6 @@ ppc_elf_check_relocs (bfd *abfd,
 		 a function defined in a dynamic object.  */
 	      if (!update_plt_info (abfd, h, NULL, 0))
 		return FALSE;
-
-	      /* We may need a copy reloc too.  */
-	      h->non_got_ref = 1;
 	    }
 
 	dodyn:
@@ -5186,6 +5197,20 @@ ppc_elf_size_dynamic_sections (bfd *outp
 
   return TRUE;
 }
+
+/* Return TRUE if symbol should be hashed in the `.gnu.hash' section.  */
+
+static bfd_boolean
+ppc_elf_hash_symbol (struct elf_link_hash_entry *h)
+{
+  if (h->plt.plist != NULL
+      && !h->def_regular
+      && (!h->pointer_equality_needed
+	  || !h->ref_regular_nonweak))
+    return FALSE;
+
+  return _bfd_elf_hash_symbol (h);
+}
 
 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
 
@@ -7127,15 +7152,28 @@ ppc_elf_finish_dynamic_symbol (bfd *outp
 
 	    if (!h->def_regular)
 	      {
-		/* Mark the symbol as undefined, rather than as defined in
-		   the .plt section.  Leave the value alone.  */
+		/* Mark the symbol as undefined, rather than as
+		   defined in the .plt section.  Leave the value if
+		   there were any relocations where pointer equality
+		   matters (this is a clue for the dynamic linker, to
+		   make function pointer comparisons work between an
+		   application and shared library), otherwise set it
+		   to zero.  */
 		sym->st_shndx = SHN_UNDEF;
-		/* If the symbol is weak, we do need to clear the value.
-		   Otherwise, the PLT entry would provide a definition for
-		   the symbol even if the symbol wasn't defined anywhere,
-		   and so the symbol would never be NULL.  */
-		if (!h->ref_regular_nonweak)
+		if (!h->pointer_equality_needed)
 		  sym->st_value = 0;
+		else if (!h->ref_regular_nonweak)
+		  {
+		    /* Choose your poison.  We must have either text
+		       dynamic relocations, broken function pointer
+		       comparisons, or broken tests for a NULL
+		       function pointer.  */
+		    (*_bfd_error_handler)
+		      (_("weak reference to %s in non-pic code"
+			 " will break function pointer comparisons"),
+		       h->root.root.string);
+		    sym->st_value = 0;
+		  }
 	      }
 	    doneone = TRUE;
 	  }
@@ -7687,6 +7725,7 @@ ppc_elf_finish_dynamic_sections (bfd *ou
 #define elf_backend_adjust_dynamic_symbol	ppc_elf_adjust_dynamic_symbol
 #define elf_backend_add_symbol_hook		ppc_elf_add_symbol_hook
 #define elf_backend_size_dynamic_sections	ppc_elf_size_dynamic_sections
+#define elf_backend_hash_symbol			ppc_elf_hash_symbol
 #define elf_backend_finish_dynamic_symbol	ppc_elf_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections	ppc_elf_finish_dynamic_sections
 #define elf_backend_fake_sections		ppc_elf_fake_sections

-- 
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]