* elf.c (bfd_section_from_shdr): Make "name" const.
[deliverable/binutils-gdb.git] / bfd / linker.c
index 1b48f199fe3c10445487383ce603bc74fb7009ca..228f088a0175de28aa3689b5714987e48c1bb8d7 100644 (file)
@@ -1,5 +1,6 @@
 /* linker.c -- BFD linker routines
 /* linker.c -- BFD linker routines
-   Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+   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.
    Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -59,7 +60,7 @@ SECTION
        a.out (in <<aoutx.h>>) and ECOFF (in <<ecoff.c>>).  The a.out
        routines are used as examples throughout this section.
 
        a.out (in <<aoutx.h>>) and ECOFF (in <<ecoff.c>>).  The a.out
        routines are used as examples throughout this section.
 
-@menu  
+@menu
 @* Creating a Linker Hash Table::
 @* Adding Symbols to the Hash Table::
 @* Performing the Final Link::
 @* Creating a Linker Hash Table::
 @* Adding Symbols to the Hash Table::
 @* Performing the Final Link::
@@ -74,7 +75,7 @@ SUBSECTION
 @cindex target vector (_bfd_link_hash_table_create)
        The linker routines must create a hash table, which must be
        derived from <<struct bfd_link_hash_table>> described in
 @cindex target vector (_bfd_link_hash_table_create)
        The linker routines must create a hash table, which must be
        derived from <<struct bfd_link_hash_table>> described in
-       <<bfdlink.c>>.  @xref{Hash Tables} for information on how to
+       <<bfdlink.c>>.  @xref{Hash Tables}, for information on how to
        create a derived hash table.  This entry point is called using
        the target vector of the linker output file.
 
        create a derived hash table.  This entry point is called using
        the target vector of the linker output file.
 
@@ -395,8 +396,7 @@ SUBSUBSECTION
        is used to further controls which local symbols are included
        in the output file.  If the value is <<discard_l>>, then all
        local symbols which begin with a certain prefix are discarded;
        is used to further controls which local symbols are included
        in the output file.  If the value is <<discard_l>>, then all
        local symbols which begin with a certain prefix are discarded;
-       this prefix is described by the <<lprefix>> and
-       <<lprefix_len>> fields of the <<bfd_link_info>> structure.
+       this is controlled by the <<bfd_is_local_label_name>> entry point.
 
        The a.out backend handles symbols by calling
        <<aout_link_write_symbols>> on each input BFD and then
 
        The a.out backend handles symbols by calling
        <<aout_link_write_symbols>> on each input BFD and then
@@ -426,7 +426,7 @@ static void set_symbol_from_hash
   PARAMS ((asymbol *, struct bfd_link_hash_entry *));
 static boolean generic_add_output_symbol
   PARAMS ((bfd *, size_t *psymalloc, asymbol *));
   PARAMS ((asymbol *, struct bfd_link_hash_entry *));
 static boolean generic_add_output_symbol
   PARAMS ((bfd *, size_t *psymalloc, asymbol *));
-static boolean default_fill_link_order
+static boolean default_data_link_order
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
           struct bfd_link_order *));
 static boolean default_indirect_link_order
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
           struct bfd_link_order *));
 static boolean default_indirect_link_order
@@ -445,28 +445,27 @@ _bfd_link_hash_newfunc (entry, table, string)
      struct bfd_hash_table *table;
      const char *string;
 {
      struct bfd_hash_table *table;
      const char *string;
 {
-  struct bfd_link_hash_entry *ret = (struct bfd_link_hash_entry *) entry;
-
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
-  if (ret == (struct bfd_link_hash_entry *) NULL)
-    ret = ((struct bfd_link_hash_entry *)
-          bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry)));
-  if (ret == (struct bfd_link_hash_entry *) NULL)
-    return NULL;
+  if (entry == NULL)
+    {
+      entry = bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry));
+      if (entry == NULL)
+       return entry;
+    }
 
   /* Call the allocation method of the superclass.  */
 
   /* Call the allocation method of the superclass.  */
