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]

Fix undefined weak hidden syms for MIPS shared libraries


This patch goes along with the testcase in my previous message.  We
were always emitting a dynamic relocation for even undefined weak
symbols, but nothing marked them as dynamic, so the relocation got
symndx 0xffffff.  The consensus seems to be that relocations should be
emitted in shared libraries if default visibility, and clearly no
relocation is necessary for non-default visibility, so that's what
I've implemented.

Like other ports, MIPS now needs an allocate_dynrelocs routine.
adjust_dynamic_symbol is not good enough, since the symbol might not
be dynamic.

Tested on mips64-linux and committed.  This almost certainly fixes the
Debian mklibs utility on MIPS; my initial testcase was a reduced
version of glibc.

-- 
Daniel Jacobowitz
CodeSourcery

2008-07-28  Daniel Jacobowitz  <dan@codesourcery.com>

	* elfxx-mips.c (mips_elf_calculate_relocation): Avoid generating
	relocations for undefined weak symbols with non-default visibility.
	(_bfd_mips_elf_check_relocs): Use possibly_dynamic_relocs for
	global symbols in shared libraries.
	(allocate_dynrelocs): New function.
	(_bfd_mips_elf_adjust_dynamic_symbol): Do not handle
	possibly_dynamic_relocs here.
	(_bfd_mips_elf_size_dynamic_sections): Call allocate_dynrelocs.

Index: elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.234
diff -u -p -r1.234 elfxx-mips.c
--- elfxx-mips.c	10 Jul 2008 19:06:53 -0000	1.234
+++ elfxx-mips.c	28 Jul 2008 22:13:42 -0000
@@ -4509,6 +4509,9 @@ mips_elf_calculate_relocation (bfd *abfd
 	       && h->root.def_dynamic
 	       && !h->root.def_regular))
 	  && r_symndx != 0
+	  && (h == NULL
+	      || h->root.root.type != bfd_link_hash_undefweak
+	      || ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
 	  && (input_section->flags & SEC_ALLOC) != 0)
 	{
 	  /* If we're creating a shared library, or this relocation is
@@ -7008,7 +7011,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 		  if (sreloc == NULL)
 		    return FALSE;
 		}
-	      if (info->shared)
+	      if (info->shared && h == NULL)
 		{
 		  /* When creating a shared object, we must copy these
 		     reloc types into the output file as R_MIPS_REL32
@@ -7023,8 +7026,17 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
 		{
 		  struct mips_elf_link_hash_entry *hmips;
 
-		  /* We only need to copy this reloc if the symbol is
-                     defined in a dynamic object.  */
+		  /* For a shared object, we must copy this relocation
+		     unless the symbol turns out to be undefined and
+		     weak with non-default visibility, in which case
+		     it will be left as zero.
+
+		     We could elide R_MIPS_REL32 for locally binding symbols
+		     in shared libraries, but do not yet do so.
+
+		     For an executable, we only need to copy this
+		     reloc if the symbol is defined in a dynamic
+		     object.  */
 		  hmips = (struct mips_elf_link_hash_entry *) h;
 		  ++hmips->possibly_dynamic_relocs;
 		  if (MIPS_ELF_READONLY_SECTION (sec))
@@ -7289,6 +7301,66 @@ _bfd_mips_relax_section (bfd *abfd, asec
   return FALSE;
 }
 
+/* Allocate space for global sym dynamic relocs.  */
+
+static bfd_boolean
+allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
+{
+  struct bfd_link_info *info = inf;
+  bfd *dynobj;
+  struct mips_elf_link_hash_entry *hmips;
+  struct mips_elf_link_hash_table *htab;
+
+  htab = mips_elf_hash_table (info);
+  dynobj = elf_hash_table (info)->dynobj;
+  hmips = (struct mips_elf_link_hash_entry *) h;
+
+  /* VxWorks executables are handled elsewhere; we only need to
+     allocate relocations in shared objects.  */
+  if (htab->is_vxworks && !info->shared)
+    return TRUE;
+
+  /* If this symbol is defined in a dynamic object, or we are creating
+     a shared library, we will need to copy any R_MIPS_32 or
+     R_MIPS_REL32 relocs against it into the output file.  */
+  if (! info->relocatable
+      && hmips->possibly_dynamic_relocs != 0
+      && (h->root.type == bfd_link_hash_defweak
+	  || !h->def_regular
+	  || info->shared))
+    {
+      bfd_boolean do_copy = TRUE;
+
+      if (h->root.type == bfd_link_hash_undefweak)
+	{
+	  /* Do not copy relocations for undefined weak symbols with
+	     non-default visibility.  */
+	  if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+	    do_copy = FALSE;
+
+	  /* Make sure undefined weak symbols are output as a dynamic
+	     symbol in PIEs.  */
+	  else if (h->dynindx == -1 && !h->forced_local)
+	    {
+	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
+		return FALSE;
+	    }
+	}
+
+      if (do_copy)
+	{
+	  mips_elf_allocate_dynamic_relocations
+	    (dynobj, info, hmips->possibly_dynamic_relocs);
+	  if (hmips->readonly_reloc)
+	    /* We tell the dynamic linker that there are relocations
+	       against the text segment.  */
+	    info->flags |= DF_TEXTREL;
+	}
+    }
+
+  return TRUE;
+}
+
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -7315,22 +7387,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (str
 		      && h->ref_regular
 		      && !h->def_regular)));
 
-  /* If this symbol is defined in a dynamic object, we need to copy
-     any R_MIPS_32 or R_MIPS_REL32 relocs against it into the output
-     file.  */
   hmips = (struct mips_elf_link_hash_entry *) h;
-  if (! info->relocatable
-      && hmips->possibly_dynamic_relocs != 0
-      && (h->root.type == bfd_link_hash_defweak
-	  || !h->def_regular))
-    {
-      mips_elf_allocate_dynamic_relocations
-	(dynobj, info, hmips->possibly_dynamic_relocs);
-      if (hmips->readonly_reloc)
-	/* We tell the dynamic linker that there are relocations
-	   against the text segment.  */
-	info->flags |= DF_TEXTREL;
-    }
 
   /* For a function, create a stub, if allowed.  */
   if (! hmips->no_fn_stub
@@ -7724,6 +7781,9 @@ _bfd_mips_elf_size_dynamic_sections (bfd
 	}
     }
 
+  /* Allocate space for global sym dynamic relocs.  */
+  elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info);
+
   /* The check_relocs and adjust_dynamic_symbol entry points have
      determined the sizes of the various dynamic sections.  Allocate
      memory for them.  */


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