* elflink.c (_bfd_elf_merge_symbol): Rewrite weak symbol handling.

(_bfd_elf_add_default_symbol): Remove indirect BFD_ASSERTs.
	* elflink.h (elf_link_add_object_symbols): Don't clear dt_needed in
	symbol loop.  Instead use add_needed to flag tag as written.
This commit is contained in:
Alan Modra 2004-03-18 04:32:17 +00:00
parent 12a7367e81
commit 79349b0926
3 changed files with 54 additions and 142 deletions

View File

@ -1,3 +1,10 @@
2004-03-18 Alan Modra <amodra@bigpond.net.au>
* elflink.c (_bfd_elf_merge_symbol): Rewrite weak symbol handling.
(_bfd_elf_add_default_symbol): Remove indirect BFD_ASSERTs.
* elflink.h (elf_link_add_object_symbols): Don't clear dt_needed in
symbol loop. Instead use add_needed to flag tag as written.
2004-03-17 Nathan Sidwell <nathan@codesourcery.com>
* elfxx-mips.c (_bfd_mips_elf_merge_private_bfd_data): Correct

View File

@ -653,7 +653,7 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd, struct bfd_link_info *info)
TYPE_CHANGE_OK if it is OK for the type to change. We set
SIZE_CHANGE_OK if it is OK for the size to change. By OK to
change, we mean that we shouldn't warn if the type or size does
change. DT_NEEDED indicates if it comes from a DT_NEEDED entry of
change. DT_NEEDED indicates if it comes from a DT_NEEDED entry of
a shared object. */
bfd_boolean
@ -676,7 +676,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
int bind;
bfd *oldbfd;
bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
bfd_boolean newweakdef, oldweakdef, newweakundef, oldweakundef;
bfd_boolean newweak, oldweak;
*skip = FALSE;
*override = FALSE;
@ -814,7 +814,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
is the first time we see it in a dynamic object, we mark
if it is weak. Otherwise, we clear it. */
if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0)
{
{
if (bind == STB_WEAK)
h->elf_link_hash_flags |= ELF_LINK_DYNAMIC_WEAK;
}
@ -882,48 +882,38 @@ _bfd_elf_merge_symbol (bfd *abfd,
return TRUE;
}
/* We need to treat weak definition right, depending on if there is a
definition from a dynamic object. */
if (bind == STB_WEAK)
{
if (olddef)
{
newweakdef = TRUE;
newweakundef = FALSE;
}
else
{
newweakdef = FALSE;
newweakundef = TRUE;
}
}
else
newweakdef = newweakundef = FALSE;
/* Differentiate strong and weak symbols. */
newweak = bind == STB_WEAK;
oldweak = (h->root.type == bfd_link_hash_defweak
|| h->root.type == bfd_link_hash_undefweak);
/* If the new weak definition comes from a relocatable file and the
old symbol comes from a dynamic object, we treat the new one as
strong. */
if (newweakdef && !newdyn && olddyn)
newweakdef = FALSE;
/* It's OK to change the type if either the existing symbol or the
new symbol is weak. A type change is also OK if the old symbol
is undefined and the new symbol is defined. */
if (h->root.type == bfd_link_hash_defweak)
{
oldweakdef = TRUE;
oldweakundef = FALSE;
}
else if (h->root.type == bfd_link_hash_undefweak)
{
oldweakdef = FALSE;
oldweakundef = TRUE;
}
else
oldweakdef = oldweakundef = FALSE;
if (oldweak
|| newweak
|| (newdef
&& h->root.type == bfd_link_hash_undefined))
*type_change_ok = TRUE;
/* If the old weak definition comes from a relocatable file and the
new symbol comes from a dynamic object, we treat the old one as
strong. */
if (oldweakdef && !olddyn && newdyn)
oldweakdef = FALSE;
/* It's OK to change the size if either the existing symbol or the
new symbol is weak, or if the old symbol is undefined. */
if (*type_change_ok
|| h->root.type == bfd_link_hash_undefined)
*size_change_ok = TRUE;
/* If a new weak symbol comes from a regular file and the old symbol
comes from a dynamic library, we treat the new one as strong.
Similarly, an old weak symbol from a regular file is treated as
strong when the new symbol comes from a dynamic library. Further,
an old weak symbol from a dynamic library is treated as strong if
the new symbol is from a DT_NEEDED dynamic library. */
if (!newdyn && olddyn)
newweak = FALSE;
if ((!olddyn || dt_needed) && newdyn)
oldweak = FALSE;
/* NEWDYNCOMMON and OLDDYNCOMMON indicate whether the new or old
symbol, respectively, appears to be a common symbol in a dynamic
@ -950,11 +940,10 @@ _bfd_elf_merge_symbol (bfd *abfd,
if (newdyn
&& newdef
&& !newweak
&& (sec->flags & SEC_ALLOC) != 0
&& (sec->flags & SEC_LOAD) == 0
&& sym->st_size > 0
&& !newweakdef
&& !newweakundef
&& ELF_ST_TYPE (sym->st_info) != STT_FUNC)
newdyncommon = TRUE;
else
@ -972,28 +961,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
else
olddyncommon = FALSE;
/* It's OK to change the type if either the existing symbol or the
new symbol is weak unless it comes from a DT_NEEDED entry of
a shared object, in which case, the DT_NEEDED entry may not be
required at the run time. The type change is also OK if the
old symbol is undefined and the new symbol is defined. */
if ((! dt_needed && oldweakdef)
|| oldweakundef
|| newweakdef
|| newweakundef
|| (newdef
&& (h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_undefweak)))
*type_change_ok = TRUE;
/* It's OK to change the size if either the existing symbol or the
new symbol is weak, or if the old symbol is undefined. */
if (*type_change_ok
|| h->root.type == bfd_link_hash_undefined)
*size_change_ok = TRUE;
/* If both the old and the new symbols look like common symbols in a
dynamic object, set the size of the symbol to the larger of the
two. */
@ -1031,24 +998,15 @@ _bfd_elf_merge_symbol (bfd *abfd,
represent variables; this can cause confusion in principle, but
any such confusion would seem to indicate an erroneous program or
shared library. We also permit a common symbol in a regular
object to override a weak symbol in a shared object.
We prefer a non-weak definition in a shared library to a weak
definition in the executable unless it comes from a DT_NEEDED
entry of a shared object, in which case, the DT_NEEDED entry
may not be required at the run time. */
object to override a weak symbol in a shared object. */
if (newdyn
&& newdef
&& (olddef
|| (h->root.type == bfd_link_hash_common
&& (newweakdef
|| newweakundef
&& (newweak
|| ELF_ST_TYPE (sym->st_info) == STT_FUNC)))
&& (!oldweakdef
|| dt_needed
|| newweakdef
|| newweakundef))
&& (!oldweak || newweak))
{
*override = TRUE;
newdef = FALSE;
@ -1101,11 +1059,12 @@ _bfd_elf_merge_symbol (bfd *abfd,
if (! newdyn
&& (newdef
|| (bfd_is_com_section (sec)
&& (oldweakdef || h->type == STT_FUNC)))
&& (oldweak
|| h->type == STT_FUNC)))
&& olddyn
&& olddef
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
&& ((!newweakdef && !newweakundef) || oldweakdef))
&& (!newweak || oldweak))
{
/* Change the hash table entry to undefined, and let
_bfd_generic_link_add_one_symbol do the right thing with the
@ -1194,49 +1153,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
}
}
/* Handle the special case of a weak definition in a regular object
followed by a non-weak definition in a shared object. In this
case, we prefer the definition in the shared object unless it
comes from a DT_NEEDED entry of a shared object, in which case,
the DT_NEEDED entry may not be required at the run time. */
if (olddef
&& ! dt_needed
&& oldweakdef
&& newdef
&& newdyn
&& !newweakdef
&& !newweakundef)
{
/* To make this work we have to frob the flags so that the rest
of the code does not think we are using the regular
definition. */
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
else if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
h->elf_link_hash_flags |= ELF_LINK_HASH_REF_DYNAMIC;
h->elf_link_hash_flags &= ~ (ELF_LINK_HASH_DEF_REGULAR
| ELF_LINK_HASH_DEF_DYNAMIC);
/* If H is the target of an indirection, we want the caller to
use H rather than the indirect symbol. Otherwise if we are
defining a new indirect symbol we will wind up attaching it
to the entry we are overriding. */
*sym_hash = h;
}
/* 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 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
&& olddyn
&& !oldweakdef
&& newdef
&& ! newdyn
&& (newweakdef || newweakundef))
*override = TRUE;
return TRUE;
}
@ -1384,12 +1300,6 @@ _bfd_elf_add_default_symbol (bfd *abfd,
{
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;
(*bed->elf_backend_copy_indirect_symbol) (bed, ht, hi);
@ -1462,12 +1372,6 @@ nondefault:
if (hi->root.type == bfd_link_hash_indirect)
{
/* 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);
(*bed->elf_backend_copy_indirect_symbol) (bed, h, hi);
/* See if the new flags lead us to realize that the symbol

View File

@ -1,5 +1,5 @@
/* ELF linker support.
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@ -95,6 +95,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
Elf_Internal_Sym *isymend;
const struct elf_backend_data *bed;
bfd_boolean dt_needed;
bfd_boolean add_needed;
struct elf_link_hash_table * hash_table;
bfd_size_type amt;
@ -201,6 +202,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
}
dt_needed = FALSE;
add_needed = FALSE;
if (! dynamic)
{
/* If we are creating a shared library, create all the dynamic
@ -222,7 +224,6 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
else
{
asection *s;
bfd_boolean add_needed;
const char *name;
bfd_size_type oldsize;
bfd_size_type strindex;
@ -778,7 +779,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
case bfd_link_hash_defweak:
old_bfd = h->root.u.def.section->owner;
break;
case bfd_link_hash_common:
old_bfd = h->root.u.c.p->section->owner;
old_alignment = h->root.u.c.p->alignment_power;
@ -1050,7 +1051,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
break;
}
if (dt_needed && definition
if (dt_needed && !add_needed && definition
&& (h->elf_link_hash_flags
& ELF_LINK_HASH_REF_REGULAR) != 0)
{
@ -1061,7 +1062,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
the regular object to create a dynamic executable. We
have to make sure there is a DT_NEEDED entry for it. */
dt_needed = FALSE;
add_needed = TRUE;
oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
strindex = _bfd_elf_strtab_add (hash_table->dynstr,
elf_dt_soname (abfd), FALSE);
@ -1357,7 +1358,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
&& (info->strip != strip_all && info->strip != strip_debugger))
{
asection *stabstr;
stabstr = bfd_get_section_by_name (abfd, ".stabstr");
if (stabstr != NULL)
{
@ -1372,7 +1373,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
&& !bfd_is_abs_section (stab->output_section))
{
struct bfd_elf_section_data *secdata;
secdata = elf_section_data (stab);
if (! _bfd_link_section_stabs (abfd,
& hash_table->stab_info,