mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-26 19:44:11 +08:00
* 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:
parent
12a7367e81
commit
79349b0926
@ -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
|
||||
|
174
bfd/elflink.c
174
bfd/elflink.c
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user