-  ret = ((struct bfd_link_hash_entry *)
-        bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
-
-  if (ret)
+  entry = bfd_hash_newfunc (entry, table, string);
+  if (entry)
     {
     {
+      struct bfd_link_hash_entry *h = (struct bfd_link_hash_entry *) entry;
+
       /* Initialize the local fields.  */
       /* Initialize the local fields.  */
-      ret->type = bfd_link_hash_new;
-      ret->next = NULL;
+      h->type = bfd_link_hash_new;
+      h->next = NULL;
     }
 
     }
 
-  return (struct bfd_hash_entry *) ret;
+  return entry;
 }
 
 /* Initialize a link hash table.  The BFD argument is the one
 }
 
 /* Initialize a link hash table.  The BFD argument is the one
@@ -483,6 +482,8 @@ _bfd_link_hash_table_init (table, abfd, newfunc)
   table->creator = abfd->xvec;
   table->undefs = NULL;
   table->undefs_tail = NULL;
   table->creator = abfd->xvec;
   table->undefs = NULL;
   table->undefs_tail = NULL;
+  table->type = bfd_link_generic_hash_table;
+
   return bfd_hash_table_init (&table->table, newfunc);
 }
 
   return bfd_hash_table_init (&table->table, newfunc);
 }
 
@@ -526,6 +527,8 @@ bfd_wrapped_link_hash_lookup (abfd, info, string, create, copy, follow)
      boolean copy;
      boolean follow;
 {
      boolean copy;
      boolean follow;
 {
+  bfd_size_type amt;
+
   if (info->wrap_hash != NULL)
     {
       const char *l;
   if (info->wrap_hash != NULL)
     {
       const char *l;
@@ -545,7 +548,8 @@ bfd_wrapped_link_hash_lookup (abfd, info, string, create, copy, follow)
          /* This symbol is being wrapped.  We want to replace all
              references to SYM with references to __wrap_SYM.  */
 
          /* This symbol is being wrapped.  We want to replace all
              references to SYM with references to __wrap_SYM.  */
 
-         n = (char *) bfd_malloc (strlen (l) + sizeof WRAP + 1);
+         amt = strlen (l) + sizeof WRAP + 1;
+         n = (char *) bfd_malloc (amt);
          if (n == NULL)
            return NULL;
 
          if (n == NULL)
            return NULL;
 
@@ -576,7 +580,8 @@ bfd_wrapped_link_hash_lookup (abfd, info, string, create, copy, follow)
              wrapped.  We want to replace all references to __real_SYM
              with references to SYM.  */
 
              wrapped.  We want to replace all references to __real_SYM
              with references to SYM.  */
 
-         n = (char *) bfd_malloc (strlen (l + sizeof REAL - 1) + 2);
+         amt = strlen (l + sizeof REAL - 1) + 2;
+         n = (char *) bfd_malloc (amt);
          if (n == NULL)
            return NULL;
 
          if (n == NULL)
            return NULL;
 
@@ -601,7 +606,7 @@ bfd_wrapped_link_hash_lookup (abfd, info, string, create, copy, follow)
    struct bfd_link_hash_entry * with no explicit cast required on the
    call.  */
 
    struct bfd_link_hash_entry * with no explicit cast required on the
    call.  */
 
-void 
+void
 bfd_link_hash_traverse (table, func, info)
      struct bfd_link_hash_table *table;
      boolean (*func) PARAMS ((struct bfd_link_hash_entry *, PTR));
 bfd_link_hash_traverse (table, func, info)
      struct bfd_link_hash_table *table;
      boolean (*func) PARAMS ((struct bfd_link_hash_entry *, PTR));
@@ -636,30 +641,29 @@ _bfd_generic_link_hash_newfunc (entry, table, string)
      struct bfd_hash_table *table;
      const char *string;
 {
      struct bfd_hash_table *table;
      const char *string;
 {
-  struct generic_link_hash_entry *ret =
-    (struct generic_link_hash_entry *) entry;
-
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
-  if (ret == (struct generic_link_hash_entry *) NULL)
-    ret = ((struct generic_link_hash_entry *)
-          bfd_hash_allocate (table, sizeof (struct generic_link_hash_entry)));
-  if (ret == (struct generic_link_hash_entry *) NULL)
-    return NULL;
+  if (entry == NULL)
+    {
+      entry = bfd_hash_allocate (table,
+                                sizeof (struct generic_link_hash_entry));
+      if (entry == NULL)
+       return entry;
+    }
 
   /* Call the allocation method of the superclass.  */
 
   /* Call the allocation method of the superclass.  */
-  ret = ((struct generic_link_hash_entry *)
-        _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
-                                table, string));
-
-  if (ret)
+  entry = _bfd_link_hash_newfunc (entry, table, string);
+  if (entry)
     {
     {
+      struct generic_link_hash_entry *ret;
+
       /* Set local fields.  */
       /* Set local fields.  */
+      ret = (struct generic_link_hash_entry *) entry;
       ret->written = false;
       ret->sym = NULL;
     }
 
       ret->written = false;
       ret->sym = NULL;
     }
 
-  return (struct bfd_hash_entry *) ret;
+  return entry;
 }
 
 /* Create an generic link hash table.  */
 }
 
 /* Create an generic link hash table.  */
