* bfd.m4 (BFD_NEED_DECLARATION): Restore.
[deliverable/binutils-gdb.git] / bfd / linker.c
index c0e3236f853e04b3d95c05848cb0bdeb61c82b12..89630c0e2f0301402e3db740e8cf210b923fbef0 100644 (file)
@@ -1,6 +1,6 @@
 /* linker.c -- BFD linker routines
-   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   Free Software Foundation, Inc.
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+   2003, 2004, 2005 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.
@@ -88,7 +88,7 @@ SUBSECTION
 
        For example, with each entry in the hash table the a.out
        linker keeps the index the symbol has in the final output file
-       (this index number is used so that when doing a relocateable
+       (this index number is used so that when doing a relocatable
        link the symbol index used in the output file can be quickly
        filled in when copying over a reloc).  The a.out linker code
        defines the required structures and functions for a hash table
@@ -277,7 +277,7 @@ SUBSECTION
        the input sections and copy the data into the output sections.
        It must build an output symbol table including any local
        symbols from the input files and the global symbols from the
-       hash table.  When producing relocateable output, it must
+       hash table.  When producing relocatable output, it must
        modify the input relocs and write them into the output file.
        There may also be object format dependent work to be done.
 
@@ -317,7 +317,7 @@ SUBSUBSECTION
        types of information.  They also describe relocs that must be
        created by the BFD backend, but do not correspond to any input
        file; this is used to support -Ur, which builds constructors
-       while generating a relocateable object file.
+       while generating a relocatable object file.
 
 INODE
 Relocating the section contents, Writing the symbol table, Information provided by the linker, Performing the Final Link
@@ -339,7 +339,7 @@ SUBSUBSECTION
        input files.  The <<_bfd_final_link>> function should read the
        contents of the section and any associated relocs, apply the
        relocs to the section contents, and write out the modified
-       section contents.  If performing a relocateable link, the
+       section contents.  If performing a relocatable link, the
        relocs themselves must also be modified and written out.
 
 @findex _bfd_relocate_contents
@@ -406,34 +406,26 @@ SUBSUBSECTION
        file at the end of <<NAME(aout,final_link)>>.
 */
 
-static bfd_boolean generic_link_read_symbols
-  PARAMS ((bfd *));
-static bfd_boolean generic_link_add_symbols
-  PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean collect));
 static bfd_boolean generic_link_add_object_symbols
-  PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean collect));
+  (bfd *, struct bfd_link_info *, bfd_boolean collect);
+static bfd_boolean generic_link_add_symbols
+  (bfd *, struct bfd_link_info *, bfd_boolean);
 static bfd_boolean generic_link_check_archive_element_no_collect
-  PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean *pneeded));
+  (bfd *, struct bfd_link_info *, bfd_boolean *);
 static bfd_boolean generic_link_check_archive_element_collect
-  PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean *pneeded));
+  (bfd *, struct bfd_link_info *, bfd_boolean *);
 static bfd_boolean generic_link_check_archive_element
-  PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean *pneeded,
-          bfd_boolean collect));
+  (bfd *, struct bfd_link_info *, bfd_boolean *, bfd_boolean);
 static bfd_boolean generic_link_add_symbol_list
-  PARAMS ((bfd *, struct bfd_link_info *, bfd_size_type count, asymbol **,
-          bfd_boolean collect));
-static bfd *hash_entry_bfd
-  PARAMS ((struct bfd_link_hash_entry *));
-static void set_symbol_from_hash
-  PARAMS ((asymbol *, struct bfd_link_hash_entry *));
+  (bfd *, struct bfd_link_info *, bfd_size_type count, asymbol **,
+   bfd_boolean);
 static bfd_boolean generic_add_output_symbol
-  PARAMS ((bfd *, size_t *psymalloc, asymbol *));
+  (bfd *, size_t *psymalloc, asymbol *);
 static bfd_boolean default_data_link_order
-  PARAMS ((bfd *, struct bfd_link_info *, asection *,
-          struct bfd_link_order *));
+  (bfd *, struct bfd_link_info *, asection *, struct bfd_link_order *);
 static bfd_boolean default_indirect_link_order
-  PARAMS ((bfd *, struct bfd_link_info *, asection *,
-          struct bfd_link_order *, bfd_boolean));
+  (bfd *, struct bfd_link_info *, asection *, struct bfd_link_order *,
+   bfd_boolean);
 
 /* The link hash table structure is defined in bfdlink.h.  It provides
    a base hash table which the backend specific hash tables are built
@@ -442,17 +434,15 @@ static bfd_boolean default_indirect_link_order
 /* Routine to create an entry in the link hash table.  */
 
 struct bfd_hash_entry *
-_bfd_link_hash_newfunc (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
+_bfd_link_hash_newfunc (struct bfd_hash_entry *entry,
+                       struct bfd_hash_table *table,
+                       const char *string)
 {
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
   if (entry == NULL)
     {
-      entry = (struct bfd_hash_entry *)
-       bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry));
+      entry = bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry));
       if (entry == NULL)
        return entry;
     }
@@ -465,7 +455,9 @@ _bfd_link_hash_newfunc (entry, table, string)
 
       /* Initialize the local fields.  */
       h->type = bfd_link_hash_new;
-      h->next = NULL;
+      memset (&h->u.undef.next, 0,
+             (sizeof (struct bfd_link_hash_entry)
+              - offsetof (struct bfd_link_hash_entry, u.undef.next)));
     }
 
   return entry;
@@ -475,12 +467,12 @@ _bfd_link_hash_newfunc (entry, table, string)
    responsible for creating this table.  */
 
 bfd_boolean
