* elf32-mips.c (mips_elf_object_p): Unconditionally set
[deliverable/binutils-gdb.git] / bfd / linker.c
index 37ab1c8e2706337e7b4d7074a63ea270515a6c5e..4ce41e97999c33f219e5b77be7b8b21a36b23e52 100644 (file)
@@ -1,5 +1,5 @@
 /* linker.c -- BFD linker routines
-   Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+   Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
    Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -380,10 +380,7 @@ SUBSUBSECTION
        written out when considering the symbols of each input file,
        but it is still necessary to traverse the hash table since the
        linker script may have defined some symbols that are not in
-       any of the input files.  The <<written>> field in the
-       <<bfd_link_hash_entry>> structure may be used to determine
-       which entries in the hash table have not already been written
-       out.
+       any of the input files.
 
        The <<strip>> field of the <<bfd_link_info>> structure
        controls which symbols are written out.  The possible values
@@ -870,7 +867,7 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
       /* An empty archive is a special case.  */
       if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL)
        return true;
-      bfd_set_error (bfd_error_no_symbols);
+      bfd_set_error (bfd_error_no_armap);
       return false;
     }
 
@@ -1065,9 +1062,9 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
 
       /* We are only interested if we know something about this
         symbol, and it is undefined or common.  An undefined weak
-        symbol (type bfd_link_hash_weak) is not considered to be a
-        reference when pulling files out of an archive.  See the SVR4
-        ABI, p. 4-27.  */
+        symbol (type bfd_link_hash_undefweak) is not considered to be
+        a reference when pulling files out of an archive.  See the
+        SVR4 ABI, p. 4-27.  */
       h = bfd_link_hash_lookup (info->hash, bfd_asymbol_name (p), false,
                                false, true);
       if (h == (struct bfd_link_hash_entry *) NULL
@@ -1124,27 +1121,27 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
             attached to symbfd to ensure that it is in a BFD which
             will be linked in.  */
          h->type = bfd_link_hash_common;
+         h->u.c.p =
+           ((struct bfd_link_hash_common_entry *)
+            bfd_hash_allocate (&info->hash->table,
+                               sizeof (struct bfd_link_hash_common_entry)));
+         if (h->u.c.p == NULL)
+           return false;
 
          size = bfd_asymbol_value (p);
          h->u.c.size = size;
-         if (h->u.c.size != size)
-           {
-             /* The size did not fit in the bitfield.  */
-             bfd_set_error (bfd_error_bad_value);
-             return false;
-           }
 
          power = bfd_log2 (size);
          if (power > 4)
            power = 4;
-         h->u.c.alignment_power = power;
+         h->u.c.p->alignment_power = power;
 
          if (p->section == bfd_com_section_ptr)
-           h->u.c.section = bfd_make_section_old_way (symbfd, "COMMON");
+           h->u.c.p->section = bfd_make_section_old_way (symbfd, "COMMON");
          else
-           h->u.c.section = bfd_make_section_old_way (symbfd,
-                                                      p->section->name);
-         h->u.c.section->flags = SEC_ALLOC;
+           h->u.c.p->section = bfd_make_section_old_way (symbfd,
+                                                         p->section->name);
+         h->u.c.p->section->flags = SEC_ALLOC;
        }
       else
        {
@@ -1220,6 +1217,17 @@ generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect)
                  (struct bfd_link_hash_entry **) &h)))
            return false;
 
+         /* If this is a constructor symbol, and the linker didn't do
+             anything with it, then we want to just pass the symbol
+             through to the output file.  This will happen when
+             linking with -r.  */
+         if ((p->flags & BSF_CONSTRUCTOR) != 0
+             && (h == NULL || h->root.type == bfd_link_hash_new))
+           {
+             p->udata.p = NULL;
+             continue;
+           }
+
          /* Save the BFD symbol so that we don't lose any backend
             specific information that may be attached to it.  We only
             want this one if it gives more information than the
@@ -1287,6 +1295,7 @@ enum link_action
   UND,         /* Mark symbol undefined.  */
   WEAK,                /* Mark symbol weak undefined.  */
   DEF,         /* Mark symbol defined.  */