@@ -669,9 +673,9 @@ _bfd_generic_link_hash_table_create (abfd)
      bfd *abfd;
 {
   struct generic_link_hash_table *ret;
      bfd *abfd;
 {
   struct generic_link_hash_table *ret;
+  bfd_size_type amt = sizeof (struct generic_link_hash_table);
 
 
-  ret = ((struct generic_link_hash_table *)
-        bfd_alloc (abfd, sizeof (struct generic_link_hash_table)));
+  ret = (struct generic_link_hash_table *) bfd_malloc (amt);
   if (ret == NULL)
     return (struct bfd_link_hash_table *) NULL;
   if (! _bfd_link_hash_table_init (&ret->root, abfd,
   if (ret == NULL)
     return (struct bfd_link_hash_table *) NULL;
   if (! _bfd_link_hash_table_init (&ret->root, abfd,
@@ -683,6 +687,17 @@ _bfd_generic_link_hash_table_create (abfd)
   return &ret->root;
 }
 
   return &ret->root;
 }
 
+void
+_bfd_generic_link_hash_table_free (hash)
+     struct bfd_link_hash_table *hash;
+{
+  struct generic_link_hash_table *ret
+    = (struct generic_link_hash_table *) hash;
+
+  bfd_hash_table_free (&ret->root.table);
+  free (ret);
+}
+
 /* Grab the symbols for an object file when doing a generic link.  We
    store the symbols in the outsymbols field.  We need to keep them
    around for the entire link to ensure that we only read them once.
 /* Grab the symbols for an object file when doing a generic link.  We
    store the symbols in the outsymbols field.  We need to keep them
    around for the entire link to ensure that we only read them once.
@@ -694,7 +709,7 @@ static boolean
 generic_link_read_symbols (abfd)
      bfd *abfd;
 {
 generic_link_read_symbols (abfd)
      bfd *abfd;
 {
-  if (abfd->outsymbols == (asymbol **) NULL)
+  if (bfd_get_outsymbols (abfd) == (asymbol **) NULL)
     {
       long symsize;
       long symcount;
     {
       long symsize;
       long symcount;
@@ -702,13 +717,14 @@ generic_link_read_symbols (abfd)
       symsize = bfd_get_symtab_upper_bound (abfd);
       if (symsize < 0)
        return false;
       symsize = bfd_get_symtab_upper_bound (abfd);
       if (symsize < 0)
        return false;
-      abfd->outsymbols = (asymbol **) bfd_alloc (abfd, symsize);
-      if (abfd->outsymbols == NULL && symsize != 0)
+      bfd_get_outsymbols (abfd) =
+       (asymbol **) bfd_alloc (abfd, (bfd_size_type) symsize);
+      if (bfd_get_outsymbols (abfd) == NULL && symsize != 0)
        return false;
        return false;
-      symcount = bfd_canonicalize_symtab (abfd, abfd->outsymbols);
+      symcount = bfd_canonicalize_symtab (abfd, bfd_get_outsymbols (abfd));
       if (symcount < 0)
        return false;
       if (symcount < 0)
        return false;
-      abfd->symcount = symcount;
+      bfd_get_symcount (abfd) = symcount;
     }
 
   return true;
     }
 
   return true;
@@ -741,6 +757,19 @@ _bfd_generic_link_add_symbols_collect (abfd, info)
   return generic_link_add_symbols (abfd, info, true);
 }
 
   return generic_link_add_symbols (abfd, info, true);
 }
 
+/* Indicate that we are only retrieving symbol values from this
+   section.  We want the symbols to act as though the values in the
+   file are absolute.  */
+
+void
+_bfd_generic_link_just_syms (sec, info)
+     asection *sec;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+{
+  sec->output_section = bfd_abs_section_ptr;
+  sec->output_offset = sec->vma;
+}
+
 /* Add symbols from an object file to the global hash table.  */
 
 static boolean
 /* Add symbols from an object file to the global hash table.  */
 
 static boolean
@@ -779,12 +808,14 @@ generic_link_add_object_symbols (abfd, info, collect)
      struct bfd_link_info *info;
      boolean collect;
 {
      struct bfd_link_info *info;
      boolean collect;
 {
+  bfd_size_type symcount;
+  struct symbol_cache_entry **outsyms;
+
   if (! generic_link_read_symbols (abfd))
     return false;
   if (! generic_link_read_symbols (abfd))
     return false;
-  return generic_link_add_symbol_list (abfd, info,
-                                      _bfd_generic_link_get_symcount (abfd),
-                                      _bfd_generic_link_get_symbols (abfd),
-                                      collect);
+  symcount = _bfd_generic_link_get_symcount (abfd);
+  outsyms = _bfd_generic_link_get_symbols (abfd);
+  return generic_link_add_symbol_list (abfd, info, symcount, outsyms, collect);
 }
 \f
 /* We build a hash table of all symbols defined in an archive.  */
 }
 \f
 /* We build a hash table of all symbols defined in an archive.  */
@@ -795,7 +826,7 @@ generic_link_add_object_symbols (abfd, info, collect)
 struct archive_list
 {
   struct archive_list *next;
 struct archive_list
 {
   struct archive_list *next;
-  int indx;
+  unsigned int indx;
 };
 
 /* An entry in an archive hash table.  */
 };
 
 /* An entry in an archive hash table.  */
@@ -924,7 +955,7 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
   register carsym *arsym;
   int pass;
   struct archive_hash_table arsym_hash;
   register carsym *arsym;
   int pass;
   struct archive_hash_table arsym_hash;
-  int indx;
+  unsigned int indx;
   struct bfd_link_hash_entry **pundef;
 
   if (! bfd_has_map (abfd))
   struct bfd_link_hash_entry **pundef;
 
   if (! bfd_has_map (abfd))
@@ -1003,10 +1034,25 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
       arh = archive_hash_lookup (&arsym_hash, h->root.string, false, false);
       if (arh == (struct archive_hash_entry *) NULL)
        {
       arh = archive_hash_lookup (&arsym_hash, h->root.string, false, false);
       if (arh == (struct archive_hash_entry *) NULL)
        {
-         pundef = &(*pundef)->next;
-         continue;
-       }
+         /* If we haven't found the exact symbol we're looking for,
+            let's look for its import thunk */
+         if (info->pei386_auto_import)
+           {
+             bfd_size_type amt = strlen (h->root.string) + 10;
+             char *buf = (char *) bfd_malloc (amt);
+             if (buf == NULL)
+               return false;
 
 
+             sprintf (buf, "__imp_%s", h->root.string);
+             arh = archive_hash_lookup (&arsym_hash, buf, false, false);
+             free(buf);
+           }
+         if (arh == (struct archive_hash_entry *) NULL)
+           {
+             pundef = &(*pundef)->next;
+             continue;
+           }
+       }
       /* Look at all the objects which define this symbol.  */
       for (l = arh->defs; l != (struct archive_list *) NULL; l = l->next)
        {
       /* Look at all the objects which define this symbol.  */
       for (l = arh->defs; l != (struct archive_list *) NULL; l = l->next)
        {
@@ -1320,14 +1366,14 @@ generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect)
                  if (bfd_is_com_section (bfd_get_section (p)))
                    p->flags |= BSF_OLD_COMMON;
                }
                  if (bfd_is_com_section (bfd_get_section (p)))
                    p->flags |= BSF_OLD_COMMON;
                }
-
-             /* Store a back pointer from the symbol to the hash
-                table entry for the benefit of relaxation code until
-                it gets rewritten to not use asymbol structures.
-                Setting this is also used to check whether these
-                symbols were set up by the generic linker.  */
-             p->udata.p = (PTR) h;
            }
            }
+
+         /* Store a back pointer from the symbol to the hash
+            table entry for the benefit of relaxation code until
+            it gets rewritten to not use asymbol structures.
+            Setting this is also used to check whether these
+            symbols were set up by the generic linker.  */
+         p->udata.p = (PTR) h;
        }
     }
 
        }
     }
 
