This is the mail archive of the binutils@sources.redhat.com 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: Versioned symbol linking bug


On Tue, Feb 25, 2003 at 01:28:12PM +1030, Alan Modra wrote:
> Hi Daniel,
>   This patch cures your testcase, but I'm not game to install it
> without a whole lot of testing, which I don't have time to do at
> the moment.

The logic seems right to me; what kind of testing can I do to increase
your confidence?  I'd like to pick this fix up for the next release.

> 
> 	* elflink.h (elf_merge_symbol): When we find a regular definition
> 	for an indirect symbol, flip the indirection so that the old
> 	direct symbol now points to the new definition.
> 
> Index: bfd/elflink.h
> ===================================================================
> RCS file: /cvs/src/src/bfd/elflink.h,v
> retrieving revision 1.206
> diff -u -p -r1.206 elflink.h
> --- bfd/elflink.h	17 Feb 2003 18:24:40 -0000	1.206
> +++ bfd/elflink.h	25 Feb 2003 02:41:23 -0000
> @@ -479,6 +479,7 @@ elf_merge_symbol (abfd, info, name, sym,
>  {
>    asection *sec;
>    struct elf_link_hash_entry *h;
> +  struct elf_link_hash_entry *flip;
>    int bind;
>    bfd *oldbfd;
>    bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
> @@ -769,6 +770,7 @@ elf_merge_symbol (abfd, info, name, sym,
>       As above, we permit a non-weak definition in a shared object to
>       override a weak definition in a regular object.  */
>  
> +  flip = NULL;
>    if (! newdyn
>        && (newdef
>  	  || (bfd_is_com_section (sec)
> @@ -797,19 +799,13 @@ elf_merge_symbol (abfd, info, name, sym,
>        if (bfd_is_com_section (sec))
>  	*type_change_ok = TRUE;
>  
> -      /* This union may have been set to be non-NULL when this symbol
> -	 was seen in a dynamic object.  We must force the union to be
> -	 NULL, so that it is correct for a regular symbol.  */
> -
> -      h->verinfo.vertree = NULL;
> -
> -      /* In this special case, if H is the target of an indirection,
> -	 we want the caller to frob with H rather than with the
> -	 indirect symbol.  That will permit the caller to redefine the
> -	 target of the indirection, rather than the indirect symbol
> -	 itself.  FIXME: This will break the -y option if we store a
> -	 symbol with a different name.  */
> -      *sym_hash = h;
> +      if ((*sym_hash)->root.type == bfd_link_hash_indirect)
> +	flip = *sym_hash;
> +      else
> +	/* This union may have been set to be non-NULL when this symbol
> +	   was seen in a dynamic object.  We must force the union to be
> +	   NULL, so that it is correct for a regular symbol.  */
> +	h->verinfo.vertree = NULL;
>      }
>  
>    /* Handle the special case of a new common symbol merging with an
> @@ -849,7 +845,26 @@ elf_merge_symbol (abfd, info, name, sym,
>        *size_change_ok = TRUE;
>        *type_change_ok = TRUE;
>  
> -      h->verinfo.vertree = NULL;
> +      if ((*sym_hash)->root.type == bfd_link_hash_indirect)
> +	flip = *sym_hash;
> +      else
> +	h->verinfo.vertree = NULL;
> +    }
> +
> +  if (flip != NULL)
> +    {
> +      /* Handle the case where we had a versioned symbol in a dynamic
> +	 library and now find a definition in a normal object.  In this
> +	 case, we make the versioned symbol point to the normal one.  */
> +      flip->root.type = h->root.type;
> +      flip->root.u.undef.abfd = h->root.u.undef.abfd;
> +      h->root.type = bfd_link_hash_indirect;
> +      h->root.u.i.link = (struct bfd_link_hash_entry *) flip;
> +      if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)
> +	{
> +	  h->elf_link_hash_flags &= ~ELF_LINK_HASH_DEF_DYNAMIC;
> +	  flip->elf_link_hash_flags |= ELF_LINK_HASH_REF_DYNAMIC;
> +	}
>      }
>  
>    /* Handle the special case of a weak definition in a regular object
> @@ -883,7 +898,7 @@ elf_merge_symbol (abfd, info, name, sym,
>  
>    /* Handle the special case of a non-weak definition in a shared
>       object followed by a weak definition in a regular object.  In
> -     this case we prefer to definition in the shared object.  To make
> +     this case we prefer the definition in the shared object.  To make
>       this work we have to tell the caller to not treat the new symbol
>       as a definition.  */
>    if (olddef
> 
> -- 
> Alan Modra
> IBM OzLabs - Linux Technology Centre
> 

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


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