This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: Versioned symbol linking bug
- From: Daniel Jacobowitz <drow at mvista dot com>
- To: binutils at sources dot redhat dot com
- Cc: Alan Modra <amodra at bigpond dot net dot au>
- Date: Thu, 17 Apr 2003 16:27:43 -0400
- Subject: Re: Versioned symbol linking bug
- References: <20030217164809.GA18104@nevyn.them.org> <20030225025812.GD31111@bubble.sa.bigpond.net.au>
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