* 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>
|
2004-03-17 Nathan Sidwell <nathan@codesourcery.com>
|
||||||
|
|
||||||
* elfxx-mips.c (_bfd_mips_elf_merge_private_bfd_data): Correct
|
* 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
|
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
|
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, 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. */
|
a shared object. */
|
||||||
|
|
||||||
bfd_boolean
|
bfd_boolean
|
||||||
|
@ -676,7 +676,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
||||||
int bind;
|
int bind;
|
||||||
bfd *oldbfd;
|
bfd *oldbfd;
|
||||||
bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
|
bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
|
||||||
bfd_boolean newweakdef, oldweakdef, newweakundef, oldweakundef;
|
bfd_boolean newweak, oldweak;
|
||||||
|
|
||||||
*skip = FALSE;
|
*skip = FALSE;
|
||||||
*override = 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
|
is the first time we see it in a dynamic object, we mark
|
||||||
if it is weak. Otherwise, we clear it. */
|
if it is weak. Otherwise, we clear it. */
|
||||||
if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0)
|
if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0)
|
||||||
{
|
{
|
||||||
if (bind == STB_WEAK)
|
if (bind == STB_WEAK)
|
||||||
h->elf_link_hash_flags |= ELF_LINK_DYNAMIC_WEAK;
|
h->elf_link_hash_flags |= ELF_LINK_DYNAMIC_WEAK;
|
||||||
}
|
}
|
||||||
|
@ -882,48 +882,38 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to treat weak definition right, depending on if there is a
|
/* Differentiate strong and weak symbols. */
|
||||||
definition from a dynamic object. */
|
newweak = bind == STB_WEAK;
|
||||||
if (bind == STB_WEAK)
|
oldweak = (h->root.type == bfd_link_hash_defweak
|
||||||
{
|
|| h->root.type == bfd_link_hash_undefweak);
|
||||||
if (olddef)
|
|
||||||
{
|
|
||||||
newweakdef = TRUE;
|
|
||||||
newweakundef = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newweakdef = FALSE;
|
|
||||||
newweakundef = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
newweakdef = newweakundef = FALSE;
|
|
||||||
|
|
||||||
/* If the new weak definition comes from a relocatable file and the
|
/* It's OK to change the type if either the existing symbol or the
|
||||||
old symbol comes from a dynamic object, we treat the new one as
|
new symbol is weak. A type change is also OK if the old symbol
|
||||||
strong. */
|
is undefined and the new symbol is defined. */
|
||||||
if (newweakdef && !newdyn && olddyn)
|
|
||||||
newweakdef = FALSE;
|
|
||||||
|
|
||||||
if (h->root.type == bfd_link_hash_defweak)
|
if (oldweak
|
||||||
{
|
|| newweak
|
||||||
oldweakdef = TRUE;
|
|| (newdef
|
||||||
oldweakundef = FALSE;
|
&& h->root.type == bfd_link_hash_undefined))
|
||||||
}
|
*type_change_ok = TRUE;
|
||||||
else if (h->root.type == bfd_link_hash_undefweak)
|
|
||||||
{
|
|
||||||
oldweakdef = FALSE;
|
|
||||||
oldweakundef = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
oldweakdef = oldweakundef = FALSE;
|
|
||||||
|
|
||||||
/* If the old weak definition comes from a relocatable file and the
|
/* It's OK to change the size if either the existing symbol or the
|
||||||
new symbol comes from a dynamic object, we treat the old one as
|
new symbol is weak, or if the old symbol is undefined. */
|
||||||
strong. */
|
|
||||||
if (oldweakdef && !olddyn && newdyn)
|
if (*type_change_ok
|
||||||
oldweakdef = FALSE;
|
|| 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
|
/* NEWDYNCOMMON and OLDDYNCOMMON indicate whether the new or old
|
||||||
symbol, respectively, appears to be a common symbol in a dynamic
|
symbol, respectively, appears to be a common symbol in a dynamic
|
||||||
|
@ -950,11 +940,10 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
||||||
|
|
||||||
if (newdyn
|
if (newdyn
|
||||||
&& newdef
|
&& newdef
|
||||||
|
&& !newweak
|
||||||
&& (sec->flags & SEC_ALLOC) != 0
|
&& (sec->flags & SEC_ALLOC) != 0
|
||||||
&& (sec->flags & SEC_LOAD) == 0
|
&& (sec->flags & SEC_LOAD) == 0
|
||||||
&& sym->st_size > 0
|
&& sym->st_size > 0
|
||||||
&& !newweakdef
|
|
||||||
&& !newweakundef
|
|
||||||
&& ELF_ST_TYPE (sym->st_info) != STT_FUNC)
|
&& ELF_ST_TYPE (sym->st_info) != STT_FUNC)
|
||||||
newdyncommon = TRUE;
|
newdyncommon = TRUE;
|
||||||
else
|
else
|
||||||
|
@ -972,28 +961,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
||||||
else
|
else
|
||||||
olddyncommon = FALSE;
|
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
|
/* 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
|
dynamic object, set the size of the symbol to the larger of the
|
||||||
two. */
|
two. */
|
||||||
|
@ -1031,24 +998,15 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
||||||
represent variables; this can cause confusion in principle, but
|
represent variables; this can cause confusion in principle, but
|
||||||
any such confusion would seem to indicate an erroneous program or
|
any such confusion would seem to indicate an erroneous program or
|
||||||
shared library. We also permit a common symbol in a regular
|
shared library. We also permit a common symbol in a regular
|
||||||
object to override a weak symbol in a shared object.
|
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. */
|
|
||||||
|
|
||||||
if (newdyn
|
if (newdyn
|
||||||
&& newdef
|
&& newdef
|
||||||
&& (olddef
|
&& (olddef
|
||||||
|| (h->root.type == bfd_link_hash_common
|
|| (h->root.type == bfd_link_hash_common
|
||||||
&& (newweakdef
|
&& (newweak
|
||||||
|| newweakundef
|
|
||||||
|| ELF_ST_TYPE (sym->st_info) == STT_FUNC)))
|
|| ELF_ST_TYPE (sym->st_info) == STT_FUNC)))
|
||||||
&& (!oldweakdef
|
&& (!oldweak || newweak))
|
||||||
|| dt_needed
|
|
||||||
|| newweakdef
|
|
||||||
|| newweakundef))
|
|
||||||
{
|
{
|
||||||
*override = TRUE;
|
*override = TRUE;
|
||||||
newdef = FALSE;
|
newdef = FALSE;
|
||||||
|
@ -1101,11 +1059,12 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
||||||
if (! newdyn
|
if (! newdyn
|
||||||
&& (newdef
|
&& (newdef
|
||||||
|| (bfd_is_com_section (sec)
|
|| (bfd_is_com_section (sec)
|
||||||
&& (oldweakdef || h->type == STT_FUNC)))
|
&& (oldweak
|
||||||
|
|| h->type == STT_FUNC)))
|
||||||
&& olddyn
|
&& olddyn
|
||||||
&& olddef
|
&& olddef
|
||||||
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
|
&& (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
|
/* Change the hash table entry to undefined, and let
|
||||||
_bfd_generic_link_add_one_symbol do the right thing with the
|
_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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1384,12 +1300,6 @@ _bfd_elf_add_default_symbol (bfd *abfd,
|
||||||
{
|
{
|
||||||
struct elf_link_hash_entry *ht;
|
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;
|
ht = (struct elf_link_hash_entry *) hi->root.u.i.link;
|
||||||
(*bed->elf_backend_copy_indirect_symbol) (bed, ht, hi);
|
(*bed->elf_backend_copy_indirect_symbol) (bed, ht, hi);
|
||||||
|
|
||||||
|
@ -1462,12 +1372,6 @@ nondefault:
|
||||||
|
|
||||||
if (hi->root.type == bfd_link_hash_indirect)
|
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);
|
(*bed->elf_backend_copy_indirect_symbol) (bed, h, hi);
|
||||||
|
|
||||||
/* See if the new flags lead us to realize that the symbol
|
/* See if the new flags lead us to realize that the symbol
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* ELF linker support.
|
/* 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.
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of BFD, the Binary File Descriptor library.
|
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;
|
Elf_Internal_Sym *isymend;
|
||||||
const struct elf_backend_data *bed;
|
const struct elf_backend_data *bed;
|
||||||
bfd_boolean dt_needed;
|
bfd_boolean dt_needed;
|
||||||
|
bfd_boolean add_needed;
|
||||||
struct elf_link_hash_table * hash_table;
|
struct elf_link_hash_table * hash_table;
|
||||||
bfd_size_type amt;
|
bfd_size_type amt;
|
||||||
|
|
||||||
|
@ -201,6 +202,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
dt_needed = FALSE;
|
dt_needed = FALSE;
|
||||||
|
add_needed = FALSE;
|
||||||
if (! dynamic)
|
if (! dynamic)
|
||||||
{
|
{
|
||||||
/* If we are creating a shared library, create all the 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
|
else
|
||||||
{
|
{
|
||||||
asection *s;
|
asection *s;
|
||||||
bfd_boolean add_needed;
|
|
||||||
const char *name;
|
const char *name;
|
||||||
bfd_size_type oldsize;
|
bfd_size_type oldsize;
|
||||||
bfd_size_type strindex;
|
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:
|
case bfd_link_hash_defweak:
|
||||||
old_bfd = h->root.u.def.section->owner;
|
old_bfd = h->root.u.def.section->owner;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case bfd_link_hash_common:
|
case bfd_link_hash_common:
|
||||||
old_bfd = h->root.u.c.p->section->owner;
|
old_bfd = h->root.u.c.p->section->owner;
|
||||||
old_alignment = h->root.u.c.p->alignment_power;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dt_needed && definition
|
if (dt_needed && !add_needed && definition
|
||||||
&& (h->elf_link_hash_flags
|
&& (h->elf_link_hash_flags
|
||||||
& ELF_LINK_HASH_REF_REGULAR) != 0)
|
& 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
|
the regular object to create a dynamic executable. We
|
||||||
have to make sure there is a DT_NEEDED entry for it. */
|
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);
|
oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
|
||||||
strindex = _bfd_elf_strtab_add (hash_table->dynstr,
|
strindex = _bfd_elf_strtab_add (hash_table->dynstr,
|
||||||
elf_dt_soname (abfd), FALSE);
|
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))
|
&& (info->strip != strip_all && info->strip != strip_debugger))
|
||||||
{
|
{
|
||||||
asection *stabstr;
|
asection *stabstr;
|
||||||
|
|
||||||
stabstr = bfd_get_section_by_name (abfd, ".stabstr");
|
stabstr = bfd_get_section_by_name (abfd, ".stabstr");
|
||||||
if (stabstr != NULL)
|
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))
|
&& !bfd_is_abs_section (stab->output_section))
|
||||||
{
|
{
|
||||||
struct bfd_elf_section_data *secdata;
|
struct bfd_elf_section_data *secdata;
|
||||||
|
|
||||||
secdata = elf_section_data (stab);
|
secdata = elf_section_data (stab);
|
||||||
if (! _bfd_link_section_stabs (abfd,
|
if (! _bfd_link_section_stabs (abfd,
|
||||||
& hash_table->stab_info,
|
& hash_table->stab_info,
|
||||||
|
|
Loading…
Reference in New Issue