PATCH: A symbol visibility problem

H. J. Lu hjl@lucon.org
Wed Jan 28 20:30:00 GMT 2004


On Wed, Jan 28, 2004 at 11:46:36AM -0800, H. J. Lu wrote:
> On Wed, Jan 28, 2004 at 11:32:42AM +0000, Nick Clifton wrote:
> > Hi H. J. Lu" <hjl@lucon.org> writes:
> > 
> > > The problem is
> > >
> > >       /* If the new symbol with non-default visibility comes from a
> > >          relocatable file and the old definition comes from a dynamic
> > >          object, we remove the old definition.  */
> > >       if ((*sym_hash)->root.type == bfd_link_hash_indirect)
> > >         h = *sym_hash;
> > >       h->root.type = bfd_link_hash_new;
> > >       h->root.u.undef.abfd = NULL;
> > >  
> > > If the new entry with non-default visibility is undefined, then
> > > setting the type to bfd_link_hash_new will lead to the
> > > assertion. Should we use
> > >
> > > 	h->root.type = bfd_link_hash_undefined;
> > >
> > > instead and let _bfd_generic_link_add_one_symbol take care of it?
> > 
> > That seems sensible, but I think only if the new symbol is undefined.
> > 
> > Do you have a patch to propose for this ?
> > 
> 
> It is more complex than I thought. When we remove the old definition
> coming from a DSO, we need to restore the previous state if the new
> symbol is undefined. Set it to bfd_link_hash_undefined is wrong if
> it was referenced before because the new symbol can be weak undefined,
> which may lead to undefined symbol error. We can tell if it has been
> referenced by checking h->root.und_next. The main problem is how to
> maintain the linker hash table undefs list. If h->root.und_next is
> not NULL, h may or may not be on the linker hash table undefs list.
> We need to make sure it is on the linker hash table undefs list and
> the undefs list won't be corrupted by it.
> 
> 

This patch tries to do it right.


H.J.
-------------- next part --------------
2004-01-28  H.J. Lu  <hongjiu.lu@intel.com>

	* elflink.c (_bfd_elf_merge_symbol): Properly handle undefined
	symbols with non-default visibility.

--- bfd/elflink.c.vsb	2003-12-04 10:43:10.000000000 -0800
+++ bfd/elflink.c	2004-01-28 12:24:26.000000000 -0800
@@ -843,8 +843,43 @@ _bfd_elf_merge_symbol (bfd *abfd,
 	 object, we remove the old definition.  */
       if ((*sym_hash)->root.type == bfd_link_hash_indirect)
 	h = *sym_hash;
-      h->root.type = bfd_link_hash_new;
-      h->root.u.undef.abfd = NULL;
+
+      if ((h->root.und_next || info->hash->undefs_tail == &h->root)
+	  && bfd_is_und_section (sec))
+	{
+	  /* If the new symbol is undefined and the old symbol was
+	     also undefined before, we need to handle it ourselves and
+	     make sure _bfd_generic_link_add_one_symbol doesn't mess
+	     up the linker hash table undefs list.  */
+
+	  if (h->root.und_next)
+	    {
+	      /* First make sure it is on the linker hash table undefs
+		 list.  */
+	      struct bfd_link_hash_entry *undef;
+	      
+	      for (undef = info->hash->undefs;
+		   undef != NULL && undef != &h->root;
+		   undef = undef->und_next);
+	      
+	      if (undef != NULL)
+		{
+		  /* Add it to the undefs list if needed.  */
+		  h->root.und_next = NULL;
+		  bfd_link_add_undef (info->hash, &h->root);
+		}
+	    }
+
+	  h->root.type = bfd_link_hash_undefined;
+	  /* FIXME: What if the new symbol is weak undefined?  */
+	  h->root.u.undef.abfd = abfd;
+	}
+      else
+	{
+	  h->root.type = bfd_link_hash_new;
+	  h->root.u.undef.abfd = NULL;
+	}
+
       if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)
 	{
 	  h->elf_link_hash_flags &= ~ELF_LINK_HASH_DEF_DYNAMIC;


More information about the Binutils mailing list