+  DEFW,                /* Mark symbol weak defined.  */
   COM,         /* Mark symbol common.  */
   REF,         /* Mark defined symbol referenced.  */
   CREF,                /* Possibly warn about common reference to defined symbol.  */
@@ -1309,17 +1318,17 @@ enum link_action
 /* The state table itself.  The first index is a link_row and the
    second index is a bfd_link_hash_type.  */
 
-static const enum link_action link_action[8][7] =
+static const enum link_action link_action[8][8] =
 {
-  /* current\prev    new    undef  weak   def    com    indr   warn  */
-  /* UNDEF_ROW         */  {UND,   NOACT, NOACT, REF,   NOACT, REFC,  WARNC },
-  /* UNDEFW_ROW        */  {WEAK,  WEAK,  NOACT, REF,   NOACT, REFC,  WARNC },
-  /* DEF_ROW   */  {DEF,   DEF,   DEF,   MDEF,  CDEF,  MDEF,  CYCLE },
-  /* DEFW_ROW  */  {DEF,   DEF,   DEF,   NOACT, NOACT, NOACT, CYCLE },
-  /* COMMON_ROW        */  {COM,   COM,   COM,   CREF,  BIG,   CREF,  WARNC },
-  /* INDR_ROW  */  {IND,   IND,   IND,   MDEF,  CIND,  MIND,  CYCLE },
-  /* WARN_ROW   */  {MWARN, WARN,  WARN,  CWARN, WARN,  CWARN, CYCLE },
-  /* SET_ROW   */  {SET,   SET,   SET,   SET,   SET,   CYCLE, CYCLE }
+  /* current\prev    new    undef  undefw def    defw   com    indr   warn  */
+  /* UNDEF_ROW         */  {UND,   NOACT, NOACT, REF,   REF,   NOACT, REFC,  WARNC },
+  /* UNDEFW_ROW        */  {WEAK,  NOACT, NOACT, REF,   REF,   NOACT, REFC,  WARNC },
+  /* DEF_ROW   */  {DEF,   DEF,   DEF,   MDEF,  DEF,   CDEF,  MDEF,  CYCLE },
+  /* DEFW_ROW  */  {DEFW,  DEFW,  DEFW,  NOACT, NOACT, NOACT, NOACT, CYCLE },
+  /* COMMON_ROW        */  {COM,   COM,   COM,   CREF,  CREF,  BIG,   CREF,  WARNC },
+  /* INDR_ROW  */  {IND,   IND,   IND,   MDEF,  IND,   CIND,  MIND,  CYCLE },
+  /* WARN_ROW   */  {MWARN, WARN,  WARN,  CWARN, CWARN, WARN,  CWARN, CYCLE },
+  /* SET_ROW   */  {SET,   SET,   SET,   SET,   SET,   SET,   CYCLE, CYCLE }
 };
 
 /* Most of the entries in the LINK_ACTION table are straightforward,
@@ -1453,7 +1462,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
 
        case WEAK:
          /* Make a new weak undefined symbol.  */
-         h->type = bfd_link_hash_weak;
+         h->type = bfd_link_hash_undefweak;
          h->u.undef.abfd = abfd;
          break;
 
@@ -1463,55 +1472,74 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
          BFD_ASSERT (h->type == bfd_link_hash_common);
          if (! ((*info->callbacks->multiple_common)
                 (info, name,
-                 h->u.c.section->owner, bfd_link_hash_common, h->u.c.size,
+                 h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
                  abfd, bfd_link_hash_defined, (bfd_vma) 0)))
            return false;
          /* Fall through.  */
        case DEF:
