* elflink.c (_bfd_elf_merge_symbol): Rewrite weak symbol handling.
authorAlan Modra <amodra@gmail.com>
Thu, 18 Mar 2004 04:32:17 +0000 (04:32 +0000)
committerAlan Modra <amodra@gmail.com>
Thu, 18 Mar 2004 04:32:17 +0000 (04:32 +0000)
(_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.

bfd/ChangeLog
bfd/elflink.c
bfd/elflink.h

index fdf1eed210d8e01309e4af32d9f2a3bde6e45b32..2d41bb8051bfa4f8995249710d6dfe5141cb2b9e 100644 (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
index 64cc04d5135d247048cfb5c6e951f248e668e3a9..c9db782dad1f065a03468a05aa1d6838014c08ec 100644 (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
index 05f7c682b2f92c1e5137ba648e4046ad69ec71a9..ec20e75167dad55cc076f6d9e5b39ec0881de289 100644 (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,