* 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> 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 * elflink.h (elf_merge_symbol): New static function, broken out of
elf_link_add_object_symbols. elf_link_add_object_symbols.
(elf_link_add_object_symbols): Call it. (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. */ NULL, so that it is correct for a regular symbol. */
h->verinfo.vertree = NULL; 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 /* Handle the special case of a new common symbol merging with an
@ -1376,26 +1383,70 @@ elf_link_add_object_symbols (abfd, info)
bfd_ind_section_ptr, (bfd_vma) 0, name, false, bfd_ind_section_ptr, (bfd_vma) 0, name, false,
collect, (struct bfd_link_hash_entry **) &hi))) collect, (struct bfd_link_hash_entry **) &hi)))
goto error_return; 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.
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.
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)
{
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;
}
/* Now set HI to H, so that the following code
will set the other fields correctly. */
hi = h;
}
/* If there is a duplicate definition somewhere, /* If there is a duplicate definition somewhere,
then HI may not point to an indirect symbol. then HI may not point to an indirect symbol. We
We will have reported an error to the user in will have reported an error to the user in that
that case. */ case. */
if (hi->root.type == bfd_link_hash_indirect) if (hi->root.type == bfd_link_hash_indirect)
{ {
/* If the symbol became indirect, then we struct elf_link_hash_entry *ht;
assume that we have not seen a definition
before. */ /* If the symbol became indirect, then we assume
that we have not seen a definition before. */
BFD_ASSERT ((hi->elf_link_hash_flags BFD_ASSERT ((hi->elf_link_hash_flags
& (ELF_LINK_HASH_DEF_DYNAMIC & (ELF_LINK_HASH_DEF_DYNAMIC
| ELF_LINK_HASH_DEF_REGULAR)) | ELF_LINK_HASH_DEF_REGULAR))
== 0); == 0);
ht = (struct elf_link_hash_entry *) hi->root.u.i.link;
/* Copy down any references that we may have /* Copy down any references that we may have
already seen to the symbol which just already seen to the symbol which just became
became indirect. */ indirect. */
h->elf_link_hash_flags |= ht->elf_link_hash_flags |=
(hi->elf_link_hash_flags (hi->elf_link_hash_flags
& (ELF_LINK_HASH_REF_DYNAMIC & (ELF_LINK_HASH_REF_DYNAMIC
| ELF_LINK_HASH_REF_REGULAR)); | ELF_LINK_HASH_REF_REGULAR));
@ -1403,27 +1454,27 @@ elf_link_add_object_symbols (abfd, info)
/* Copy over the global table offset entry. /* Copy over the global table offset entry.
This may have been already set up by a This may have been already set up by a
check_relocs routine. */ check_relocs routine. */
if (h->got_offset == (bfd_vma) -1) if (ht->got_offset == (bfd_vma) -1)
{ {
h->got_offset = hi->got_offset; ht->got_offset = hi->got_offset;
hi->got_offset = (bfd_vma) -1; hi->got_offset = (bfd_vma) -1;
} }
BFD_ASSERT (hi->got_offset == (bfd_vma) -1); BFD_ASSERT (hi->got_offset == (bfd_vma) -1);
if (h->dynindx == -1) if (ht->dynindx == -1)
{ {
h->dynindx = hi->dynindx; ht->dynindx = hi->dynindx;
h->dynstr_index = hi->dynstr_index; ht->dynstr_index = hi->dynstr_index;
hi->dynindx = -1; hi->dynindx = -1;
hi->dynstr_index = 0; hi->dynstr_index = 0;
} }
BFD_ASSERT (hi->dynindx == -1); BFD_ASSERT (hi->dynindx == -1);
/* FIXME: There may be other information to /* FIXME: There may be other information to copy
copy over for particular targets. */ over for particular targets. */
/* See if the new flags lead us to realize /* See if the new flags lead us to realize that
that the symbol must be dynamic. */ the symbol must be dynamic. */
if (! dynsym) if (! dynsym)
{ {
if (! dynamic) if (! dynamic)
@ -1442,7 +1493,6 @@ elf_link_add_object_symbols (abfd, info)
} }
} }
} }
}
/* We also need to define an indirection from the /* We also need to define an indirection from the
nondefault version of the symbol. */ nondefault version of the symbol. */
@ -1460,7 +1510,16 @@ elf_link_add_object_symbols (abfd, info)
&type_change_ok, &size_change_ok)) &type_change_ok, &size_change_ok))
goto error_return; 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 if (! (_bfd_generic_link_add_one_symbol
(info, abfd, shortname, BSF_INDIRECT, (info, abfd, shortname, BSF_INDIRECT,