@@ -1361,7 +1407,7 @@ enum link_row
 
 enum link_action
 {
 
 enum link_action
 {
-  FAIL,                /* Abort. */
+  FAIL,                /* Abort.  */
   UND,         /* Mark symbol undefined.  */
   WEAK,                /* Mark symbol weak undefined.  */
   DEF,         /* Mark symbol defined.  */
   UND,         /* Mark symbol undefined.  */
   WEAK,                /* Mark symbol weak undefined.  */
   DEF,         /* Mark symbol defined.  */
@@ -1395,9 +1441,9 @@ static const enum link_action link_action[8][8] =
   /* 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 },
   /* 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 },
+  /* COMMON_ROW        */  {COM,   COM,   COM,   CREF,  COM,   BIG,   REFC,  WARNC },
   /* INDR_ROW  */  {IND,   IND,   IND,   MDEF,  IND,   CIND,  MIND,  CYCLE },
   /* INDR_ROW  */  {IND,   IND,   IND,   MDEF,  IND,   CIND,  MIND,  CYCLE },
-  /* WARN_ROW   */  {MWARN, WARN,  WARN,  CWARN, CWARN, WARN,  CWARN, MWARN },
+  /* WARN_ROW   */  {MWARN, WARN,  WARN,  CWARN, CWARN, WARN,  CWARN, NOACT },
   /* SET_ROW   */  {SET,   SET,   SET,   SET,   SET,   SET,   CYCLE, CYCLE }
 };
 
   /* SET_ROW   */  {SET,   SET,   SET,   SET,   SET,   SET,   CYCLE, CYCLE }
 };
 
@@ -1464,7 +1510,7 @@ hash_entry_bfd (h)
      or destructor names as collect2 does.
    HASHP, if not NULL, is a place to store the created hash table
      entry; if *HASHP is not NULL, the caller has already looked up
      or destructor names as collect2 does.
    HASHP, if not NULL, is a place to store the created hash table
      entry; if *HASHP is not NULL, the caller has already looked up
-     the hash table entry, and stored it in *HASHP. */
+     the hash table entry, and stored it in *HASHP.  */
 
 boolean
 _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
 
 boolean
 _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