-_bfd_link_hash_table_init (table, abfd, newfunc)
-     struct bfd_link_hash_table *table;
-     bfd *abfd;
-     struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
-                                               struct bfd_hash_table *,
-                                               const char *));
+_bfd_link_hash_table_init
+  (struct bfd_link_hash_table *table,
+   bfd *abfd,
+   struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
+                                     struct bfd_hash_table *,
+                                     const char *))
 {
   table->creator = abfd->xvec;
   table->undefs = NULL;
@@ -495,19 +487,18 @@ _bfd_link_hash_table_init (table, abfd, newfunc)
    the real symbol.  */
 
 struct bfd_link_hash_entry *
-bfd_link_hash_lookup (table, string, create, copy, follow)
-     struct bfd_link_hash_table *table;
-     const char *string;
-     bfd_boolean create;
-     bfd_boolean copy;
-     bfd_boolean follow;
+bfd_link_hash_lookup (struct bfd_link_hash_table *table,
+                     const char *string,
+                     bfd_boolean create,
+                     bfd_boolean copy,
+                     bfd_boolean follow)
 {
   struct bfd_link_hash_entry *ret;
 
   ret = ((struct bfd_link_hash_entry *)
         bfd_hash_lookup (&table->table, string, create, copy));
 
-  if (follow && ret != (struct bfd_link_hash_entry *) NULL)
+  if (follow && ret != NULL)
     {
       while (ret->type == bfd_link_hash_indirect
             || ret->type == bfd_link_hash_warning)
@@ -522,23 +513,26 @@ bfd_link_hash_lookup (table, string, create, copy, follow)
    undefined symbol, not for definitions of a symbol.  */
 
 struct bfd_link_hash_entry *
-bfd_wrapped_link_hash_lookup (abfd, info, string, create, copy, follow)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     const char *string;
-     bfd_boolean create;
-     bfd_boolean copy;
-     bfd_boolean follow;
+bfd_wrapped_link_hash_lookup (bfd *abfd,
+                             struct bfd_link_info *info,
+                             const char *string,
+                             bfd_boolean create,
+                             bfd_boolean copy,
+                             bfd_boolean follow)
 {
   bfd_size_type amt;
 
   if (info->wrap_hash != NULL)
     {
       const char *l;
+      char prefix = '\0';
 
       l = string;
-      if (*l == bfd_get_symbol_leading_char (abfd))
-       ++l;
+      if (*l == bfd_get_symbol_leading_char (abfd) || *l == info->wrap_char)
+       {
+         prefix = *l;
+         ++l;
+       }
 
 #undef WRAP
 #define WRAP "__wrap_"
@@ -552,12 +546,11 @@ bfd_wrapped_link_hash_lookup (abfd, info, string, create, copy, follow)
              references to SYM with references to __wrap_SYM.  */
 
          amt = strlen (l) + sizeof WRAP + 1;
-         n = (char *) bfd_malloc (amt);
+         n = bfd_malloc (amt);
          if (n == NULL)
            return NULL;
 
-         /* Note that symbol_leading_char may be '\0'.  */
-         n[0] = bfd_get_symbol_leading_char (abfd);
+         n[0] = prefix;
          n[1] = '\0';
          strcat (n, WRAP);
          strcat (n, l);
@@ -584,12 +577,11 @@ bfd_wrapped_link_hash_lookup (abfd, info, string, create, copy, follow)
              with references to SYM.  */
 
          amt = strlen (l + sizeof REAL - 1) + 2;
-         n = (char *) bfd_malloc (amt);
+         n = bfd_malloc (amt);
          if (n == NULL)
            return NULL;
 
-         /* Note that symbol_leading_char may be '\0'.  */
-         n[0] = bfd_get_symbol_leading_char (abfd);
+         n[0] = prefix;
          n[1] = '\0';
          strcat (n, l + sizeof REAL - 1);
          h = bfd_link_hash_lookup (info->hash, n, create, TRUE, follow);
@@ -610,45 +602,81 @@ bfd_wrapped_link_hash_lookup (abfd, info, string, create, copy, follow)
    call.  */
 
 void
-bfd_link_hash_traverse (table, func, info)
-     struct bfd_link_hash_table *table;
-     bfd_boolean (*func) PARAMS ((struct bfd_link_hash_entry *, PTR));
-     PTR info;
+bfd_link_hash_traverse
+  (struct bfd_link_hash_table *table,
+   bfd_boolean (*func) (struct bfd_link_hash_entry *, void *),
+   void *info)
 {
   bfd_hash_traverse (&table->table,
-                    ((bfd_boolean (*) PARAMS ((struct bfd_hash_entry *, PTR)))
-                     func),
+                    (bfd_boolean (*) (struct bfd_hash_entry *, void *)) func,
                     info);
 }
 
 /* Add a symbol to the linker hash table undefs list.  */
 
-INLINE void
-bfd_link_add_undef (table, h)
-     struct bfd_link_hash_table *table;
-     struct bfd_link_hash_entry *h;
+void
+bfd_link_add_undef (struct bfd_link_hash_table *table,
+                   struct bfd_link_hash_entry *h)
 {
-  BFD_ASSERT (h->next == NULL);
-  if (table->undefs_tail != (struct bfd_link_hash_entry *) NULL)
-    table->undefs_tail->next = h;
-  if (table->undefs == (struct bfd_link_hash_entry *) NULL)
+  BFD_ASSERT (h->u.undef.next == NULL);
+  if (table->undefs_tail != NULL)
+    table->undefs_tail->u.undef.next = h;
+  if (table->undefs == NULL)
     table->undefs = h;
   table->undefs_tail = h;
 }
+
+/* The undefs list was designed so that in normal use we don't need to
+   remove entries.  However, if symbols on the list are changed from
+   bfd_link_hash_undefined to either bfd_link_hash_undefweak or
+   bfd_link_hash_new for some reason, then they must be removed from the
+   list.  Failure to do so might result in the linker attempting to add
+   the symbol to the list again at a later stage.  */
+
+void
+bfd_link_repair_undef_list (struct bfd_link_hash_table *table)
+{
+  struct bfd_link_hash_entry **pun;
+
+  pun = &table->undefs;
+  while (*pun != NULL)
+    {
+      struct bfd_link_hash_entry *h = *pun;
+
+      if (h->type == bfd_link_hash_new
+         || h->type == bfd_link_hash_undefweak)
+       {
+         *pun = h->u.undef.next;
+         h->u.undef.next = NULL;
+         if (h == table->undefs_tail)
+           {
+             if (pun == &table->undefs)
+               table->undefs_tail = NULL;
+             else
+               /* pun points at an u.undef.next field.  Go back to
+                  the start of the link_hash_entry.  */
+               table->undefs_tail = (struct bfd_link_hash_entry *)
+                 ((char *) pun - ((char *) &h->u.undef.next - (char *) h));
+             break;
+           }
+       }
+      else
+       pun = &h->u.undef.next;
+    }
+}
 \f
 /* Routine to create an entry in a generic link hash table.  */
 
 struct bfd_hash_entry *
-_bfd_generic_link_hash_newfunc (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
+_bfd_generic_link_hash_newfunc (struct bfd_hash_entry *entry,
+                               struct bfd_hash_table *table,
+                               const char *string)
 {
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
   if (entry == NULL)
     {
-      entry = (struct bfd_hash_entry *)
+      entry =
        bfd_hash_allocate (table, sizeof (struct generic_link_hash_entry));
       if (entry == NULL)
        return entry;
@@ -672,27 +700,25 @@ _bfd_generic_link_hash_newfunc (entry, table, string)
 /* Create a generic link hash table.  */
 
 struct bfd_link_hash_table *
-_bfd_generic_link_hash_table_create (abfd)
-     bfd *abfd;
+_bfd_generic_link_hash_table_create (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_malloc (amt);
+  ret = bfd_malloc (amt);
   if (ret == NULL)
-    return (struct bfd_link_hash_table *) NULL;
+    return NULL;
   if (! _bfd_link_hash_table_init (&ret->root, abfd,
                                   _bfd_generic_link_hash_newfunc))
     {
       free (ret);
-      return (struct bfd_link_hash_table *) NULL;
+      return NULL;
     }
   return &ret->root;
 }
 
 void
-_bfd_generic_link_hash_table_free (hash)
-     struct bfd_link_hash_table *hash;
+_bfd_generic_link_hash_table_free (struct bfd_link_hash_table *hash)
 {
   struct generic_link_hash_table *ret
     = (struct generic_link_hash_table *) hash;
@@ -709,10 +735,9 @@ _bfd_generic_link_hash_table_free (hash)
    structure.  */
 
 static bfd_boolean
-generic_link_read_symbols (abfd)
-     bfd *abfd;
+generic_link_read_symbols (bfd *abfd)
 {
-  if (bfd_get_outsymbols (abfd) == (asymbol **) NULL)
+  if (bfd_get_outsymbols (abfd) == NULL)
     {
       long symsize;
       long symcount;
@@ -720,8 +745,7 @@ generic_link_read_symbols (abfd)
       symsize = bfd_get_symtab_upper_bound (abfd);
       if (symsize < 0)
        return FALSE;
-      bfd_get_outsymbols (abfd) =
-       (asymbol **) bfd_alloc (abfd, (bfd_size_type) symsize);
+      bfd_get_outsymbols (abfd) = bfd_alloc (abfd, symsize);
       if (bfd_get_outsymbols (abfd) == NULL && symsize != 0)
        return FALSE;
       symcount = bfd_canonicalize_symtab (abfd, bfd_get_outsymbols (abfd));
@@ -738,9 +762,7 @@ generic_link_read_symbols (abfd)
    constructors by name.  */
 
 bfd_boolean
-_bfd_generic_link_add_symbols (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+_bfd_generic_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
 {
   return generic_link_add_symbols (abfd, info, FALSE);
 }
@@ -753,9 +775,7 @@ _bfd_generic_link_add_symbols (abfd, info)
    for which gcc uses collect2 and do not support stabs.  */
 
 bfd_boolean
-_bfd_generic_link_add_symbols_collect (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+_bfd_generic_link_add_symbols_collect (bfd *abfd, struct bfd_link_info *info)
 {
   return generic_link_add_symbols (abfd, info, TRUE);
 }
@@ -765,9 +785,8 @@ _bfd_generic_link_add_symbols_collect (abfd, info)
    file are absolute.  */
 
 void
-_bfd_generic_link_just_syms (sec, info)
-     asection *sec;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+_bfd_generic_link_just_syms (asection *sec,
+                            struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   sec->output_section = bfd_abs_section_ptr;
   sec->output_offset = sec->vma;
@@ -776,10 +795,9 @@ _bfd_generic_link_just_syms (sec, info)
 /* Add symbols from an object file to the global hash table.  */
 
 static bfd_boolean
-generic_link_add_symbols (abfd, info, collect)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     bfd_boolean collect;
+generic_link_add_symbols (bfd *abfd,
+                         struct bfd_link_info *info,
+                         bfd_boolean collect)
 {
   bfd_boolean ret;
 
@@ -806,13 +824,12 @@ generic_link_add_symbols (abfd, info, collect)
 /* Add symbols from an object file to the global hash table.  */
 
 static bfd_boolean
-generic_link_add_object_symbols (abfd, info, collect)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     bfd_boolean collect;
+generic_link_add_object_symbols (bfd *abfd,
+                                struct bfd_link_info *info,
+                                bfd_boolean collect)
 {
   bfd_size_type symcount;
-  struct symbol_cache_entry **outsyms;
+  struct bfd_symbol **outsyms;
 
   if (! generic_link_read_symbols (abfd))
     return FALSE;
@@ -848,30 +865,20 @@ struct archive_hash_table
   struct bfd_hash_table table;
 };
 
-static struct bfd_hash_entry *archive_hash_newfunc
-  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static bfd_boolean archive_hash_table_init
-  PARAMS ((struct archive_hash_table *,
-          struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
-                                      struct bfd_hash_table *,
-                                      const char *)));
-
 /* Create a new entry for an archive hash table.  */
 
 static struct bfd_hash_entry *
-archive_hash_newfunc (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
+archive_hash_newfunc (struct bfd_hash_entry *entry,
+                     struct bfd_hash_table *table,
+                     const char *string)
 {
   struct archive_hash_entry *ret = (struct archive_hash_entry *) entry;
 
   /* Allocate the structure if it has not already been allocated by a
      subclass.  */
-  if (ret == (struct archive_hash_entry *) NULL)
-    ret = ((struct archive_hash_entry *)
-          bfd_hash_allocate (table, sizeof (struct archive_hash_entry)));
-  if (ret == (struct archive_hash_entry *) NULL)
+  if (ret == NULL)
+    ret = bfd_hash_allocate (table, sizeof (struct archive_hash_entry));
+  if (ret == NULL)
     return NULL;
 
   /* Call the allocation method of the superclass.  */
@@ -881,20 +888,20 @@ archive_hash_newfunc (entry, table, string)
   if (ret)
     {
       /* Initialize the local fields.  */
-      ret->defs = (struct archive_list *) NULL;
+      ret->defs = NULL;
     }
 
-  return (struct bfd_hash_entry *) ret;
+  return &ret->root;
 }
 
 /* Initialize an archive hash table.  */
 
 static bfd_boolean
-archive_hash_table_init (table, newfunc)
-     struct archive_hash_table *table;
-     struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
-                                               struct bfd_hash_table *,
-                                               const char *));
+archive_hash_table_init
+  (struct archive_hash_table *table,
+   struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
+                                     struct bfd_hash_table *,
+                                     const char *))
 {
   return bfd_hash_table_init (&table->table, newfunc);
 }
@@ -947,11 +954,10 @@ archive_hash_table_init (table, newfunc)
    object file to be included.  */
 
 bfd_boolean
-_bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     bfd_boolean (*checkfn)
-       PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean *pneeded));
+_bfd_generic_link_add_archive_symbols
+  (bfd *abfd,
+   struct bfd_link_info *info,
+   bfd_boolean (*checkfn) (bfd *, struct bfd_link_info *, bfd_boolean *))
 {
   carsym *arsyms;
   carsym *arsym_end;
@@ -964,7 +970,7 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
   if (! bfd_has_map (abfd))
     {
       /* An empty archive is a special case.  */
-      if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL)
+      if (bfd_openr_next_archived_file (abfd, NULL) == NULL)
        return TRUE;
       bfd_set_error (bfd_error_no_armap);
       return FALSE;
@@ -983,16 +989,14 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
       struct archive_list *l, **pp;
 
       arh = archive_hash_lookup (&arsym_hash, arsym->name, TRUE, FALSE);
-      if (arh == (struct archive_hash_entry *) NULL)
+      if (arh == NULL)
        goto error_return;
       l = ((struct archive_list *)
           archive_hash_allocate (&arsym_hash, sizeof (struct archive_list)));
       if (l == NULL)
        goto error_return;
       l->indx = indx;
-      for (pp = &arh->defs;
-          *pp != (struct archive_list *) NULL;
-          pp = &(*pp)->next)
+      for (pp = &arh->defs; *pp != NULL; pp = &(*pp)->next)
        ;
       *pp = l;
       l->next = NULL;
@@ -1006,7 +1010,7 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
   /* New undefined symbols are added to the end of the list, so we
      only need to look through it once.  */
   pundef = &info->hash->undefs;
-  while (*pundef != (struct bfd_link_hash_entry *) NULL)
+  while (*pundef != NULL)
     {
       struct bfd_link_hash_entry *h;
       struct archive_hash_entry *arh;
@@ -1027,22 +1031,22 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
             us to lose track of whether the symbol has been
             referenced).  */
          if (*pundef != info->hash->undefs_tail)
-           *pundef = (*pundef)->next;
+           *pundef = (*pundef)->u.undef.next;
          else
-           pundef = &(*pundef)->next;
+           pundef = &(*pundef)->u.undef.next;
          continue;
        }
 
       /* Look for this symbol in the archive symbol map.  */
       arh = archive_hash_lookup (&arsym_hash, h->root.string, FALSE, FALSE);
-      if (arh == (struct archive_hash_entry *) NULL)
+      if (arh == NULL)
        {
          /* 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);
+             char *buf = bfd_malloc (amt);
              if (buf == NULL)
                return FALSE;
 
@@ -1050,14 +1054,14 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
              arh = archive_hash_lookup (&arsym_hash, buf, FALSE, FALSE);
              free(buf);
            }
-         if (arh == (struct archive_hash_entry *) NULL)
+         if (arh == NULL)
            {
-             pundef = &(*pundef)->next;
+             pundef = &(*pundef)->u.undef.next;
              continue;
            }
        }
       /* Look at all the objects which define this symbol.  */
-      for (l = arh->defs; l != (struct archive_list *) NULL; l = l->next)
+      for (l = arh->defs; l != NULL; l = l->next)
        {
          bfd *element;
          bfd_boolean needed;
@@ -1068,7 +1072,7 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
            break;
 
          element = bfd_get_elt_at_index (abfd, l->indx);
-         if (element == (bfd *) NULL)
+         if (element == NULL)
            goto error_return;
 
          /* If we've already included this element, or if we've
@@ -1101,7 +1105,7 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
            }
        }
 
-      pundef = &(*pundef)->next;
+      pundef = &(*pundef)->u.undef.next;
     }
 
   archive_hash_table_free (&arsym_hash);
@@ -1122,10 +1126,10 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
    for finding them.  */
 
 static bfd_boolean
-generic_link_check_archive_element_no_collect (abfd, info, pneeded)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     bfd_boolean *pneeded;
+generic_link_check_archive_element_no_collect (
+                                              bfd *abfd,
+                                              struct bfd_link_info *info,
+                                              bfd_boolean *pneeded)
 {
   return generic_link_check_archive_element (abfd, info, pneeded, FALSE);
 }
@@ -1135,10 +1139,9 @@ generic_link_check_archive_element_no_collect (abfd, info, pneeded)
    symbol name, as collect2 does.  */
 
 static bfd_boolean
-generic_link_check_archive_element_collect (abfd, info, pneeded)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     bfd_boolean *pneeded;
+generic_link_check_archive_element_collect (bfd *abfd,
+                                           struct bfd_link_info *info,
+                                           bfd_boolean *pneeded)
 {
   return generic_link_check_archive_element (abfd, info, pneeded, TRUE);
 }
@@ -1147,11 +1150,10 @@ generic_link_check_archive_element_collect (abfd, info, pneeded)
    constructors.  */
 
 static bfd_boolean
-generic_link_check_archive_element (abfd, info, pneeded, collect)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     bfd_boolean *pneeded;
-     bfd_boolean collect;
+generic_link_check_archive_element (bfd *abfd,
+                                   struct bfd_link_info *info,
+                                   bfd_boolean *pneeded,
+                                   bfd_boolean collect)
 {
   asymbol **pp, **ppend;
 
@@ -1181,7 +1183,7 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
         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
+      if (h == NULL
          || (h->type != bfd_link_hash_undefined
              && h->type != bfd_link_hash_common))
        continue;
@@ -1215,7 +1217,7 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
          unsigned int power;
 
          symbfd = h->u.undef.abfd;
-         if (symbfd == (bfd *) NULL)
+         if (symbfd == NULL)
            {
              /* This symbol was created as undefined from outside
                 BFD.  We assume that we should link in the object
@@ -1236,9 +1238,8 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
             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)));
+           bfd_hash_allocate (&info->hash->table,
+                              sizeof (struct bfd_link_hash_common_entry));
          if (h->u.c.p == NULL)
            return FALSE;
 
@@ -1279,12 +1280,11 @@ generic_link_check_archive_element (abfd, info, pneeded, collect)
    as is done by collect2.  */
 
 static bfd_boolean
-generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     bfd_size_type symbol_count;
-     asymbol **symbols;
-     bfd_boolean collect;
+generic_link_add_symbol_list (bfd *abfd,
+                             struct bfd_link_info *info,
+                             bfd_size_type symbol_count,
+                             asymbol **symbols,
+                             bfd_boolean collect)
 {
   asymbol **pp, **ppend;
 
@@ -1358,7 +1358,7 @@ generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect)
             generic one.  */
          if (info->hash->creator == abfd->xvec)
            {
-             if (h->sym == (asymbol *) NULL
+             if (h->sym == NULL
                  || (! bfd_is_und_section (bfd_get_section (p))
                      && (! bfd_is_com_section (bfd_get_section (p))
                          || bfd_is_und_section (bfd_get_section (h->sym)))))
@@ -1377,7 +1377,7 @@ generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect)
             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;
+         p->udata.p = h;
        }
     }
 
@@ -1477,8 +1477,7 @@ static const enum link_action link_action[8][8] =
 /* Return the BFD in which a hash entry has been defined, if known.  */
 
 static bfd *
-hash_entry_bfd (h)
-     struct bfd_link_hash_entry *h;
+hash_entry_bfd (struct bfd_link_hash_entry *h)
 {
   while (h->type == bfd_link_hash_warning)
     h = h->u.i.link;
@@ -1517,18 +1516,16 @@ hash_entry_bfd (h)
      the hash table entry, and stored it in *HASHP.  */
 
 bfd_boolean
-_bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
-                                 string, copy, collect, hashp)
-     struct bfd_link_info *info;
-     bfd *abfd;
-     const char *name;
-     flagword flags;
-     asection *section;
-     bfd_vma value;
-     const char *string;
-     bfd_boolean copy;
-     bfd_boolean collect;
-     struct bfd_link_hash_entry **hashp;
+_bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
+                                 bfd *abfd,
+                                 const char *name,
+                                 flagword flags,
+                                 asection *section,
+                                 bfd_vma value,
+                                 const char *string,
+                                 bfd_boolean copy,
+                                 bfd_boolean collect,
+                                 struct bfd_link_hash_entry **hashp)
 {
   enum link_row row;
   struct bfd_link_hash_entry *h;
@@ -1572,16 +1569,15 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
     }
 
   if (info->notice_all
-      || (info->notice_hash != (struct bfd_hash_table *) NULL
-         && (bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE)
-             != (struct bfd_hash_entry *) NULL)))
+      || (info->notice_hash != NULL
+         && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
     {
       if (! (*info->callbacks->notice) (info, h->root.string, abfd, section,
                                        value))
        return FALSE;
     }
 
-  if (hashp != (struct bfd_link_hash_entry **) NULL)
+  if (hashp != NULL)
     *hashp = h;
 
   do
@@ -1610,6 +1606,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
          /* Make a new weak undefined symbol.  */
          h->type = bfd_link_hash_undefweak;
          h->u.undef.abfd = abfd;
+         h->u.undef.weak = abfd;
          break;
 
        case CDEF:
@@ -1619,7 +1616,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
          if (! ((*info->callbacks->multiple_common)
                 (info, h->root.string,
                  h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
-                 abfd, bfd_link_hash_defined, (bfd_vma) 0)))
+                 abfd, bfd_link_hash_defined, 0)))
            return FALSE;
          /* Fall through.  */
        case DEF:
@@ -1694,9 +1691,8 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
            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)));
+           bfd_hash_allocate (&info->hash->table,
+                              sizeof (struct bfd_link_hash_common_entry));
          if (h->u.c.p == NULL)
            return FALSE;
 
@@ -1740,8 +1736,8 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
 
        case REF:
          /* A reference to a defined symbol.  */
-         if (h->next == NULL && info->hash->undefs_tail != h)
-           h->next = h;
+         if (h->u.undef.next == NULL && info->hash->undefs_tail != h)
+           h->u.undef.next = h;
          break;
 
        case BIG:
@@ -1802,7 +1798,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
            else
              obfd = NULL;
            if (! ((*info->callbacks->multiple_common)
-                  (info, h->root.string, obfd, h->type, (bfd_vma) 0,
+                  (info, h->root.string, obfd, h->type, 0,
                    abfd, bfd_link_hash_common, value)))
              return FALSE;
          }
@@ -1856,7 +1852,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
          if (! ((*info->callbacks->multiple_common)
                 (info, h->root.string,
                  h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
-                 abfd, bfd_link_hash_indirect, (bfd_vma) 0)))
+                 abfd, bfd_link_hash_indirect, 0)))
            return FALSE;
          /* Fall through.  */
        case IND:
@@ -1868,14 +1864,14 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
               to.  */
            inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE,
                                                copy, FALSE);
-           if (inh == (struct bfd_link_hash_entry *) NULL)
+           if (inh == 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);
+                 (_("%B: indirect symbol `%s' to `%s' is a loop"),
+                  abfd, name, string);
                bfd_set_error (bfd_error_invalid_operation);
                return FALSE;
              }
@@ -1913,8 +1909,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
            {
              if (! (*info->callbacks->warning) (info, h->u.i.warning,
                                                 h->root.string, abfd,
-                                                (asection *) NULL,
-                                                (bfd_vma) 0))
+                                                NULL, 0))
                return FALSE;
              /* Only issue a warning once.  */
              h->u.i.warning = NULL;
