diff options
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/elflink.c | 174 | ||||
-rw-r--r-- | bfd/elflink.h | 15 |
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, |