@@ -1698,7 +1744,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
        case BIG:
          /* We have found a common definition for a symbol which
             already had a common definition.  Use the maximum of the
        case BIG:
          /* We have found a common definition for a symbol which
             already had a common definition.  Use the maximum of the
-            two sizes.  */
+            two sizes, and use the section required by the larger symbol.  */
          BFD_ASSERT (h->type == bfd_link_hash_common);
          if (! ((*info->callbacks->multiple_common)
                 (info, h->root.string,
          BFD_ASSERT (h->type == bfd_link_hash_common);
          if (! ((*info->callbacks->multiple_common)
                 (info, h->root.string,
@@ -1717,6 +1763,25 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
              if (power > 4)
                power = 4;
              h->u.c.p->alignment_power = power;
              if (power > 4)
                power = 4;
              h->u.c.p->alignment_power = power;
+
+             /* Some systems have special treatment for small commons,
+                hence we want to select the section used by the larger
+                symbol.  This makes sure the symbol does not go in a
+                small common section if it is now too large.  */
+             if (section == bfd_com_section_ptr)
+               {
+                 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.p->section
+                   = bfd_make_section_old_way (abfd, section->name);
+                 h->u.c.p->section->flags = SEC_ALLOC;
+               }
+             else
+               h->u.c.p->section = section;
            }
          break;
 
            }
          break;
 
@@ -1748,37 +1813,38 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
          /* Fall through.  */
        case MDEF:
          /* Handle a multiple definition.  */
          /* Fall through.  */
        case MDEF:
          /* Handle a multiple definition.  */
-         {
-           asection *msec;
-           bfd_vma mval;
+         if (!info->allow_multiple_definition)
+           {
+             asection *msec = NULL;
+             bfd_vma mval = 0;
 
 
-           switch (h->type)
-             {
-             case bfd_link_hash_defined:
-               msec = h->u.def.section;
-               mval = h->u.def.value;
-               break;
-             case bfd_link_hash_indirect:
-               msec = bfd_ind_section_ptr;
-               mval = 0;
-               break;
-             default:
-               abort ();
-             }
+             switch (h->type)
+               {
+               case bfd_link_hash_defined:
+                 msec = h->u.def.section;
+                 mval = h->u.def.value;
+                 break;
+               case bfd_link_hash_indirect:
+                 msec = bfd_ind_section_ptr;
+                 mval = 0;
+                 break;
+               default:
+                 abort ();
+               }
 
 
-           /* Ignore a redefinition of an absolute symbol to the same
-               value; it's harmless.  */
-           if (h->type == bfd_link_hash_defined
-               && bfd_is_abs_section (msec)
-               && bfd_is_abs_section (section)
-               && value == mval)
-             break;
+             /* Ignore a redefinition of an absolute symbol to the
+                same value; it's harmless.  */
+             if (h->type == bfd_link_hash_defined
+                 && bfd_is_abs_section (msec)
+                 && bfd_is_abs_section (section)
+                 && value == mval)
+               break;
 
 
-           if (! ((*info->callbacks->multiple_definition)
-                  (info, h->root.string, msec->owner, msec, mval, abfd,
-                   section, value)))
-             return false;
-         }
+             if (! ((*info->callbacks->multiple_definition)
+                    (info, h->root.string, msec->owner, msec, mval,
+                     abfd, section, value)))
+               return false;
+           }
          break;
 
        case CIND:
          break;
 
        case CIND:
@@ -1801,6 +1867,15 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
                                                copy, false);
            if (inh == (struct bfd_link_hash_entry *) NULL)
              return false;
                                                copy, false);
            if (inh == (struct bfd_link_hash_entry *) NULL)
              return false;
+           if (inh->type == bfd_link_hash_indirect
+               && inh->u.i.link == h)
+             {
+               (*_bfd_error_handler)
+                 (_("%s: indirect symbol `%s' to `%s' is a loop"),
+                  bfd_archive_filename (abfd), name, string);
+               bfd_set_error (bfd_error_invalid_operation);
+               return false;
+             }
            if (inh->type == bfd_link_hash_new)
              {
                inh->type = bfd_link_hash_undefined;
            if (inh->type == bfd_link_hash_new)
              {
                inh->type = bfd_link_hash_undefined;
@@ -1936,8 +2011,8 @@ _bfd_generic_final_link (abfd, info)
   size_t outsymalloc;
   struct generic_write_global_symbol_info wginfo;
 
   size_t outsymalloc;
   struct generic_write_global_symbol_info wginfo;
 
-  abfd->outsymbols = (asymbol **) NULL;
-  abfd->symcount = 0;
+  bfd_get_outsymbols (abfd) = (asymbol **) NULL;
+  bfd_get_symcount (abfd) = 0;
   outsymalloc = 0;
 
   /* Mark all sections which will be included in the output file.  */
   outsymalloc = 0;
 
   /* Mark all sections which will be included in the output file.  */
@@ -1959,6 +2034,12 @@ _bfd_generic_final_link (abfd, info)
                                   _bfd_generic_link_write_global_symbol,
                                   (PTR) &wginfo);
 
                                   _bfd_generic_link_write_global_symbol,
                                   (PTR) &wginfo);
 
+  /* Make sure we have a trailing NULL pointer on OUTSYMBOLS.  We
+     shouldn't really need one, since we have SYMCOUNT, but some old
+     code still expects one.  */
+  if (! generic_add_output_symbol (abfd, &outsymalloc, NULL))
+    return false;
+
   if (info->relocateable)
     {
       /* Allocate space for the output relocs for each section.  */
   if (info->relocateable)
     {
       /* Allocate space for the output relocs for each section.  */
@@ -1989,7 +2070,7 @@ _bfd_generic_final_link (abfd, info)
                                                       input_section);
                  if (relsize < 0)
                    return false;
                                                       input_section);
                  if (relsize < 0)
                    return false;
-                 relocs = (arelent **) bfd_malloc ((size_t) relsize);
+                 relocs = (arelent **) bfd_malloc ((bfd_size_type) relsize);
                  if (!relocs && relsize != 0)
                    return false;
                  symbols = _bfd_generic_link_get_symbols (input_bfd);
                  if (!relocs && relsize != 0)
                    return false;
                  symbols = _bfd_generic_link_get_symbols (input_bfd);
@@ -2007,10 +2088,11 @@ _bfd_generic_final_link (abfd, info)
            }
          if (o->reloc_count > 0)
            {
            }
          if (o->reloc_count > 0)
            {
-             o->orelocation = ((arelent **)
-                               bfd_alloc (abfd,
-                                          (o->reloc_count
-                                           * sizeof (arelent *))));
+             bfd_size_type amt;
+
+             amt = o->reloc_count;
+             amt *= sizeof (arelent *);
+             o->orelocation = (arelent **) bfd_alloc (abfd, amt);
              if (!o->orelocation)
                return false;
              o->flags |= SEC_RELOC;
              if (!o->orelocation)
                return false;
              o->flags |= SEC_RELOC;
@@ -2060,23 +2142,26 @@ generic_add_output_symbol (output_bfd, psymalloc, sym)
      size_t *psymalloc;
      asymbol *sym;
 {
      size_t *psymalloc;
      asymbol *sym;
 {
-  if (output_bfd->symcount >= *psymalloc)
+  if (bfd_get_symcount (output_bfd) >= *psymalloc)
     {
       asymbol **newsyms;
     {
       asymbol **newsyms;
+      bfd_size_type amt;
 
       if (*psymalloc == 0)
        *psymalloc = 124;
       else
        *psymalloc *= 2;
 
       if (*psymalloc == 0)
        *psymalloc = 124;
       else
        *psymalloc *= 2;
-      newsyms = (asymbol **) bfd_realloc (output_bfd->outsymbols,
-                                         *psymalloc * sizeof (asymbol *));
+      amt = *psymalloc;
+      amt *= sizeof (asymbol *);
+      newsyms = (asymbol **) bfd_realloc (bfd_get_outsymbols (output_bfd), amt);
       if (newsyms == (asymbol **) NULL)
        return false;
       if (newsyms == (asymbol **) NULL)
        return false;
-      output_bfd->outsymbols = newsyms;
+      bfd_get_outsymbols (output_bfd) = newsyms;
     }
 
     }
 
-  output_bfd->outsymbols[output_bfd->symcount] = sym;
-  ++output_bfd->symcount;
+  bfd_get_outsymbols (output_bfd) [bfd_get_symcount (output_bfd)] = sym;
+  if (sym != NULL)
+    ++ bfd_get_symcount (output_bfd);
 
   return true;
 }
 
   return true;
 }
@@ -2272,11 +2357,14 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
                case discard_all:
                  output = false;
                  break;
                case discard_all:
                  output = false;
                  break;
+               case discard_sec_merge:
+                 output = true;
+                 if (info->relocateable
+                     || ! (sym->section->flags & SEC_MERGE))
+                   break;
+                 /* FALLTHROUGH */
                case discard_l:
                case discard_l:
-                 if (bfd_asymbol_name (sym)[0] == info->lprefix[0]
-                     && (info->lprefix_len == 1
-                         || strncmp (bfd_asymbol_name (sym), info->lprefix,
-                                     info->lprefix_len) == 0))
+                 if (bfd_is_local_label (input_bfd, sym))
                    output = false;
                  else
                    output = true;
                    output = false;
                  else
                    output = true;
@@ -2298,8 +2386,12 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
        abort ();
 
       /* If this symbol is in a section which is not being included
        abort ();
 
       /* If this symbol is in a section which is not being included
-        in the output file, then we don't want to output the symbol.  */
-      if (sym->section->linker_mark == false)
+        in the output file, then we don't want to output the symbol.
+
+        Gross.  .bss and similar sections won't have the linker_mark
+        field set.  */
+      if ((sym->section->flags & SEC_HAS_CONTENTS) != 0
+         && sym->section->linker_mark == false)
        output = false;
 
       if (output)
        output = false;
 
       if (output)
@@ -2389,6 +2481,9 @@ _bfd_generic_link_write_global_symbol (h, data)
     (struct generic_write_global_symbol_info *) data;
   asymbol *sym;
 
     (struct generic_write_global_symbol_info *) data;
   asymbol *sym;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct generic_link_hash_entry *) h->root.u.i.link;
+
   if (h->written)
     return true;
 
   if (h->written)
     return true;
 
@@ -2441,10 +2536,10 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
   if (sec->orelocation == (arelent **) NULL)
     abort ();
 
   if (sec->orelocation == (arelent **) NULL)
     abort ();
 
-  r = (arelent *) bfd_alloc (abfd, sizeof (arelent));
+  r = (arelent *) bfd_alloc (abfd, (bfd_size_type) sizeof (arelent));
   if (r == (arelent *) NULL)
     return false;
   if (r == (arelent *) NULL)
     return false;
-      
+
   r->address = link_order->offset;
   r->howto = bfd_reloc_type_lookup (abfd, link_order->u.reloc.p->reloc);
   if (r->howto == 0)
   r->address = link_order->offset;
   r->howto = bfd_reloc_type_lookup (abfd, link_order->u.reloc.p->reloc);
   if (r->howto == 0)
@@ -2487,13 +2582,15 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
       bfd_reloc_status_type rstat;
       bfd_byte *buf;
       boolean ok;
       bfd_reloc_status_type rstat;
       bfd_byte *buf;
       boolean ok;
+      file_ptr loc;
 
       size = bfd_get_reloc_size (r->howto);
       buf = (bfd_byte *) bfd_zmalloc (size);
       if (buf == (bfd_byte *) NULL)
        return false;
       rstat = _bfd_relocate_contents (r->howto, abfd,
 
       size = bfd_get_reloc_size (r->howto);
       buf = (bfd_byte *) bfd_zmalloc (size);
       if (buf == (bfd_byte *) NULL)
        return false;
       rstat = _bfd_relocate_contents (r->howto, abfd,
-                                     link_order->u.reloc.p->addend, buf);
+                                     (bfd_vma) link_order->u.reloc.p->addend,
+                                     buf);
       switch (rstat)
        {
        case bfd_reloc_ok:
       switch (rstat)
        {
        case bfd_reloc_ok:
@@ -2515,8 +2612,9 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
            }
          break;
        }
            }
          break;
        }