-         /* Define a symbol.  */
-         h->type = bfd_link_hash_defined;
-         h->u.def.section = section;
-         h->u.def.value = value;
-
-         /* If we have been asked to, we act like collect2 and
-            identify all functions that might be global constructors
-            and destructors and pass them up in a callback.  We only
-            do this for certain object file types, since many object
-            file types can handle this automatically.  */
-         if (collect && name[0] == '_')
-           {
-             const char *s;
+       case DEFW:
+         {
+           enum bfd_link_order_type oldtype;
 
-             /* A constructor or destructor name starts like this:
-                  _+GLOBAL_[_.$][ID][_.$]
-                where the first [_.$] and the second are the same
-                character (we accept any character there, in case a
-                new object file format comes along with even worse
-                naming restrictions).  */
+           /* Define a symbol.  */
+           oldtype = h->type;
+           if (action == DEFW)
+             h->type = bfd_link_hash_defweak;
+           else
+             h->type = bfd_link_hash_defined;
+           h->u.def.section = section;
+           h->u.def.value = value;
+
+           /* If we have been asked to, we act like collect2 and
+              identify all functions that might be global
+              constructors and destructors and pass them up in a
+              callback.  We only do this for certain object file
+              types, since many object file types can handle this
+              automatically.  */
+           if (collect && name[0] == '_')
+             {
+               const char *s;
+
+               /* A constructor or destructor name starts like this:
+                  _+GLOBAL_[_.$][ID][_.$] where the first [_.$] and
+                  the second are the same character (we accept any
+                  character there, in case a new object file format
+                  comes along with even worse naming restrictions).  */
 
 #define CONS_PREFIX "GLOBAL_"
 #define CONS_PREFIX_LEN (sizeof CONS_PREFIX - 1)
 
-             s = name + 1;
-             while (*s == '_')
-               ++s;
-             if (s[0] == 'G'
-                 && strncmp (s, CONS_PREFIX, CONS_PREFIX_LEN - 1) == 0)
-               {
-                 char c;
-
-                 c = s[CONS_PREFIX_LEN + 1];
-                 if ((c == 'I' || c == 'D')
-                     && s[CONS_PREFIX_LEN] == s[CONS_PREFIX_LEN + 2])
-                   {
-                     if (! ((*info->callbacks->constructor)
-                            (info,
-                             c == 'I' ? true : false,
-                             name, abfd, section, value)))
-                       return false;
-                   }
-               }
-           }
+               s = name + 1;
+               while (*s == '_')
+                 ++s;
+               if (s[0] == 'G'
+                   && strncmp (s, CONS_PREFIX, CONS_PREFIX_LEN - 1) == 0)
+                 {
+                   char c;
+
+                   c = s[CONS_PREFIX_LEN + 1];
+                   if ((c == 'I' || c == 'D')
+                       && s[CONS_PREFIX_LEN] == s[CONS_PREFIX_LEN + 2])
+                     {
+                       /* If this is a definition of a symbol which
+                           was previously weakly defined, we are in
+                           trouble.  We have already added a
+                           constructor entry for the weak defined
+                           symbol, and now we are trying to add one
+                           for the new symbol.  Fortunately, this case
+                           should never arise in practice.  */
+                       if (oldtype == bfd_link_hash_defweak)
+                         abort ();
+
+                       if (! ((*info->callbacks->constructor)
+                              (info,
+                               c == 'I' ? true : false,
+                               name, abfd, section, value)))
+                         return false;
+                     }
+                 }
+             }
+         }
 
          break;
 
@@ -1520,13 +1548,14 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
          if (h->type == bfd_link_hash_new)
            bfd_link_add_undef (info->hash, h);
          h->type = bfd_link_hash_common;
+         h->u.c.p =
+           ((struct bfd_link_hash_common_entry *)
+            bfd_hash_allocate (&info->hash->table,
+                               sizeof (struct bfd_link_hash_common_entry)));
+         if (h->u.c.p == NULL)
+           return false;
+
          h->u.c.size = value;
-         if (h->u.c.size != value)
-           {
-             /* The size did not fit in the bitfield.  */
-             bfd_set_error (bfd_error_bad_value);
-             return false;
-           }
 
          /* Select a default alignment based on the size.  This may
              be overridden by the caller.  */
@@ -1536,7 +1565,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
            power = bfd_log2 (value);
            if (power > 4)
              power = 4;
