aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elflink.c174
-rw-r--r--bfd/elflink.h15
3 files changed, 54 insertions, 142 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index fdf1eed..2d41bb8 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 64cc04d..c9db782 100644
--- a/bfd/elflink.c
+++ b/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
diff --git a/bfd/elflink.h b/bfd/elflink.h
index 05f7c68..ec20e75 100644
--- a/bfd/elflink.h
+++ b/bfd/elflink.h
@@ -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,