-      ok = bfd_set_section_contents (abfd, sec, (PTR) buf,
-                                    (file_ptr) link_order->offset, size);
+      loc = link_order->offset * bfd_octets_per_byte (abfd);
+      ok = bfd_set_section_contents (abfd, sec, (PTR) buf, loc,
+                                    (bfd_size_type) size);
       free (buf);
       if (! ok)
        return false;
       free (buf);
       if (! ok)
        return false;
@@ -2537,17 +2635,14 @@ bfd_new_link_order (abfd, section)
      bfd *abfd;
      asection *section;
 {
      bfd *abfd;
      asection *section;
 {
+  bfd_size_type amt = sizeof (struct bfd_link_order);
   struct bfd_link_order *new;
 
   struct bfd_link_order *new;
 
-  new = ((struct bfd_link_order *)
-        bfd_alloc_by_size_t (abfd, sizeof (struct bfd_link_order)));
+  new = (struct bfd_link_order *) bfd_zalloc (abfd, amt);
   if (!new)
     return NULL;
 
   new->type = bfd_undefined_link_order;
   if (!new)
     return NULL;
 
   new->type = bfd_undefined_link_order;
-  new->offset = 0;
-  new->size = 0;
-  new->next = (struct bfd_link_order *) NULL;
 
   if (section->link_order_tail != (struct bfd_link_order *) NULL)
     section->link_order_tail->next = new;
 
   if (section->link_order_tail != (struct bfd_link_order *) NULL)
     section->link_order_tail->next = new;
@@ -2579,48 +2674,63 @@ _bfd_default_link_order (abfd, info, sec, link_order)
     case bfd_indirect_link_order:
       return default_indirect_link_order (abfd, info, sec, link_order,
                                          false);
     case bfd_indirect_link_order:
       return default_indirect_link_order (abfd, info, sec, link_order,
                                          false);
-    case bfd_fill_link_order:
-      return default_fill_link_order (abfd, info, sec, link_order);
     case bfd_data_link_order:
     case bfd_data_link_order:
-      return bfd_set_section_contents (abfd, sec,
-                                      (PTR) link_order->u.data.contents,
-                                      (file_ptr) link_order->offset,
-                                      link_order->size);
+      return default_data_link_order (abfd, info, sec, link_order);
     }
 }
 
     }
 }
 