-           h->u.c.alignment_power = power;
+           h->u.c.p->alignment_power = power;
          }
 
          /* The section of a common symbol is only used if the common
@@ -1551,16 +1580,17 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
              handling.  */
          if (section == bfd_com_section_ptr)
            {
-             h->u.c.section = bfd_make_section_old_way (abfd, "COMMON");
-             h->u.c.section->flags = SEC_ALLOC;
+             h->u.c.p->section = bfd_make_section_old_way (abfd, "COMMON");
+             h->u.c.p->section->flags = SEC_ALLOC;
            }
          else if (section->owner != abfd)
            {
-             h->u.c.section = bfd_make_section_old_way (abfd, section->name);
-             h->u.c.section->flags = SEC_ALLOC;
+             h->u.c.p->section = bfd_make_section_old_way (abfd,
+                                                           section->name);
+             h->u.c.p->section->flags = SEC_ALLOC;
            }
          else
-           h->u.c.section = section;
+           h->u.c.p->section = section;
          break;
 
        case REF:
@@ -1576,7 +1606,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
          BFD_ASSERT (h->type == bfd_link_hash_common);
          if (! ((*info->callbacks->multiple_common)
                 (info, name,
-                 h->u.c.section->owner, bfd_link_hash_common, h->u.c.size,
+                 h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
                  abfd, bfd_link_hash_common, value)))
            return false;
          if (value > h->u.c.size)
@@ -1590,7 +1620,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
              power = bfd_log2 (value);
              if (power > 4)
                power = 4;
-             h->u.c.alignment_power = power;
+             h->u.c.p->alignment_power = power;
            }
          break;
 
@@ -1602,7 +1632,8 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
               was already defined.  FIXME: It would nice if we could
               report the BFD which defined an indirect symbol, but we
               don't have anywhere to store the information.  */
-           if (h->type == bfd_link_hash_defined)
+           if (h->type == bfd_link_hash_defined
+               || h->type == bfd_link_hash_defweak)
              obfd = h->u.def.section->owner;
            else
              obfd = NULL;
@@ -1631,10 +1662,6 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
                msec = h->u.def.section;
                mval = h->u.def.value;
                break;
-             case bfd_link_hash_common:
-               msec = bfd_com_section_ptr;
-               mval = h->u.c.size;
-               break;
              case bfd_link_hash_indirect:
                msec = bfd_ind_section_ptr;
                mval = 0;
@@ -1663,7 +1690,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
          BFD_ASSERT (h->type == bfd_link_hash_common);
          if (! ((*info->callbacks->multiple_common)
                 (info, name,
-                 h->u.c.section->owner, bfd_link_hash_common, h->u.c.size,
+                 h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
                  abfd, bfd_link_hash_indirect, (bfd_vma) 0)))
            return false;
          /* Fall through.  */