@@ -1928,8 +1923,8 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
 
        case REFC:
          /* A reference to an indirect symbol.  */
-         if (h->next == NULL && info->hash->undefs_tail != h)
-           h->next = h;
+         if (h->u.undef.next == NULL && info->hash->undefs_tail != h)
+           h->u.undef.next = h;
          h = h->u.i.link;
          cycle = TRUE;
          break;
@@ -1937,23 +1932,20 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
        case WARN:
          /* Issue a warning.  */
          if (! (*info->callbacks->warning) (info, string, h->root.string,
-                                            hash_entry_bfd (h),
-                                            (asection *) NULL, (bfd_vma) 0))
+                                            hash_entry_bfd (h), NULL, 0))
            return FALSE;
          break;
 
        case CWARN:
          /* Warn if this symbol has been referenced already,
             otherwise add a warning.  A symbol has been referenced if
-            the next field is not NULL, or it is the tail of the
+            the u.undef.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 (h->u.undef.next != NULL || info->hash->undefs_tail == h)
            {
              if (! (*info->callbacks->warning) (info, string, h->root.string,
-                                                hash_entry_bfd (h),
-                                                (asection *) NULL,
-                                                (bfd_vma) 0))
+                                                hash_entry_bfd (h), NULL, 0))
                return FALSE;
              break;
            }
@@ -1966,8 +1958,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
            /* STRING is the warning to give.  */
            sub = ((struct bfd_link_hash_entry *)
                   ((*info->hash->table.newfunc)
-                   ((struct bfd_hash_entry *) NULL, &info->hash->table,
-                    h->root.string)));
+                   (NULL, &info->hash->table, h->root.string)));
            if (sub == NULL)
              return FALSE;
            *sub = *h;