-/* Default routine to handle a bfd_fill_link_order.  */
+/* Default routine to handle a bfd_data_link_order.  */
 
 
-/*ARGSUSED*/
 static boolean
 static boolean
-default_fill_link_order (abfd, info, sec, link_order)
+default_data_link_order (abfd, info, sec, link_order)
      bfd *abfd;
      bfd *abfd;
-     struct bfd_link_info *info;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
      asection *sec;
      struct bfd_link_order *link_order;
 {
      asection *sec;
      struct bfd_link_order *link_order;
 {
-  size_t size;
-  char *space;
-  size_t i;
-  int fill;
+  bfd_size_type size;
+  size_t fill_size;
+  bfd_byte *fill;
+  file_ptr loc;
   boolean result;
 
   BFD_ASSERT ((sec->flags & SEC_HAS_CONTENTS) != 0);
 
   boolean result;
 
   BFD_ASSERT ((sec->flags & SEC_HAS_CONTENTS) != 0);
 
-  size = (size_t) link_order->size;
-  space = (char *) bfd_malloc (size);
-  if (space == NULL && size != 0)
-    return false;
+  size = link_order->size;
+  if (size == 0)
+    return true;
+
+  fill = link_order->u.data.contents;
+  fill_size = link_order->u.data.size;
+  if (fill_size != 0 && fill_size < size)
+    {
+      bfd_byte *p;
+      fill = (bfd_byte *) bfd_malloc (size);
+      if (fill == NULL)
+       return false;
+      p = fill;
+      if (fill_size == 1)
+       memset (p, (int) link_order->u.data.contents[0], (size_t) size);
+      else
+       {
+         do
+           {
+             memcpy (p, link_order->u.data.contents, fill_size);
+             p += fill_size;
+             size -= fill_size;
+           }
+         while (size >= fill_size);
+         if (size != 0)
+           memcpy (p, link_order->u.data.contents, (size_t) size);
+         size = link_order->size;
+       }
+    }
 
 
-  fill = link_order->u.fill.value;
-  for (i = 0; i < size; i += 2)
-    space[i] = fill >> 8;
-  for (i = 1; i < size; i += 2)
-    space[i] = fill;
-  result = bfd_set_section_contents (abfd, sec, space,
-                                    (file_ptr) link_order->offset,
-                                    link_order->size);
-  free (space);
+  loc = link_order->offset * bfd_octets_per_byte (abfd);
+  result = bfd_set_section_contents (abfd, sec, fill, loc, size);
+
+  if (fill != link_order->u.data.contents)
+    free (fill);
   return result;
 }
 
   return result;
 }
 
