* elflink.h (elf_merge_symbol): In the case of a new defined

symbol overriding an old defined symbol, return the hash table
	entry which we modify, even if it is the target of an
	indirection.
	(elf_link_add_object_symbols): If the real name of the symbol gets
	overridden, convert the versioned symbol into an indirect symbol
	to the real symbol.
This commit is contained in:
Ian Lance Taylor 1997-06-24 02:28:03 +00:00
parent 044d7d4944
commit 541a4b5425
2 changed files with 124 additions and 57 deletions

View File

@ -1,5 +1,13 @@
Mon Jun 23 18:03:27 1997 Ian Lance Taylor <ian@cygnus.com>
* elflink.h (elf_merge_symbol): In the case of a new defined
symbol overriding an old defined symbol, return the hash table
entry which we modify, even if it is the target of an
indirection.
(elf_link_add_object_symbols): If the real name of the symbol gets
overridden, convert the versioned symbol into an indirect symbol
to the real symbol.
* elflink.h (elf_merge_symbol): New static function, broken out of
elf_link_add_object_symbols.
(elf_link_add_object_symbols): Call it.

View File

@ -568,6 +568,13 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
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. */
*sym_hash = h;
}
/* Handle the special case of a new common symbol merging with an
@ -1376,70 +1383,113 @@ elf_link_add_object_symbols (abfd, info)
bfd_ind_section_ptr, (bfd_vma) 0, name, false,
collect, (struct bfd_link_hash_entry **) &hi)))
goto error_return;
}
else
{
/* In this case the symbol named SHORTNAME is
overriding the indirect symbol we want to
add. We were planning on making SHORTNAME an
indirect symbol referring to NAME. SHORTNAME
is the name without a version. NAME is the
fully versioned name, and it is the default
version.
/* If there is a duplicate definition somewhere,
then HI may not point to an indirect symbol.
We will have reported an error to the user in
that case. */
Overriding means that we already saw a
definition for the symbol SHORTNAME in a
regular object, and it is overriding the
symbol defined in the dynamic object.
if (hi->root.type == bfd_link_hash_indirect)
When this happens, we actually want to change
NAME, the symbol we just added, to refer to
SHORTNAME. This will cause references to
NAME in the shared object to become
references to SHORTNAME in the regular
object. This is what we expect when we
override a function in a shared object: that
the references in the shared object will be
mapped to the definition in the regular
object. */
h->root.type = bfd_link_hash_indirect;
h->root.u.i.link = (struct bfd_link_hash_entry *) hi;
if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)
{
/* If the symbol became indirect, then we
assume that we have not seen a definition
before. */
BFD_ASSERT ((hi->elf_link_hash_flags
& (ELF_LINK_HASH_DEF_DYNAMIC
| ELF_LINK_HASH_DEF_REGULAR))
== 0);
h->elf_link_hash_flags &=~ ELF_LINK_HASH_DEF_DYNAMIC;
hi->elf_link_hash_flags |= ELF_LINK_HASH_REF_DYNAMIC;
if (! _bfd_elf_link_record_dynamic_symbol (info, hi))
goto error_return;
}
/* Copy down any references that we may have
already seen to the symbol which just
became indirect. */
h->elf_link_hash_flags |=
(hi->elf_link_hash_flags
& (ELF_LINK_HASH_REF_DYNAMIC
| ELF_LINK_HASH_REF_REGULAR));
/* Now set HI to H, so that the following code
will set the other fields correctly. */
hi = h;
}
/* Copy over the global table offset entry.
This may have been already set up by a
check_relocs routine. */
if (h->got_offset == (bfd_vma) -1)
/* If there is a duplicate definition somewhere,
then HI may not point to an indirect symbol. We
will have reported an error to the user in that
case. */
if (hi->root.type == bfd_link_hash_indirect)
{
struct elf_link_hash_entry *ht;
/* If the symbol became indirect, then we assume
that we have not seen a definition before. */
BFD_ASSERT ((hi->elf_link_hash_flags
& (ELF_LINK_HASH_DEF_DYNAMIC
| ELF_LINK_HASH_DEF_REGULAR))
== 0);
ht = (struct elf_link_hash_entry *) hi->root.u.i.link;
/* Copy down any references that we may have
already seen to the symbol which just became
indirect. */
ht->elf_link_hash_flags |=
(hi->elf_link_hash_flags
& (ELF_LINK_HASH_REF_DYNAMIC
| ELF_LINK_HASH_REF_REGULAR));
/* Copy over the global table offset entry.
This may have been already set up by a
check_relocs routine. */
if (ht->got_offset == (bfd_vma) -1)
{
ht->got_offset = hi->got_offset;
hi->got_offset = (bfd_vma) -1;
}
BFD_ASSERT (hi->got_offset == (bfd_vma) -1);
if (ht->dynindx == -1)
{
ht->dynindx = hi->dynindx;
ht->dynstr_index = hi->dynstr_index;
hi->dynindx = -1;
hi->dynstr_index = 0;
}
BFD_ASSERT (hi->dynindx == -1);
/* FIXME: There may be other information to copy
over for particular targets. */
/* See if the new flags lead us to realize that
the symbol must be dynamic. */
if (! dynsym)
{
if (! dynamic)
{
h->got_offset = hi->got_offset;
hi->got_offset = (bfd_vma) -1;
if (info->shared
|| ((hi->elf_link_hash_flags
& ELF_LINK_HASH_REF_DYNAMIC)
!= 0))
dynsym = true;
}
BFD_ASSERT (hi->got_offset == (bfd_vma) -1);
if (h->dynindx == -1)
else
{
h->dynindx = hi->dynindx;
h->dynstr_index = hi->dynstr_index;
hi->dynindx = -1;
hi->dynstr_index = 0;
}
BFD_ASSERT (hi->dynindx == -1);
/* FIXME: There may be other information to
copy over for particular targets. */
/* See if the new flags lead us to realize
that the symbol must be dynamic. */
if (! dynsym)
{
if (! dynamic)
{
if (info->shared
|| ((hi->elf_link_hash_flags
& ELF_LINK_HASH_REF_DYNAMIC)
!= 0))
dynsym = true;
}
else
{
if ((hi->elf_link_hash_flags
& ELF_LINK_HASH_REF_REGULAR) != 0)
dynsym = true;
}
if ((hi->elf_link_hash_flags
& ELF_LINK_HASH_REF_REGULAR) != 0)
dynsym = true;
}
}
}
@ -1460,7 +1510,16 @@ elf_link_add_object_symbols (abfd, info)
&type_change_ok, &size_change_ok))
goto error_return;
if (! override)
if (override)
{
/* Here SHORTNAME is a versioned name, so we
don't expect to see the type of override we
do in the case above. */
(*_bfd_error_handler)
("%s: warning: unexpected redefinition of `%s'",
bfd_get_filename (abfd), shortname);
}
else
{
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, shortname, BSF_INDIRECT,