@@ -2004,9 +1995,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
 /* Generic final link routine.  */
 
 bfd_boolean
-_bfd_generic_final_link (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+_bfd_generic_final_link (bfd *abfd, struct bfd_link_info *info)
 {
   bfd *sub;
   asection *o;
@@ -2014,7 +2003,7 @@ _bfd_generic_final_link (abfd, info)
   size_t outsymalloc;
   struct generic_write_global_symbol_info wginfo;
 
-  bfd_get_outsymbols (abfd) = (asymbol **) NULL;
+  bfd_get_outsymbols (abfd) = NULL;
   bfd_get_symcount (abfd) = 0;
   outsymalloc = 0;
 
@@ -2025,7 +2014,7 @@ _bfd_generic_final_link (abfd, info)
        p->u.indirect.section->linker_mark = TRUE;
 
   /* Build the output symbol table.  */
-  for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next)
+  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
     if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc))
       return FALSE;
 
@@ -2035,7 +2024,7 @@ _bfd_generic_final_link (abfd, info)
   wginfo.psymalloc = &outsymalloc;
   _bfd_generic_link_hash_traverse (_bfd_generic_hash_table (info),
                                   _bfd_generic_link_write_global_symbol,
-                                  (PTR) &wginfo);
+                                  &wginfo);
 
   /* Make sure we have a trailing NULL pointer on OUTSYMBOLS.  We
      shouldn't really need one, since we have SYMCOUNT, but some old
@@ -2043,17 +2032,13 @@ _bfd_generic_final_link (abfd, info)
   if (! generic_add_output_symbol (abfd, &outsymalloc, NULL))
     return FALSE;
 
-  if (info->relocateable)
+  if (info->relocatable)
     {
       /* Allocate space for the output relocs for each section.  */