@@ -2639,6 +2749,8 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
   bfd *input_bfd;
   bfd_byte *contents = NULL;
   bfd_byte *new_contents;
   bfd *input_bfd;
   bfd_byte *contents = NULL;
   bfd_byte *new_contents;
+  bfd_size_type sec_size;
+  file_ptr loc;
 
   BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0);
 
 
   BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0);
 
@@ -2662,7 +2774,7 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
         types of object files.  Handling this case correctly is
         difficult, and sometimes impossible.  */
       (*_bfd_error_handler)
         types of object files.  Handling this case correctly is
         difficult, and sometimes impossible.  */
       (*_bfd_error_handler)
-       ("Attempt to do relocateable link with %s input and %s output",
+       (_("Attempt to do relocateable link with %s input and %s output"),
         bfd_get_target (input_bfd), bfd_get_target (output_bfd));
       bfd_set_error (bfd_error_wrong_format);
       return false;
         bfd_get_target (input_bfd), bfd_get_target (output_bfd));
       bfd_set_error (bfd_error_wrong_format);
       return false;
@@ -2718,13 +2830,13 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
              if (h != NULL)
                set_symbol_from_hash (sym, h);
            }
              if (h != NULL)
                set_symbol_from_hash (sym, h);
            }
-       }         
+       }
     }
 
   /* Get and relocate the section contents.  */
     }
 
   /* Get and relocate the section contents.  */
-  contents = ((bfd_byte *)
-             bfd_malloc (bfd_section_size (input_bfd, input_section)));
-  if (contents == NULL && bfd_section_size (input_bfd, input_section) != 0)
+  sec_size = bfd_section_size (input_bfd, input_section);
+  contents = ((bfd_byte *) bfd_malloc (sec_size));
+  if (contents == NULL && sec_size != 0)
     goto error_return;
   new_contents = (bfd_get_relocated_section_contents
                  (output_bfd, info, link_order, contents, info->relocateable,
     goto error_return;
   new_contents = (bfd_get_relocated_section_contents
                  (output_bfd, info, link_order, contents, info->relocateable,
@@ -2733,9 +2845,9 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
     goto error_return;
 
   /* Output the section contents.  */
     goto error_return;
 
   /* Output the section contents.  */
+  loc = link_order->offset * bfd_octets_per_byte (output_bfd);
   if (! bfd_set_section_contents (output_bfd, output_section,
   if (! bfd_set_section_contents (output_bfd, output_section,
-                                 (PTR) new_contents,
-                                 link_order->offset, link_order->size))
+                                 (PTR) new_contents, loc, link_order->size))
     goto error_return;
 
   if (contents != NULL)
     goto error_return;
 
   if (contents != NULL)
@@ -2786,12 +2898,10 @@ DESCRIPTION
 
 */
 
 
 */
 
-
-
 boolean
 _bfd_generic_link_split_section (abfd, sec)
 boolean
 _bfd_generic_link_split_section (abfd, sec)
-     bfd *abfd;
-     asection *sec;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *sec ATTRIBUTE_UNUSED;
 {
   return false;
 }
 {
   return false;
 }
This page took 0.050645 seconds and 4 git commands to generate.