@@ -1738,10 +1765,10 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
 
        case CWARN:
          /* Warn if this symbol has been referenced already,
-            otherwise either add a warning or cycle.  A symbol has
-            been referenced if the next field is not NULL, or it is
-            the tail of the undefined symbol list.  The REF case
-            above helps to ensure this.  */
+            otherwise add a warning.  A symbol has been referenced if
+            the next field is not NULL, or it is the tail of the
+            undefined symbol list.  The REF case above helps to
+            ensure this.  */
          if (h->next != NULL || info->hash->undefs_tail == h)
            {
              if (! (*info->callbacks->warning) (info, string))
@@ -2015,9 +2042,25 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
          || bfd_is_com_section (bfd_get_section (sym))
          || bfd_is_ind_section (bfd_get_section (sym)))
        {
-         h = _bfd_generic_link_hash_lookup (_bfd_generic_hash_table (info),
-                                            bfd_asymbol_name (sym),
-                                            false, false, true);
+         if (sym->udata.p != NULL)
+           h = (struct generic_link_hash_entry *) sym->udata.p;
+         else if ((sym->flags & BSF_CONSTRUCTOR) != 0)
+           {
+             /* This case normally means that the main linker code
+                 deliberately ignored this constructor symbol.  We
+                 should just pass it through.  This will screw up if
+                 the constructor symbol is from a different,
+                 non-generic, object file format, but the case will
+                 only arise when linking with -r, which will probably
+                 fail anyhow, since there will be no way to represent
+                 the relocs in the output format being used.  */
+             h = NULL;
+           }
+         else
+           h = _bfd_generic_link_hash_lookup (_bfd_generic_hash_table (info),
+                                              bfd_asymbol_name (sym),
+                                              false, false, true);
+
          if (h != (struct generic_link_hash_entry *) NULL)
            {
              /* Force all references to this symbol to point to
@@ -2037,12 +2080,24 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
                case bfd_link_hash_new:
                  abort ();
                case bfd_link_hash_undefined:
-               case bfd_link_hash_weak:
                  break;
+               case bfd_link_hash_undefweak:
+                 sym->flags |= BSF_WEAK;
+                 break;
+               case bfd_link_hash_indirect:
+                 h = (struct generic_link_hash_entry *) h->root.u.i.link;
+                 /* fall through */
                case bfd_link_hash_defined:
+                 sym->flags |= BSF_GLOBAL;
+                 sym->flags &=~ BSF_CONSTRUCTOR;
+                 sym->value = h->root.u.def.value;
+                 sym->section = h->root.u.def.section;
+                 break;
+               case bfd_link_hash_defweak:
+                 sym->flags |= BSF_WEAK;
+                 sym->flags &=~ BSF_CONSTRUCTOR;
                  sym->value = h->root.u.def.value;
                  sym->section = h->root.u.def.section;
-                 sym->flags |= BSF_GLOBAL;
                  break;
                case bfd_link_hash_common:
                  sym->value = h->root.u.c.size;
@@ -2053,7 +2108,7 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
                      sym->section = bfd_com_section_ptr;
                    }
                  /* We do not set the section of the symbol to
-                    h->root.u.c.section.  That value was saved so
+                    h->root.u.c.p->section.  That value was saved so
                     that we would know where to allocate the symbol
                     if it was defined.  In this case the type is
                     still bfd_link_hash_common, so we did not define
@@ -2160,7 +2215,7 @@ set_symbol_from_hash (sym, h)
       sym->section = bfd_und_section_ptr;
       sym->value = 0;
       break;
-    case bfd_link_hash_weak:
+    case bfd_link_hash_undefweak:
       sym->section = bfd_und_section_ptr;
       sym->value = 0;
       sym->flags |= BSF_WEAK;
@@ -2169,6 +2224,11 @@ set_symbol_from_hash (sym, h)
       sym->section = h->u.def.section;
       sym->value = h->u.def.value;
       break;
+    case bfd_link_hash_defweak:
+      sym->flags |= BSF_WEAK;
+      sym->section = h->u.def.section;
+      sym->value = h->u.def.value;
+      break;
     case bfd_link_hash_common:
       sym->value = h->u.c.size;
       if (sym->section == NULL)
@@ -2263,7 +2323,7 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
       
   r->address = link_order->offset;
   r->howto = bfd_reloc_type_lookup (abfd, link_order->u.reloc.p->reloc);
-  if (r->howto == (const reloc_howto_type *) NULL)
+  if (r->howto == 0)
     {
       bfd_set_error (bfd_error_bad_value);
       return false;
@@ -2586,3 +2646,30 @@ _bfd_count_link_order_relocs (link_order)
 
   return c;
 }
+
+/*
+FUNCTION
+       bfd_link_split_section
+
+SYNOPSIS
+        boolean bfd_link_split_section(bfd *abfd, asection *sec);
+
+DESCRIPTION
+       Return nonzero if @var{sec} should be split during a
+       reloceatable or final link.
+
+.#define bfd_link_split_section(abfd, sec) \
+.       BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec))
+.
+
+*/
+
+
+
+boolean
+_bfd_generic_link_split_section (abfd, sec)
+     bfd *abfd;
+     asection *sec;
+{
+  return false;
+}
This page took 0.030096 seconds and 4 git commands to generate.