-      for (o = abfd->sections;
-          o != (asection *) NULL;
-          o = o->next)
+      for (o = abfd->sections; o != NULL; o = o->next)
        {
          o->reloc_count = 0;
-         for (p = o->link_order_head;
-              p != (struct bfd_link_order *) NULL;
-              p = p->next)
+         for (p = o->link_order_head; p != NULL; p = p->next)
            {
              if (p->type == bfd_section_reloc_link_order
                  || p->type == bfd_symbol_reloc_link_order)
@@ -2073,7 +2058,7 @@ _bfd_generic_final_link (abfd, info)
                                                       input_section);
                  if (relsize < 0)
                    return FALSE;
-                 relocs = (arelent **) bfd_malloc ((bfd_size_type) relsize);
+                 relocs = bfd_malloc (relsize);
                  if (!relocs && relsize != 0)
                    return FALSE;
                  symbols = _bfd_generic_link_get_symbols (input_bfd);
@@ -2095,7 +2080,7 @@ _bfd_generic_final_link (abfd, info)
 
              amt = o->reloc_count;
              amt *= sizeof (arelent *);
-             o->orelocation = (arelent **) bfd_alloc (abfd, amt);
+             o->orelocation = bfd_alloc (abfd, amt);
              if (!o->orelocation)
                return FALSE;
              o->flags |= SEC_RELOC;
@@ -2107,13 +2092,9 @@ _bfd_generic_final_link (abfd, info)
     }
 
   /* Handle all the link order information for the sections.  */
-  for (o = abfd->sections;
-       o != (asection *) NULL;
-       o = o->next)
+  for (o = abfd->sections; o != NULL; o = o->next)
     {
-      for (p = o->link_order_head;
-          p != (struct bfd_link_order *) NULL;
-          p = p->next)
+      for (p = o->link_order_head; p != NULL; p = p->next)
        {
          switch (p->type)
            {
@@ -2140,10 +2121,7 @@ _bfd_generic_final_link (abfd, info)
 /* Add an output symbol to the output BFD.  */
 
 static bfd_boolean
-generic_add_output_symbol (output_bfd, psymalloc, sym)
-     bfd *output_bfd;
-     size_t *psymalloc;
-     asymbol *sym;
+generic_add_output_symbol (bfd *output_bfd, size_t *psymalloc, asymbol *sym)
 {
   if (bfd_get_symcount (output_bfd) >= *psymalloc)
     {
@@ -2156,8 +2134,8 @@ generic_add_output_symbol (output_bfd, psymalloc, sym)
        *psymalloc *= 2;
       amt = *psymalloc;
       amt *= sizeof (asymbol *);
-      newsyms = (asymbol **) bfd_realloc (bfd_get_outsymbols (output_bfd), amt);
-      if (newsyms == (asymbol **) NULL)
+      newsyms = bfd_realloc (bfd_get_outsymbols (output_bfd), amt);
+      if (newsyms == NULL)
        return FALSE;
       bfd_get_outsymbols (output_bfd) = newsyms;
     }
@@ -2172,11 +2150,10 @@ generic_add_output_symbol (output_bfd, psymalloc, sym)
 /* Handle the symbols for an input BFD.  */
 
 bfd_boolean
-_bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
-     bfd *output_bfd;
-     bfd *input_bfd;
-     struct bfd_link_info *info;
-     size_t *psymalloc;
+_bfd_generic_link_output_symbols (bfd *output_bfd,
+                                 bfd *input_bfd,
+                                 struct bfd_link_info *info,
+                                 size_t *psymalloc)
 {
   asymbol **sym_ptr;
   asymbol **sym_end;
@@ -2185,13 +2162,11 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
     return FALSE;
 
   /* Create a filename symbol if we are supposed to.  */
-  if (info->create_object_symbols_section != (asection *) NULL)
+  if (info->create_object_symbols_section != NULL)
     {
       asection *sec;
 
-      for (sec = input_bfd->sections;
-          sec != (asection *) NULL;
-          sec = sec->next)
+      for (sec = input_bfd->sections; sec != NULL; sec = sec->next)
        {
          if (sec->output_section == info->create_object_symbols_section)
            {
@@ -2224,7 +2199,7 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
       struct generic_link_hash_entry *h;
       bfd_boolean output;
 
-      h = (struct generic_link_hash_entry *) NULL;
+      h = NULL;
       sym = *sym_ptr;
       if ((sym->flags & (BSF_INDIRECT
                         | BSF_WARNING
@@ -2236,7 +2211,7 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
          || bfd_is_ind_section (bfd_get_section (sym)))
        {
          if (sym->udata.p != NULL)
-           h = (struct generic_link_hash_entry *) sym->udata.p;
+           h = sym->udata.p;
          else if ((sym->flags & BSF_CONSTRUCTOR) != 0)
            {
              /* This case normally means that the main linker code
@@ -2259,7 +2234,7 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
                                               bfd_asymbol_name (sym),
                                               FALSE, FALSE, TRUE);
 
-         if (h != (struct generic_link_hash_entry *) NULL)
+         if (h != NULL)
            {
              /* Force all references to this symbol to point to
                 the same area in memory.  It is possible that
@@ -2268,7 +2243,7 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
                 check that.  */
              if (info->hash->creator == input_bfd->xvec)
                {
-                 if (h->sym != (asymbol *) NULL)
+                 if (h->sym != NULL)
                    *sym_ptr = sym = h->sym;
                }
 
@@ -2320,9 +2295,8 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
         write_file_locals in ldsym.c.  */
       if (info->strip == strip_all
          || (info->strip == strip_some
-             && (bfd_hash_lookup (info->keep_hash, bfd_asymbol_name (sym),
-                                  FALSE, FALSE)
-                 == (struct bfd_hash_entry *) NULL)))
+             && bfd_hash_lookup (info->keep_hash, bfd_asymbol_name (sym),
+                                 FALSE, FALSE) == NULL))
        output = FALSE;
       else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
        {
@@ -2362,7 +2336,7 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
                  break;
                case discard_sec_merge:
                  output = TRUE;
-                 if (info->relocateable
+                 if (info->relocatable
                      || ! (sym->section->flags & SEC_MERGE))
                    break;
                  /* FALLTHROUGH */
@@ -2389,19 +2363,21 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
        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.
-
-        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)
+        in the output file, then we don't want to output the
+        symbol.  .bss and similar sections won't have the linker_mark
+        field set.  We also check if its output section has been
+        removed from the output file.  */
+      if (((sym->section->flags & SEC_HAS_CONTENTS) != 0
+          && ! sym->section->linker_mark)
+         || bfd_section_removed_from_list (output_bfd,
+                                           sym->section->output_section))
        output = FALSE;
 
       if (output)
        {
          if (! generic_add_output_symbol (output_bfd, psymalloc, sym))
            return FALSE;
-         if (h != (struct generic_link_hash_entry *) NULL)
+         if (h != NULL)
            h->written = TRUE;
        }
     }
@@ -2413,9 +2389,7 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
    hash table entry.  */
 
 static void
-set_symbol_from_hash (sym, h)
-     asymbol *sym;
-     struct bfd_link_hash_entry *h;
+set_symbol_from_hash (asymbol *sym, struct bfd_link_hash_entry *h)
 {
   switch (h->type)
     {
@@ -2476,12 +2450,10 @@ set_symbol_from_hash (sym, h)
    This is called for each symbol in the hash table.  */
 
 bfd_boolean
-_bfd_generic_link_write_global_symbol (h, data)
-     struct generic_link_hash_entry *h;
-     PTR data;
+_bfd_generic_link_write_global_symbol (struct generic_link_hash_entry *h,
+                                      void *data)
 {
-  struct generic_write_global_symbol_info *wginfo =
-    (struct generic_write_global_symbol_info *) data;
+  struct generic_write_global_symbol_info *wginfo = data;
   asymbol *sym;
 
   if (h->root.type == bfd_link_hash_warning)
@@ -2498,7 +2470,7 @@ _bfd_generic_link_write_global_symbol (h, data)
                              FALSE, FALSE) == NULL))
     return TRUE;
 
-  if (h->sym != (asymbol *) NULL)
+  if (h->sym != NULL)
     sym = h->sym;
   else
     {
@@ -2526,21 +2498,20 @@ _bfd_generic_link_write_global_symbol (h, data)
 /* Create a relocation.  */
 
 bfd_boolean
-_bfd_generic_reloc_link_order (abfd, info, sec, link_order)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     struct bfd_link_order *link_order;
+_bfd_generic_reloc_link_order (bfd *abfd,
+                              struct bfd_link_info *info,
+                              asection *sec,
+                              struct bfd_link_order *link_order)
 {
   arelent *r;
 
-  if (! info->relocateable)
+  if (! info->relocatable)
     abort ();
-  if (sec->orelocation == (arelent **) NULL)
+  if (sec->orelocation == NULL)
     abort ();
 
-  r = (arelent *) bfd_alloc (abfd, (bfd_size_type) sizeof (arelent));
-  if (r == (arelent *) NULL)
+  r = bfd_alloc (abfd, sizeof (arelent));
+  if (r == NULL)
     return FALSE;
 
   r->address = link_order->offset;
@@ -2562,12 +2533,11 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
           bfd_wrapped_link_hash_lookup (abfd, info,
                                         link_order->u.reloc.p->u.name,
                                         FALSE, FALSE, TRUE));
-      if (h == (struct generic_link_hash_entry *) NULL
+      if (h == NULL
          || ! h->written)
        {
          if (! ((*info->callbacks->unattached_reloc)
-                (info, link_order->u.reloc.p->u.name,
-                 (bfd *) NULL, (asection *) NULL, (bfd_vma) 0)))
+                (info, link_order->u.reloc.p->u.name, NULL, NULL, 0)))
            return FALSE;
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
@@ -2588,8 +2558,8 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
       file_ptr loc;
 
       size = bfd_get_reloc_size (r->howto);
-      buf = (bfd_byte *) bfd_zmalloc (size);
-      if (buf == (bfd_byte *) NULL)
+      buf = bfd_zmalloc (size);
+      if (buf == NULL)
        return FALSE;
       rstat = _bfd_relocate_contents (r->howto, abfd,
                                      (bfd_vma) link_order->u.reloc.p->addend,
@@ -2603,12 +2573,12 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
          abort ();
        case bfd_reloc_overflow:
          if (! ((*info->callbacks->reloc_overflow)
-                (info,
+                (info, NULL,
                  (link_order->type == bfd_section_reloc_link_order
                   ? bfd_section_name (abfd, link_order->u.reloc.p->u.section)
                   : link_order->u.reloc.p->u.name),
                  r->howto->name, link_order->u.reloc.p->addend,
-                 (bfd *) NULL, (asection *) NULL, (bfd_vma) 0)))
+                 NULL, NULL, 0)))
            {
              free (buf);
              return FALSE;
@@ -2616,8 +2586,7 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
          break;
        }
       loc = link_order->offset * bfd_octets_per_byte (abfd);
-      ok = bfd_set_section_contents (abfd, sec, (PTR) buf, loc,
-                                    (bfd_size_type) size);
+      ok = bfd_set_section_contents (abfd, sec, buf, loc, size);
       free (buf);
       if (! ok)
        return FALSE;
@@ -2634,20 +2603,18 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order)
 /* Allocate a new link_order for a section.  */
 
 struct bfd_link_order *
-bfd_new_link_order (abfd, section)
-     bfd *abfd;
-     asection *section;
+bfd_new_link_order (bfd *abfd, asection *section)
 {
   bfd_size_type amt = sizeof (struct bfd_link_order);
   struct bfd_link_order *new;
 
-  new = (struct bfd_link_order *) bfd_zalloc (abfd, amt);
+  new = bfd_zalloc (abfd, amt);
   if (!new)
     return NULL;
 
   new->type = bfd_undefined_link_order;
 
-  if (section->link_order_tail != (struct bfd_link_order *) NULL)
+  if (section->link_order_tail != NULL)
     section->link_order_tail->next = new;
   else
     section->link_order_head = new;
@@ -2661,11 +2628,10 @@ bfd_new_link_order (abfd, section)
    of how the particular backends generates relocs.  */
 
 bfd_boolean
-_bfd_default_link_order (abfd, info, sec, link_order)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     struct bfd_link_order *link_order;
+_bfd_default_link_order (bfd *abfd,
+                        struct bfd_link_info *info,
+                        asection *sec,
+                        struct bfd_link_order *link_order)
 {
   switch (link_order->type)
     {
@@ -2685,11 +2651,10 @@ _bfd_default_link_order (abfd, info, sec, link_order)
 /* Default routine to handle a bfd_data_link_order.  */
 
 static bfd_boolean
-default_data_link_order (abfd, info, sec, link_order)
-     bfd *abfd;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     asection *sec;
-     struct bfd_link_order *link_order;
+default_data_link_order (bfd *abfd,
+                        struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                        asection *sec,
+                        struct bfd_link_order *link_order)
 {
   bfd_size_type size;
   size_t fill_size;
@@ -2708,7 +2673,7 @@ default_data_link_order (abfd, info, sec, link_order)
   if (fill_size != 0 && fill_size < size)
     {
       bfd_byte *p;
-      fill = (bfd_byte *) bfd_malloc (size);
+      fill = bfd_malloc (size);
       if (fill == NULL)
        return FALSE;
       p = fill;
@@ -2740,13 +2705,11 @@ default_data_link_order (abfd, info, sec, link_order)
 /* Default routine to handle a bfd_indirect_link_order.  */
 
 static bfd_boolean
-default_indirect_link_order (output_bfd, info, output_section, link_order,
-                            generic_linker)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     asection *output_section;
-     struct bfd_link_order *link_order;
-     bfd_boolean generic_linker;
+default_indirect_link_order (bfd *output_bfd,
+                            struct bfd_link_info *info,
+                            asection *output_section,
+                            struct bfd_link_order *link_order,
+                            bfd_boolean generic_linker)
 {
   asection *input_section;
   bfd *input_bfd;
@@ -2765,11 +2728,11 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
 
   BFD_ASSERT (input_section->output_section == output_section);
   BFD_ASSERT (input_section->output_offset == link_order->offset);
-  BFD_ASSERT (input_section->_cooked_size == link_order->size);
+  BFD_ASSERT (input_section->size == link_order->size);
 
-  if (info->relocateable
+  if (info->relocatable
       && input_section->reloc_count > 0
-      && output_section->orelocation == (arelent **) NULL)
+      && output_section->orelocation == NULL)
     {
       /* Space has not been allocated for the output relocations.
         This can happen when we are called by a specific backend
@@ -2777,7 +2740,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)
-       (_("Attempt to do relocateable link with %s input and %s output"),
+       (_("Attempt to do relocatable 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;
@@ -2821,7 +2784,7 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
              /* sym->udata may have been set by
                 generic_link_add_symbol_list.  */
              if (sym->udata.p != NULL)
-               h = (struct bfd_link_hash_entry *) sym->udata.p;
+               h = sym->udata.p;
              else if (bfd_is_und_section (bfd_get_section (sym)))
                h = bfd_wrapped_link_hash_lookup (output_bfd, info,
                                                  bfd_asymbol_name (sym),
@@ -2837,12 +2800,14 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
     }
 
   /* Get and relocate the section contents.  */
-  sec_size = bfd_section_size (input_bfd, input_section);
-  contents = ((bfd_byte *) bfd_malloc (sec_size));
+  sec_size = (input_section->rawsize > input_section->size
+             ? input_section->rawsize
+             : input_section->size);
+  contents = 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,
+                 (output_bfd, info, link_order, contents, info->relocatable,
                   _bfd_generic_link_get_symbols (input_bfd)));
   if (!new_contents)
     goto error_return;
@@ -2850,7 +2815,7 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
   /* Output the section contents.  */
   loc = link_order->offset * bfd_octets_per_byte (output_bfd);
   if (! bfd_set_section_contents (output_bfd, output_section,
-                                 (PTR) new_contents, loc, link_order->size))
+                                 new_contents, loc, link_order->size))
     goto error_return;
 
   if (contents != NULL)
@@ -2867,14 +2832,13 @@ default_indirect_link_order (output_bfd, info, output_section, link_order,
    list.  */
 
 unsigned int
-_bfd_count_link_order_relocs (link_order)
-     struct bfd_link_order *link_order;
+_bfd_count_link_order_relocs (struct bfd_link_order *link_order)
 {
   register unsigned int c;
   register struct bfd_link_order *l;
 
   c = 0;
-  for (l = link_order; l != (struct bfd_link_order *) NULL; l = l->next)
+  for (l = link_order; l != NULL; l = l->next)
     {
       if (l->type == bfd_section_reloc_link_order
          || l->type == bfd_symbol_reloc_link_order)
@@ -2889,7 +2853,7 @@ FUNCTION
        bfd_link_split_section
 
 SYNOPSIS
-        bfd_boolean bfd_link_split_section(bfd *abfd, asection *sec);
+        bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec);
 
 DESCRIPTION
        Return nonzero if @var{sec} should be split during a
@@ -2902,9 +2866,208 @@ DESCRIPTION
 */
 
 bfd_boolean
-_bfd_generic_link_split_section (abfd, sec)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     asection *sec ATTRIBUTE_UNUSED;
+_bfd_generic_link_split_section (bfd *abfd ATTRIBUTE_UNUSED,
+                                asection *sec ATTRIBUTE_UNUSED)
 {
   return FALSE;
 }
+
+/*
+FUNCTION
+       bfd_section_already_linked
+
+SYNOPSIS
+        void bfd_section_already_linked (bfd *abfd, asection *sec);
+
+DESCRIPTION
+       Check if @var{sec} has been already linked during a reloceatable
+       or final link.
+
+.#define bfd_section_already_linked(abfd, sec) \
+.       BFD_SEND (abfd, _section_already_linked, (abfd, sec))
+.
+
+*/
+
+/* Sections marked with the SEC_LINK_ONCE flag should only be linked
+   once into the output.  This routine checks each section, and
+   arrange to discard it if a section of the same name has already
+   been linked.  This code assumes that all relevant sections have the 
+   SEC_LINK_ONCE flag set; that is, it does not depend solely upon the
+   section name.  bfd_section_already_linked is called via
+   bfd_map_over_sections.  */
+
+/* The hash table.  */
+
+static struct bfd_hash_table _bfd_section_already_linked_table;
+
+/* Support routines for the hash table used by section_already_linked,
+   initialize the table, traverse, lookup, fill in an entry and remove
+   the table.  */
+
+void
+bfd_section_already_linked_table_traverse
+  (bfd_boolean (*func) (struct bfd_section_already_linked_hash_entry *,
+                       void *), void *info)
+{
+  bfd_hash_traverse (&_bfd_section_already_linked_table,
+                    (bfd_boolean (*) (struct bfd_hash_entry *,
+                                      void *)) func,
+                    info);
+}
+
+struct bfd_section_already_linked_hash_entry *
+bfd_section_already_linked_table_lookup (const char *name)
+{
+  return ((struct bfd_section_already_linked_hash_entry *)
+         bfd_hash_lookup (&_bfd_section_already_linked_table, name,
+                          TRUE, FALSE));
+}
+
+void
+bfd_section_already_linked_table_insert
+  (struct bfd_section_already_linked_hash_entry *already_linked_list,
+   asection *sec)
+{
+  struct bfd_section_already_linked *l;
+
+  /* Allocate the memory from the same obstack as the hash table is
+     kept in.  */
+  l = bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
+  l->sec = sec;
+  l->next = already_linked_list->entry;
+  already_linked_list->entry = l;
+}
+
+static struct bfd_hash_entry *
+already_linked_newfunc (struct bfd_hash_entry *entry ATTRIBUTE_UNUSED,
+                       struct bfd_hash_table *table,
+                       const char *string ATTRIBUTE_UNUSED)
+{
+  struct bfd_section_already_linked_hash_entry *ret =
+    bfd_hash_allocate (table, sizeof *ret);
+
+  ret->entry = NULL;
+
+  return &ret->root;
+}
+
+bfd_boolean
+bfd_section_already_linked_table_init (void)
+{
+  return bfd_hash_table_init_n (&_bfd_section_already_linked_table,
+                               already_linked_newfunc, 42);
+}
+
+void
+bfd_section_already_linked_table_free (void)
+{
+  bfd_hash_table_free (&_bfd_section_already_linked_table);
+}
+
+/* This is used on non-ELF inputs.  */
+
+void
+_bfd_generic_section_already_linked (bfd *abfd, asection *sec)
+{
+  flagword flags;
+  const char *name;
+  struct bfd_section_already_linked *l;
+  struct bfd_section_already_linked_hash_entry *already_linked_list;
+
+  flags = sec->flags;
+  if ((flags & SEC_LINK_ONCE) == 0)
+    return;
+
+  /* FIXME: When doing a relocatable link, we may have trouble
+     copying relocations in other sections that refer to local symbols
+     in the section being discarded.  Those relocations will have to
+     be converted somehow; as of this writing I'm not sure that any of
+     the backends handle that correctly.
+
+     It is tempting to instead not discard link once sections when
+     doing a relocatable link (technically, they should be discarded
+     whenever we are building constructors).  However, that fails,
+     because the linker winds up combining all the link once sections
+     into a single large link once section, which defeats the purpose
+     of having link once sections in the first place.  */
+
+  name = bfd_get_section_name (abfd, sec);
+
+  already_linked_list = bfd_section_already_linked_table_lookup (name);
+
+  for (l = already_linked_list->entry; l != NULL; l = l->next)
+    {
+      bfd_boolean skip = FALSE;
+      struct coff_comdat_info *s_comdat
+       = bfd_coff_get_comdat_section (abfd, sec);
+      struct coff_comdat_info *l_comdat
+       = bfd_coff_get_comdat_section (l->sec->owner, l->sec);
+
+      /* We may have 3 different sections on the list: group section,
+        comdat section and linkonce section. SEC may be a linkonce or
+        comdat section. We always ignore group section. For non-COFF
+        inputs, we also ignore comdat section.
+
+        FIXME: Is that safe to match a linkonce section with a comdat
+        section for COFF inputs?  */
+      if ((l->sec->flags & SEC_GROUP) != 0)
+       skip = TRUE;
+      else if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
+       {
+         if (s_comdat != NULL
+             && l_comdat != NULL
+             && strcmp (s_comdat->name, l_comdat->name) != 0)
+           skip = TRUE;
+       }
+      else if (l_comdat != NULL)
+       skip = TRUE;
+
+      if (!skip)
+       {
+         /* The section has already been linked.  See if we should
+             issue a warning.  */
+         switch (flags & SEC_LINK_DUPLICATES)
+           {
+           default:
+             abort ();
+
+           case SEC_LINK_DUPLICATES_DISCARD:
+             break;
+
+           case SEC_LINK_DUPLICATES_ONE_ONLY:
+             (*_bfd_error_handler)
+               (_("%B: warning: ignoring duplicate section `%A'\n"),
+                abfd, sec);
+             break;
+
+           case SEC_LINK_DUPLICATES_SAME_CONTENTS:
+             /* FIXME: We should really dig out the contents of both
+                 sections and memcmp them.  The COFF/PE spec says that
+                 the Microsoft linker does not implement this
+                 correctly, so I'm not going to bother doing it
+                 either.  */
+             /* Fall through.  */
+           case SEC_LINK_DUPLICATES_SAME_SIZE:
+             if (sec->size != l->sec->size)
+               (*_bfd_error_handler)
+                 (_("%B: warning: duplicate section `%A' has different size\n"),
+                  abfd, sec);
+             break;
+           }
+
+         /* Set the output_section field so that lang_add_section
+            does not create a lang_input_section structure for this
+            section.  Since there might be a symbol in the section
+            being discarded, we must retain a pointer to the section
+            which we are really going to use.  */
+         sec->output_section = bfd_abs_section_ptr;
+         sec->kept_section = l->sec;
+
+         return;
+       }
+    }
+
+  /* This is the first section with this name.  Record it.  */
+  bfd_section_already_linked_table_insert (already_linked_list, sec);
+}
This page took 0.04647 seconds and 4 git commands to generate.