Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / cofflink.c
index 1af86abaec9d43548ee4a0a0e1ea8164214eec00..b2b64db95002451e9582ba09174fbfd36412f4d2 100644 (file)
@@ -1,13 +1,12 @@
 /* COFF specific linker code.
 /* COFF specific linker code.
-   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004 Free Software Foundation, Inc.
+   Copyright (C) 1994-2020 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 /* This file contains the COFF backend linker code.  */
 
 
 /* This file contains the COFF backend linker code.  */
 
-#include "bfd.h"
 #include "sysdep.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "coff/internal.h"
 #include "libcoff.h"
 #include "safe-ctype.h"
 
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "coff/internal.h"
 #include "libcoff.h"
 #include "safe-ctype.h"
 
-static bfd_boolean coff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info);
-static bfd_boolean coff_link_check_archive_element (bfd *abfd, struct bfd_link_info *info, bfd_boolean *pneeded);
-static bfd_boolean coff_link_add_symbols (bfd *abfd, struct bfd_link_info *info);
+static bfd_boolean coff_link_add_object_symbols (bfd *, struct bfd_link_info *);
+static bfd_boolean coff_link_check_archive_element
+  (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, const char *,
+   bfd_boolean *);
+static bfd_boolean coff_link_add_symbols (bfd *, struct bfd_link_info *);
 
 /* Return TRUE if SYM is a weak, external symbol.  */
 #define IS_WEAK_EXTERNAL(abfd, sym)                    \
 
 /* Return TRUE if SYM is a weak, external symbol.  */
 #define IS_WEAK_EXTERNAL(abfd, sym)                    \
@@ -78,7 +80,7 @@ _bfd_coff_link_hash_newfunc (struct bfd_hash_entry *entry,
       /* Set local fields.  */
       ret->indx = -1;
       ret->type = T_NULL;
       /* Set local fields.  */
       ret->indx = -1;
       ret->type = T_NULL;
-      ret->class = C_NULL;
+      ret->symbol_class = C_NULL;
       ret->numaux = 0;
       ret->auxbfd = NULL;
       ret->aux = NULL;
       ret->numaux = 0;
       ret->auxbfd = NULL;
       ret->aux = NULL;
@@ -94,10 +96,11 @@ _bfd_coff_link_hash_table_init (struct coff_link_hash_table *table,
                                bfd *abfd,
                                struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
                                                                   struct bfd_hash_table *,
                                bfd *abfd,
                                struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
                                                                   struct bfd_hash_table *,
-                                                                  const char *))
+                                                                  const char *),
+                               unsigned int entsize)
 {
   memset (&table->stab_info, 0, sizeof (table->stab_info));
 {
   memset (&table->stab_info, 0, sizeof (table->stab_info));
-  return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
+  return _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
 }
 
 /* Create a COFF linker hash table.  */
 }
 
 /* Create a COFF linker hash table.  */
@@ -108,12 +111,13 @@ _bfd_coff_link_hash_table_create (bfd *abfd)
   struct coff_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct coff_link_hash_table);
 
   struct coff_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct coff_link_hash_table);
 
-  ret = bfd_malloc (amt);
+  ret = (struct coff_link_hash_table *) bfd_malloc (amt);
   if (ret == NULL)
     return NULL;
 
   if (! _bfd_coff_link_hash_table_init (ret, abfd,
   if (ret == NULL)
     return NULL;
 
   if (! _bfd_coff_link_hash_table_init (ret, abfd,
-                                       _bfd_coff_link_hash_newfunc))
+                                       _bfd_coff_link_hash_newfunc,
+                                       sizeof (struct coff_link_hash_entry)))
     {
       free (ret);
       return (struct bfd_link_hash_table *) NULL;
     {
       free (ret);
       return (struct bfd_link_hash_table *) NULL;
@@ -188,72 +192,6 @@ coff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   return TRUE;
 }
 
   return TRUE;
 }
 
-/* Look through the symbols to see if this object file should be
-   included in the link.  */
-
-static bfd_boolean
-coff_link_check_ar_symbols (bfd *abfd,
-                           struct bfd_link_info *info,
-                           bfd_boolean *pneeded)
-{
-  bfd_size_type symesz;
-  bfd_byte *esym;
-  bfd_byte *esym_end;
-
-  *pneeded = FALSE;
-
-  symesz = bfd_coff_symesz (abfd);
-  esym = (bfd_byte *) obj_coff_external_syms (abfd);
-  esym_end = esym + obj_raw_syment_count (abfd) * symesz;
-  while (esym < esym_end)
-    {
-      struct internal_syment sym;
-      enum coff_symbol_classification classification;
-
-      bfd_coff_swap_sym_in (abfd, esym, &sym);
-
-      classification = bfd_coff_classify_symbol (abfd, &sym);
-      if (classification == COFF_SYMBOL_GLOBAL
-         || classification == COFF_SYMBOL_COMMON)
-       {
-         const char *name;
-         char buf[SYMNMLEN + 1];
-         struct bfd_link_hash_entry *h;
-
-         /* This symbol is externally visible, and is defined by this
-             object file.  */
-         name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
-         if (name == NULL)
-           return FALSE;
-         h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
-
-         /* Auto import.  */
-         if (!h
-             && info->pei386_auto_import
-             && !strncmp (name,"__imp_", 6))
-           h = bfd_link_hash_lookup (info->hash, name + 6, FALSE, FALSE, TRUE);
-
-         /* We are only interested in symbols that are currently
-            undefined.  If a symbol is currently known to be common,
-            COFF linkers do not bring in an object file which defines
-            it.  */
-         if (h != (struct bfd_link_hash_entry *) NULL
-             && h->type == bfd_link_hash_undefined)
-           {
-             if (! (*info->callbacks->add_archive_element) (info, abfd, name))
-               return FALSE;
-             *pneeded = TRUE;
-             return TRUE;
-           }
-       }
-
-      esym += (sym.n_numaux + 1) * symesz;
-    }
-
-  /* We do not need this object file.  */
-  return TRUE;
-}
-
 /* Check a single archive element to see if we need to include it in
    the link.  *PNEEDED is set according to whether this element is
    needed in the link or not.  This is called via
 /* Check a single archive element to see if we need to include it in
    the link.  *PNEEDED is set according to whether this element is
    needed in the link or not.  This is called via
@@ -262,23 +200,28 @@ coff_link_check_ar_symbols (bfd *abfd,
 static bfd_boolean
 coff_link_check_archive_element (bfd *abfd,
                                 struct bfd_link_info *info,
 static bfd_boolean
 coff_link_check_archive_element (bfd *abfd,
                                 struct bfd_link_info *info,
+                                struct bfd_link_hash_entry *h,
+                                const char *name,
                                 bfd_boolean *pneeded)
 {
                                 bfd_boolean *pneeded)
 {
-  if (! _bfd_coff_get_external_symbols (abfd))
-    return FALSE;
+  *pneeded = FALSE;
 
 
-  if (! coff_link_check_ar_symbols (abfd, info, pneeded))
-    return FALSE;
+  /* We are only interested in symbols that are currently undefined.
+     If a symbol is currently known to be common, COFF linkers do not
+     bring in an object file which defines it.  */
+  if (h->type != bfd_link_hash_undefined)
+    return TRUE;
 
 
-  if (*pneeded
-      && ! coff_link_add_symbols (abfd, info))
-    return FALSE;
+  /* PR 22369 - Skip non COFF objects in the archive.  */
+  if (! bfd_family_coff (abfd))
+    return TRUE;
 
 
-  if ((! info->keep_memory || ! *pneeded)
-      && ! _bfd_coff_free_symbols (abfd))
-    return FALSE;
+  /* Include this element?  */
+  if (!(*info->callbacks->add_archive_element) (info, abfd, name, &abfd))
+    return TRUE;
+  *pneeded = TRUE;
 
 
-  return TRUE;
+  return bfd_link_add_symbols (abfd, info);
 }
 
 /* Add all the symbols from an object file to the hash table.  */
 }
 
 /* Add all the symbols from an object file to the hash table.  */
@@ -299,6 +242,11 @@ coff_link_add_symbols (bfd *abfd,
   bfd_byte *esym_end;
   bfd_size_type amt;
 
   bfd_byte *esym_end;
   bfd_size_type amt;
 
+  symcount = obj_raw_syment_count (abfd);
+
+  if (symcount == 0)
+    return TRUE;               /* Nothing to do.  */
+
   /* Keep the symbols during this function, in case the linker needs
      to read the generic symbols in order to report an error message.  */
   keep_syms = obj_coff_keep_syms (abfd);
   /* Keep the symbols during this function, in case the linker needs
      to read the generic symbols in order to report an error message.  */
   keep_syms = obj_coff_keep_syms (abfd);
@@ -309,13 +257,11 @@ coff_link_add_symbols (bfd *abfd,
   else
     default_copy = TRUE;
 
   else
     default_copy = TRUE;
 
-  symcount = obj_raw_syment_count (abfd);
-
   /* We keep a list of the linker hash table entries that correspond
      to particular symbols.  */
   amt = symcount * sizeof (struct coff_link_hash_entry *);
   /* We keep a list of the linker hash table entries that correspond
      to particular symbols.  */
   amt = symcount * sizeof (struct coff_link_hash_entry *);
-  sym_hash = bfd_zalloc (abfd, amt);
-  if (sym_hash == NULL && symcount != 0)
+  sym_hash = (struct coff_link_hash_entry **) bfd_zalloc (abfd, amt);
+  if (sym_hash == NULL)
     goto error_return;
   obj_coff_sym_hashes (abfd) = sym_hash;
 
     goto error_return;
   obj_coff_sym_hashes (abfd) = sym_hash;
 
@@ -348,7 +294,7 @@ coff_link_add_symbols (bfd *abfd,
            goto error_return;
 
          /* We must copy the name into memory if we got it from the
            goto error_return;
 
          /* We must copy the name into memory if we got it from the
-             syment itself, rather than the string table.  */
+            syment itself, rather than the string table.  */
          copy = default_copy;
          if (sym._n._n_n._n_zeroes != 0
              || sym._n._n_n._n_offset == 0)
          copy = default_copy;
          if (sym._n._n_n._n_zeroes != 0
              || sym._n._n_n._n_offset == 0)
@@ -364,7 +310,9 @@ coff_link_add_symbols (bfd *abfd,
            case COFF_SYMBOL_GLOBAL:
              flags = BSF_EXPORT | BSF_GLOBAL;
              section = coff_section_from_bfd_index (abfd, sym.n_scnum);
            case COFF_SYMBOL_GLOBAL:
              flags = BSF_EXPORT | BSF_GLOBAL;
              section = coff_section_from_bfd_index (abfd, sym.n_scnum);
-             if (! obj_pe (abfd))
+             if (discarded_section (section))
+               section = bfd_und_section_ptr;
+             else if (! obj_pe (abfd))
                value -= section->vma;
              break;
 
                value -= section->vma;
              break;
 
@@ -381,6 +329,8 @@ coff_link_add_symbols (bfd *abfd,
            case COFF_SYMBOL_PE_SECTION:
              flags = BSF_SECTION_SYM | BSF_GLOBAL;
              section = coff_section_from_bfd_index (abfd, sym.n_scnum);
            case COFF_SYMBOL_PE_SECTION:
              flags = BSF_SECTION_SYM | BSF_GLOBAL;
              section = coff_section_from_bfd_index (abfd, sym.n_scnum);
+             if (discarded_section (section))
+               section = bfd_und_section_ptr;
              break;
            }
 
              break;
            }
 
@@ -390,8 +340,8 @@ coff_link_add_symbols (bfd *abfd,
          addit = TRUE;
 
          /* In the PE format, section symbols actually refer to the
          addit = TRUE;
 
          /* In the PE format, section symbols actually refer to the
-             start of the output section.  We handle them specially
-             here.  */
+            start of the output section.  We handle them specially
+            here.  */
          if (obj_pe (abfd) && (flags & BSF_SECTION_SYM) != 0)
            {
              *sym_hash = coff_link_hash_lookup (coff_hash_table (info),
          if (obj_pe (abfd) && (flags & BSF_SECTION_SYM) != 0)
            {
              *sym_hash = coff_link_hash_lookup (coff_hash_table (info),
@@ -402,8 +352,8 @@ coff_link_add_symbols (bfd *abfd,
                       & COFF_LINK_HASH_PE_SECTION_SYMBOL) == 0
                      && (*sym_hash)->root.type != bfd_link_hash_undefined
                      && (*sym_hash)->root.type != bfd_link_hash_undefweak)
                       & COFF_LINK_HASH_PE_SECTION_SYMBOL) == 0
                      && (*sym_hash)->root.type != bfd_link_hash_undefined
                      && (*sym_hash)->root.type != bfd_link_hash_undefweak)
-                   (*_bfd_error_handler)
-                     ("Warning: symbol `%s' is both section and non-section",
+                   _bfd_error_handler
+                     (_("warning: symbol `%s' is both section and non-section"),
                       name);
 
                  addit = FALSE;
                       name);
 
                  addit = FALSE;
@@ -435,18 +385,19 @@ coff_link_add_symbols (bfd *abfd,
          if (obj_pe (abfd)
              && (classification == COFF_SYMBOL_GLOBAL
                  || classification == COFF_SYMBOL_PE_SECTION)
          if (obj_pe (abfd)
              && (classification == COFF_SYMBOL_GLOBAL
                  || classification == COFF_SYMBOL_PE_SECTION)
-             && section->comdat != NULL
-             && strncmp (name, "??_", 3) == 0
-             && strcmp (name, section->comdat->name) == 0)
+             && coff_section_data (abfd, section) != NULL
+             && coff_section_data (abfd, section)->comdat != NULL
+             && CONST_STRNEQ (name, "??_")
+             && strcmp (name, coff_section_data (abfd, section)->comdat->name) == 0)
            {
              if (*sym_hash == NULL)
                *sym_hash = coff_link_hash_lookup (coff_hash_table (info),
                                                   name, FALSE, copy, FALSE);
              if (*sym_hash != NULL
                  && (*sym_hash)->root.type == bfd_link_hash_defined
            {
              if (*sym_hash == NULL)
                *sym_hash = coff_link_hash_lookup (coff_hash_table (info),
                                                   name, FALSE, copy, FALSE);
              if (*sym_hash != NULL
                  && (*sym_hash)->root.type == bfd_link_hash_defined
-                 && (*sym_hash)->root.u.def.section->comdat != NULL
-                 && strcmp ((*sym_hash)->root.u.def.section->comdat->name,
-                            section->comdat->name) == 0)
+                 && coff_section_data (abfd, (*sym_hash)->root.u.def.section)->comdat != NULL
+                 && strcmp (coff_section_data (abfd, (*sym_hash)->root.u.def.section)->comdat->name,
+                            coff_section_data (abfd, section)->comdat->name) == 0)
                addit = FALSE;
            }
 
                addit = FALSE;
            }
 
@@ -464,10 +415,10 @@ coff_link_add_symbols (bfd *abfd,
              COFF_LINK_HASH_PE_SECTION_SYMBOL;
 
          /* Limit the alignment of a common symbol to the possible
              COFF_LINK_HASH_PE_SECTION_SYMBOL;
 
          /* Limit the alignment of a common symbol to the possible
-             alignment of a section.  There is no point to permitting
-             a higher alignment for a common symbol: we can not
-             guarantee it, and it may cause us to allocate extra space
-             in the common section.  */
+            alignment of a section.  There is no point to permitting
+            a higher alignment for a common symbol: we can not
+            guarantee it, and it may cause us to allocate extra space
+            in the common section.  */
          if (section == bfd_com_section_ptr
              && (*sym_hash)->root.type == bfd_link_hash_common
              && ((*sym_hash)->root.u.c.p->alignment_power
          if (section == bfd_com_section_ptr
              && (*sym_hash)->root.type == bfd_link_hash_common
              && ((*sym_hash)->root.u.c.p->alignment_power
@@ -475,46 +426,47 @@ coff_link_add_symbols (bfd *abfd,
            (*sym_hash)->root.u.c.p->alignment_power
              = bfd_coff_default_section_alignment_power (abfd);
 
            (*sym_hash)->root.u.c.p->alignment_power
              = bfd_coff_default_section_alignment_power (abfd);
 
-         if (info->hash->creator->flavour == bfd_get_flavour (abfd))
+         if (bfd_get_flavour (info->output_bfd) == bfd_get_flavour (abfd))
            {
              /* If we don't have any symbol information currently in
            {
              /* If we don't have any symbol information currently in
-                 the hash table, or if we are looking at a symbol
-                 definition, then update the symbol class and type in
-                 the hash table.  */
-             if (((*sym_hash)->class == C_NULL
-                  && (*sym_hash)->type == T_NULL)
-                 || sym.n_scnum != 0
-                 || (sym.n_value != 0
-                     && (*sym_hash)->root.type != bfd_link_hash_defined
-                     && (*sym_hash)->root.type != bfd_link_hash_defweak))
-               {
-                 (*sym_hash)->class = sym.n_sclass;
-                 if (sym.n_type != T_NULL)
-                   {
-                     /* We want to warn if the type changed, but not
-                        if it changed from an unspecified type.
-                        Testing the whole type byte may work, but the
-                        change from (e.g.) a function of unspecified
-                        type to function of known type also wants to
-                        skip the warning.  */
-                     if ((*sym_hash)->type != T_NULL
-                         && (*sym_hash)->type != sym.n_type
-                         && !(DTYPE ((*sym_hash)->type) == DTYPE (sym.n_type)
-                              && (BTYPE ((*sym_hash)->type) == T_NULL
-                                  || BTYPE (sym.n_type) == T_NULL)))
-                       (*_bfd_error_handler)
-                         (_("Warning: type of symbol `%s' changed from %d to %d in %s"),
-                          name, (*sym_hash)->type, sym.n_type,
-                          bfd_archive_filename (abfd));
-
-                     /* We don't want to change from a meaningful
-                        base type to a null one, but if we know
-                        nothing, take what little we might now know.  */
-                     if (BTYPE (sym.n_type) != T_NULL
-                         || (*sym_hash)->type == T_NULL)
+                the hash table, or if we are looking at a symbol
+                definition, then update the symbol class and type in
+                the hash table.  */
+             if (((*sym_hash)->symbol_class == C_NULL
+                  && (*sym_hash)->type == T_NULL)
+                 || sym.n_scnum != 0
+                 || (sym.n_value != 0
+                     && (*sym_hash)->root.type != bfd_link_hash_defined
+                     && (*sym_hash)->root.type != bfd_link_hash_defweak))
+               {
+                 (*sym_hash)->symbol_class = sym.n_sclass;
+                 if (sym.n_type != T_NULL)
+                   {
+                     /* We want to warn if the type changed, but not
+                        if it changed from an unspecified type.
+                        Testing the whole type byte may work, but the
+                        change from (e.g.) a function of unspecified
+                        type to function of known type also wants to
+                        skip the warning.  */
+                     if ((*sym_hash)->type != T_NULL
+                         && (*sym_hash)->type != sym.n_type
+                         && !(DTYPE ((*sym_hash)->type) == DTYPE (sym.n_type)
+                              && (BTYPE ((*sym_hash)->type) == T_NULL
+                                  || BTYPE (sym.n_type) == T_NULL)))
+                       _bfd_error_handler
+                         /* xgettext: c-format */
+                         (_("warning: type of symbol `%s' changed"
+                            " from %d to %d in %pB"),
+                          name, (*sym_hash)->type, sym.n_type, abfd);
+
+                     /* We don't want to change from a meaningful
+                        base type to a null one, but if we know
+                        nothing, take what little we might now know.  */
+                     if (BTYPE (sym.n_type) != T_NULL
+                         || (*sym_hash)->type == T_NULL)
                        (*sym_hash)->type = sym.n_type;
                        (*sym_hash)->type = sym.n_type;
-                   }
-                 (*sym_hash)->auxbfd = abfd;
+                   }
+                 (*sym_hash)->auxbfd = abfd;
                  if (sym.n_numaux != 0)
                    {
                      union internal_auxent *alloc;
                  if (sym.n_numaux != 0)
                    {
                      union internal_auxent *alloc;
@@ -544,8 +496,8 @@ coff_link_add_symbols (bfd *abfd,
              && (*sym_hash)->numaux != 0)
            {
              /* Some PE sections (such as .bss) have a zero size in
              && (*sym_hash)->numaux != 0)
            {
              /* Some PE sections (such as .bss) have a zero size in
-                 the section header, but a non-zero size in the AUX
-                 record.  Correct that here.
+                the section header, but a non-zero size in the AUX
+                record.  Correct that here.
 
                 FIXME: This is not at all the right place to do this.
                 For example, it won't help objdump.  This needs to be
 
                 FIXME: This is not at all the right place to do this.
                 For example, it won't help objdump.  This needs to be
@@ -555,8 +507,8 @@ coff_link_add_symbols (bfd *abfd,
                section->size = (*sym_hash)->aux[0].x_scn.x_scnlen;
 
              /* FIXME: We could test whether the section sizes
                section->size = (*sym_hash)->aux[0].x_scn.x_scnlen;
 
              /* FIXME: We could test whether the section sizes
-                 matches the size in the aux entry, but apparently
-                 that sometimes fails unexpectedly.  */
+                matches the size in the aux entry, but apparently
+                that sometimes fails unexpectedly.  */
            }
        }
 
            }
        }
 
@@ -566,9 +518,9 @@ coff_link_add_symbols (bfd *abfd,
 
   /* If this is a non-traditional, non-relocatable link, try to
      optimize the handling of any .stab/.stabstr sections.  */
 
   /* If this is a non-traditional, non-relocatable link, try to
      optimize the handling of any .stab/.stabstr sections.  */
-  if (! info->relocatable
+  if (! bfd_link_relocatable (info)
       && ! info->traditional_format
       && ! info->traditional_format
-      && info->hash->creator->flavour == bfd_get_flavour (abfd)
+      && bfd_get_flavour (info->output_bfd) == bfd_get_flavour (abfd)
       && (info->strip != strip_all && info->strip != strip_debugger))
     {
       asection *stabstr;
       && (info->strip != strip_all && info->strip != strip_debugger))
     {
       asection *stabstr;
@@ -579,16 +531,16 @@ coff_link_add_symbols (bfd *abfd,
        {
          bfd_size_type string_offset = 0;
          asection *stab;
        {
          bfd_size_type string_offset = 0;
          asection *stab;
-         
+
          for (stab = abfd->sections; stab; stab = stab->next)
          for (stab = abfd->sections; stab; stab = stab->next)
-           if (strncmp (".stab", stab->name, 5) == 0
+           if (CONST_STRNEQ (stab->name, ".stab")
                && (!stab->name[5]
                    || (stab->name[5] == '.' && ISDIGIT (stab->name[6]))))
            {
              struct coff_link_hash_table *table;
              struct coff_section_tdata *secdata
                = coff_section_data (abfd, stab);
                && (!stab->name[5]
                    || (stab->name[5] == '.' && ISDIGIT (stab->name[6]))))
            {
              struct coff_link_hash_table *table;
              struct coff_section_tdata *secdata
                = coff_section_data (abfd, stab);
-             
+
              if (secdata == NULL)
                {
                  amt = sizeof (struct coff_section_tdata);
              if (secdata == NULL)
                {
                  amt = sizeof (struct coff_section_tdata);
@@ -625,7 +577,7 @@ _bfd_coff_final_link (bfd *abfd,
                      struct bfd_link_info *info)
 {
   bfd_size_type symesz;
                      struct bfd_link_info *info)
 {
   bfd_size_type symesz;
-  struct coff_final_link_info finfo;
+  struct coff_final_link_info flaginfo;
   bfd_boolean debug_merge_allocated;
   bfd_boolean long_section_names;
   asection *o;
   bfd_boolean debug_merge_allocated;
   bfd_boolean long_section_names;
   asection *o;
@@ -646,30 +598,30 @@ _bfd_coff_final_link (bfd *abfd,
 
   symesz = bfd_coff_symesz (abfd);
 
 
   symesz = bfd_coff_symesz (abfd);
 
-  finfo.info = info;
-  finfo.output_bfd = abfd;
-  finfo.strtab = NULL;
-  finfo.section_info = NULL;
-  finfo.last_file_index = -1;
-  finfo.last_bf_index = -1;
-  finfo.internal_syms = NULL;
-  finfo.sec_ptrs = NULL;
-  finfo.sym_indices = NULL;
-  finfo.outsyms = NULL;
-  finfo.linenos = NULL;
-  finfo.contents = NULL;
-  finfo.external_relocs = NULL;
-  finfo.internal_relocs = NULL;
-  finfo.global_to_static = FALSE;
+  flaginfo.info = info;
+  flaginfo.output_bfd = abfd;
+  flaginfo.strtab = NULL;
+  flaginfo.section_info = NULL;
+  flaginfo.last_file_index = -1;
+  flaginfo.last_bf_index = -1;
+  flaginfo.internal_syms = NULL;
+  flaginfo.sec_ptrs = NULL;
+  flaginfo.sym_indices = NULL;
+  flaginfo.outsyms = NULL;
+  flaginfo.linenos = NULL;
+  flaginfo.contents = NULL;
+  flaginfo.external_relocs = NULL;
+  flaginfo.internal_relocs = NULL;
+  flaginfo.global_to_static = FALSE;
   debug_merge_allocated = FALSE;
 
   coff_data (abfd)->link_info = info;
 
   debug_merge_allocated = FALSE;
 
   coff_data (abfd)->link_info = info;
 
-  finfo.strtab = _bfd_stringtab_init ();
-  if (finfo.strtab == NULL)
+  flaginfo.strtab = _bfd_stringtab_init ();
+  if (flaginfo.strtab == NULL)
     goto error_return;
 
     goto error_return;
 
-  if (! coff_debug_merge_hash_table_init (&finfo.debug_merge))
+  if (! coff_debug_merge_hash_table_init (&flaginfo.debug_merge))
     goto error_return;
   debug_merge_allocated = TRUE;
 
     goto error_return;
   debug_merge_allocated = TRUE;
 
@@ -693,7 +645,7 @@ _bfd_coff_final_link (bfd *abfd,
     {
       o->reloc_count = 0;
       o->lineno_count = 0;
     {
       o->reloc_count = 0;
       o->lineno_count = 0;
-      for (p = o->link_order_head; p != NULL; p = p->next)
+      for (p = o->map_head.link_order; p != NULL; p = p->next)
        {
          if (p->type == bfd_indirect_link_order)
            {
        {
          if (p->type == bfd_indirect_link_order)
            {
@@ -711,7 +663,7 @@ _bfd_coff_final_link (bfd *abfd,
                  || info->strip == strip_some)
                o->lineno_count += sec->lineno_count;
 
                  || info->strip == strip_some)
                o->lineno_count += sec->lineno_count;
 
-             if (info->relocatable)
+             if (bfd_link_relocatable (info))
                o->reloc_count += sec->reloc_count;
 
              if (sec->rawsize > max_contents_size)
                o->reloc_count += sec->reloc_count;
 
              if (sec->rawsize > max_contents_size)
@@ -723,7 +675,7 @@ _bfd_coff_final_link (bfd *abfd,
              if (sec->reloc_count > max_reloc_count)
                max_reloc_count = sec->reloc_count;
            }
              if (sec->reloc_count > max_reloc_count)
                max_reloc_count = sec->reloc_count;
            }
-         else if (info->relocatable
+         else if (bfd_link_relocatable (info)
                   && (p->type == bfd_section_reloc_link_order
                       || p->type == bfd_symbol_reloc_link_order))
            ++o->reloc_count;
                   && (p->type == bfd_section_reloc_link_order
                       || p->type == bfd_symbol_reloc_link_order))
            ++o->reloc_count;
@@ -745,11 +697,11 @@ _bfd_coff_final_link (bfd *abfd,
          && strlen (o->name) > SCNNMLEN)
        {
          /* This section has a long name which must go in the string
          && strlen (o->name) > SCNNMLEN)
        {
          /* This section has a long name which must go in the string
-             table.  This must correspond to the code in
-             coff_write_object_contents which puts the string index
-             into the s_name field of the section header.  That is why
-             we pass hash as FALSE.  */
-         if (_bfd_stringtab_add (finfo.strtab, o->name, FALSE, FALSE)
+            table.  This must correspond to the code in
+            coff_write_object_contents which puts the string index
+            into the s_name field of the section header.  That is why
+            we pass hash as FALSE.  */
+         if (_bfd_stringtab_add (flaginfo.strtab, o->name, FALSE, FALSE)
              == (bfd_size_type) -1)
            goto error_return;
          long_section_names = TRUE;
              == (bfd_size_type) -1)
            goto error_return;
          long_section_names = TRUE;
@@ -758,21 +710,21 @@ _bfd_coff_final_link (bfd *abfd,
 
   /* If doing a relocatable link, allocate space for the pointers we
      need to keep.  */
 
   /* If doing a relocatable link, allocate space for the pointers we
      need to keep.  */
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     {
       unsigned int i;
 
       /* We use section_count + 1, rather than section_count, because
     {
       unsigned int i;
 
       /* We use section_count + 1, rather than section_count, because
-         the target_index fields are 1 based.  */
+        the target_index fields are 1 based.  */
       amt = abfd->section_count + 1;
       amt *= sizeof (struct coff_link_section_info);
       amt = abfd->section_count + 1;
       amt *= sizeof (struct coff_link_section_info);
-      finfo.section_info = bfd_malloc (amt);
-      if (finfo.section_info == NULL)
+      flaginfo.section_info = (struct coff_link_section_info *) bfd_malloc (amt);
+      if (flaginfo.section_info == NULL)
        goto error_return;
       for (i = 0; i <= abfd->section_count; i++)
        {
        goto error_return;
       for (i = 0; i <= abfd->section_count; i++)
        {
-         finfo.section_info[i].relocs = NULL;
-         finfo.section_info[i].rel_hashes = NULL;
+         flaginfo.section_info[i].relocs = NULL;
+         flaginfo.section_info[i].rel_hashes = NULL;
        }
     }
 
        }
     }
 
@@ -794,27 +746,29 @@ _bfd_coff_final_link (bfd *abfd,
       if (o->reloc_count != 0)
        {
          /* We don't know the indices of global symbols until we have
       if (o->reloc_count != 0)
        {
          /* We don't know the indices of global symbols until we have
-             written out all the local symbols.  For each section in
-             the output file, we keep an array of pointers to hash
-             table entries.  Each entry in the array corresponds to a
-             reloc.  When we find a reloc against a global symbol, we
-             set the corresponding entry in this array so that we can
-             fix up the symbol index after we have written out all the
-             local symbols.
+            written out all the local symbols.  For each section in
+            the output file, we keep an array of pointers to hash
+            table entries.  Each entry in the array corresponds to a
+            reloc.  When we find a reloc against a global symbol, we
+            set the corresponding entry in this array so that we can
+            fix up the symbol index after we have written out all the
+            local symbols.
 
             Because of this problem, we also keep the relocs in
             memory until the end of the link.  This wastes memory,
             but only when doing a relocatable link, which is not the
             common case.  */
 
             Because of this problem, we also keep the relocs in
             memory until the end of the link.  This wastes memory,
             but only when doing a relocatable link, which is not the
             common case.  */
-         BFD_ASSERT (info->relocatable);
+         BFD_ASSERT (bfd_link_relocatable (info));
          amt = o->reloc_count;
          amt *= sizeof (struct internal_reloc);
          amt = o->reloc_count;
          amt *= sizeof (struct internal_reloc);
-         finfo.section_info[o->target_index].relocs = bfd_malloc (amt);
+         flaginfo.section_info[o->target_index].relocs =
+             (struct internal_reloc *) bfd_malloc (amt);
          amt = o->reloc_count;
          amt *= sizeof (struct coff_link_hash_entry *);
          amt = o->reloc_count;
          amt *= sizeof (struct coff_link_hash_entry *);
-         finfo.section_info[o->target_index].rel_hashes = bfd_malloc (amt);
-         if (finfo.section_info[o->target_index].relocs == NULL
-             || finfo.section_info[o->target_index].rel_hashes == NULL)
+         flaginfo.section_info[o->target_index].rel_hashes =
+             (struct coff_link_hash_entry **) bfd_malloc (amt);
+         if (flaginfo.section_info[o->target_index].relocs == NULL
+             || flaginfo.section_info[o->target_index].rel_hashes == NULL)
            goto error_return;
 
          if (o->reloc_count > max_output_reloc_count)
            goto error_return;
 
          if (o->reloc_count > max_output_reloc_count)
@@ -833,43 +787,43 @@ _bfd_coff_final_link (bfd *abfd,
      the opportunity to clear the output_has_begun fields of all the
      input BFD's.  */
   max_sym_count = 0;
      the opportunity to clear the output_has_begun fields of all the
      input BFD's.  */
   max_sym_count = 0;
-  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+  for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
     {
       size_t sz;
 
       sub->output_has_begun = FALSE;
     {
       size_t sz;
 
       sub->output_has_begun = FALSE;
-      sz = obj_raw_syment_count (sub);
+      sz = bfd_family_coff (sub) ? obj_raw_syment_count (sub) : 2;
       if (sz > max_sym_count)
        max_sym_count = sz;
     }
 
   /* Allocate some buffers used while linking.  */
   amt = max_sym_count * sizeof (struct internal_syment);
       if (sz > max_sym_count)
        max_sym_count = sz;
     }
 
   /* Allocate some buffers used while linking.  */
   amt = max_sym_count * sizeof (struct internal_syment);
-  finfo.internal_syms = bfd_malloc (amt);
+  flaginfo.internal_syms = (struct internal_syment *) bfd_malloc (amt);
   amt = max_sym_count * sizeof (asection *);
   amt = max_sym_count * sizeof (asection *);
-  finfo.sec_ptrs = bfd_malloc (amt);
+  flaginfo.sec_ptrs = (asection **) bfd_malloc (amt);
   amt = max_sym_count * sizeof (long);
   amt = max_sym_count * sizeof (long);
-  finfo.sym_indices = bfd_malloc (amt);
-  finfo.outsyms = bfd_malloc ((max_sym_count + 1) * symesz);
+  flaginfo.sym_indices = (long int *) bfd_malloc (amt);
+  flaginfo.outsyms = (bfd_byte *) bfd_malloc ((max_sym_count + 1) * symesz);
   amt = max_lineno_count * bfd_coff_linesz (abfd);
   amt = max_lineno_count * bfd_coff_linesz (abfd);
-  finfo.linenos = bfd_malloc (amt);
-  finfo.contents = bfd_malloc (max_contents_size);
+  flaginfo.linenos = (bfd_byte *) bfd_malloc (amt);
+  flaginfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
   amt = max_reloc_count * relsz;
   amt = max_reloc_count * relsz;
-  finfo.external_relocs = bfd_malloc (amt);
-  if (! info->relocatable)
+  flaginfo.external_relocs = (bfd_byte *) bfd_malloc (amt);
+  if (! bfd_link_relocatable (info))
     {
       amt = max_reloc_count * sizeof (struct internal_reloc);
     {
       amt = max_reloc_count * sizeof (struct internal_reloc);
-      finfo.internal_relocs = bfd_malloc (amt);
+      flaginfo.internal_relocs = (struct internal_reloc *) bfd_malloc (amt);
     }
     }
-  if ((finfo.internal_syms == NULL && max_sym_count > 0)
-      || (finfo.sec_ptrs == NULL && max_sym_count > 0)
-      || (finfo.sym_indices == NULL && max_sym_count > 0)
-      || finfo.outsyms == NULL
-      || (finfo.linenos == NULL && max_lineno_count > 0)
-      || (finfo.contents == NULL && max_contents_size > 0)
-      || (finfo.external_relocs == NULL && max_reloc_count > 0)
-      || (! info->relocatable
-         && finfo.internal_relocs == NULL
+  if ((flaginfo.internal_syms == NULL && max_sym_count > 0)
+      || (flaginfo.sec_ptrs == NULL && max_sym_count > 0)
+      || (flaginfo.sym_indices == NULL && max_sym_count > 0)
+      || flaginfo.outsyms == NULL
+      || (flaginfo.linenos == NULL && max_lineno_count > 0)
+      || (flaginfo.contents == NULL && max_contents_size > 0)
+      || (flaginfo.external_relocs == NULL && max_reloc_count > 0)
+      || (! bfd_link_relocatable (info)
+         && flaginfo.internal_relocs == NULL
          && max_reloc_count > 0))
     goto error_return;
 
          && max_reloc_count > 0))
     goto error_return;
 
@@ -888,15 +842,15 @@ _bfd_coff_final_link (bfd *abfd,
 
   for (o = abfd->sections; o != NULL; o = o->next)
     {
 
   for (o = abfd->sections; o != NULL; o = o->next)
     {
-      for (p = o->link_order_head; p != NULL; p = p->next)
+      for (p = o->map_head.link_order; p != NULL; p = p->next)
        {
          if (p->type == bfd_indirect_link_order
              && bfd_family_coff (p->u.indirect.section->owner))
            {
              sub = p->u.indirect.section->owner;
        {
          if (p->type == bfd_indirect_link_order
              && bfd_family_coff (p->u.indirect.section->owner))
            {
              sub = p->u.indirect.section->owner;
-             if (! bfd_coff_link_output_has_begun (sub, & finfo))
+             if (! bfd_coff_link_output_has_begun (sub, & flaginfo))
                {
                {
-                 if (! _bfd_coff_link_input_bfd (&finfo, sub))
+                 if (! _bfd_coff_link_input_bfd (&flaginfo, sub))
                    goto error_return;
                  sub->output_has_begun = TRUE;
                }
                    goto error_return;
                  sub->output_has_begun = TRUE;
                }
@@ -904,7 +858,7 @@ _bfd_coff_final_link (bfd *abfd,
          else if (p->type == bfd_section_reloc_link_order
                   || p->type == bfd_symbol_reloc_link_order)
            {
          else if (p->type == bfd_section_reloc_link_order
                   || p->type == bfd_symbol_reloc_link_order)
            {
-             if (! _bfd_coff_reloc_link_order (abfd, &finfo, o, p))
+             if (! _bfd_coff_reloc_link_order (abfd, &flaginfo, o, p))
                goto error_return;
            }
          else
                goto error_return;
            }
          else
@@ -915,65 +869,181 @@ _bfd_coff_final_link (bfd *abfd,
        }
     }
 
        }
     }
 
-  if (! bfd_coff_final_link_postscript (abfd, & finfo))
+  if (flaginfo.info->strip != strip_all && flaginfo.info->discard != discard_all)
+    {
+      /* Add local symbols from foreign inputs.  */
+      for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
+       {
+         unsigned int i;
+
+         if (bfd_family_coff (sub) || ! bfd_get_outsymbols (sub))
+           continue;
+         for (i = 0; i < bfd_get_symcount (sub); ++i)
+           {
+             asymbol *sym = bfd_get_outsymbols (sub) [i];
+             file_ptr pos;
+             struct internal_syment isym;
+             union internal_auxent iaux;
+             bfd_size_type string_size = 0, indx;
+             bfd_vma written = 0;
+             bfd_boolean rewrite = FALSE, hash;
+
+             if (! (sym->flags & BSF_LOCAL)
+                 || (sym->flags & (BSF_SECTION_SYM | BSF_DEBUGGING_RELOC
+                                   | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC
+                                   | BSF_SYNTHETIC))
+                 || ((sym->flags & BSF_DEBUGGING)
+                     && ! (sym->flags & BSF_FILE)))
+               continue;
+
+             /* See if we are discarding symbols with this name.  */
+             if ((flaginfo.info->strip == strip_some
+                  && (bfd_hash_lookup (flaginfo.info->keep_hash,
+                                       bfd_asymbol_name(sym), FALSE, FALSE)
+                      == NULL))
+                 || (((flaginfo.info->discard == discard_sec_merge
+                       && (bfd_asymbol_section (sym)->flags & SEC_MERGE)
+                       && ! bfd_link_relocatable (flaginfo.info))
+                      || flaginfo.info->discard == discard_l)
+                     && bfd_is_local_label_name (sub, bfd_asymbol_name(sym))))
+               continue;
+
+             pos = obj_sym_filepos (abfd) + obj_raw_syment_count (abfd)
+                                            * symesz;
+             if (bfd_seek (abfd, pos, SEEK_SET) != 0)
+               goto error_return;
+             if (! coff_write_alien_symbol(abfd, sym, &isym, &iaux, &written,
+                                           &string_size, NULL, NULL))
+               goto error_return;
+
+             hash = !flaginfo.info->traditional_format;
+
+             if (string_size >= 6 && isym.n_sclass == C_FILE
+                 && ! isym._n._n_n._n_zeroes && isym.n_numaux)
+               {
+                 indx = _bfd_stringtab_add (flaginfo.strtab, ".file", hash,
+                                            FALSE);
+                 if (indx == (bfd_size_type) -1)
+                   goto error_return;
+                 isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+                 bfd_coff_swap_sym_out (abfd, &isym, flaginfo.outsyms);
+                 if (bfd_seek (abfd, pos, SEEK_SET) != 0
+                     || bfd_bwrite (flaginfo.outsyms, symesz,
+                                    abfd) != symesz)
+                   goto error_return;
+                 string_size -= 6;
+               }
+
+             if (string_size)
+               {
+                 indx = _bfd_stringtab_add (flaginfo.strtab,
+                                            bfd_asymbol_name (sym), hash,
+                                            FALSE);
+                 if (indx == (bfd_size_type) -1)
+                   goto error_return;
+                 if (isym.n_sclass != C_FILE)
+                   {
+                     isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+                     bfd_coff_swap_sym_out (abfd, &isym, flaginfo.outsyms);
+                     rewrite = TRUE;
+                   }
+                 else
+                   {
+                     BFD_ASSERT (isym.n_numaux == 1);
+                     iaux.x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
+                     bfd_coff_swap_aux_out (abfd, &iaux, isym.n_type, C_FILE,
+                                            0, 1, flaginfo.outsyms + symesz);
+                     if (bfd_seek (abfd, pos + symesz, SEEK_SET) != 0
+                         || bfd_bwrite (flaginfo.outsyms + symesz, symesz,
+                                        abfd) != symesz)
+                       goto error_return;
+                   }
+               }
+
+             if (isym.n_sclass == C_FILE)
+               {
+                 if (flaginfo.last_file_index != -1)
+                   {
+                     flaginfo.last_file.n_value = obj_raw_syment_count (abfd);
+                     bfd_coff_swap_sym_out (abfd, &flaginfo.last_file,
+                                            flaginfo.outsyms);
+                     pos = obj_sym_filepos (abfd) + flaginfo.last_file_index
+                                                    * symesz;
+                     rewrite = TRUE;
+                   }
+                 flaginfo.last_file_index = obj_raw_syment_count (abfd);
+                 flaginfo.last_file = isym;
+               }
+
+             if (rewrite
+                 && (bfd_seek (abfd, pos, SEEK_SET) != 0
+                     || bfd_bwrite (flaginfo.outsyms, symesz, abfd) != symesz))
+               goto error_return;
+
+             obj_raw_syment_count (abfd) += written;
+           }
+       }
+    }
+
+  if (! bfd_coff_final_link_postscript (abfd, & flaginfo))
     goto error_return;
 
   /* Free up the buffers used by _bfd_coff_link_input_bfd.  */
 
     goto error_return;
 
   /* Free up the buffers used by _bfd_coff_link_input_bfd.  */
 
-  coff_debug_merge_hash_table_free (&finfo.debug_merge);
+  coff_debug_merge_hash_table_free (&flaginfo.debug_merge);
   debug_merge_allocated = FALSE;
 
   debug_merge_allocated = FALSE;
 
-  if (finfo.internal_syms != NULL)
+  if (flaginfo.internal_syms != NULL)
     {
     {
-      free (finfo.internal_syms);
-      finfo.internal_syms = NULL;
+      free (flaginfo.internal_syms);
+      flaginfo.internal_syms = NULL;
     }
     }
-  if (finfo.sec_ptrs != NULL)
+  if (flaginfo.sec_ptrs != NULL)
     {
     {
-      free (finfo.sec_ptrs);
-      finfo.sec_ptrs = NULL;
+      free (flaginfo.sec_ptrs);
+      flaginfo.sec_ptrs = NULL;
     }
     }
-  if (finfo.sym_indices != NULL)
+  if (flaginfo.sym_indices != NULL)
     {
     {
-      free (finfo.sym_indices);
-      finfo.sym_indices = NULL;
+      free (flaginfo.sym_indices);
+      flaginfo.sym_indices = NULL;
     }
     }
-  if (finfo.linenos != NULL)
+  if (flaginfo.linenos != NULL)
     {
     {
-      free (finfo.linenos);
-      finfo.linenos = NULL;
+      free (flaginfo.linenos);
+      flaginfo.linenos = NULL;
     }
     }
-  if (finfo.contents != NULL)
+  if (flaginfo.contents != NULL)
     {
     {
-      free (finfo.contents);
-      finfo.contents = NULL;
+      free (flaginfo.contents);
+      flaginfo.contents = NULL;
     }
     }
-  if (finfo.external_relocs != NULL)
+  if (flaginfo.external_relocs != NULL)
     {
     {
-      free (finfo.external_relocs);
-      finfo.external_relocs = NULL;
+      free (flaginfo.external_relocs);
+      flaginfo.external_relocs = NULL;
     }
     }
-  if (finfo.internal_relocs != NULL)
+  if (flaginfo.internal_relocs != NULL)
     {
     {
-      free (finfo.internal_relocs);
-      finfo.internal_relocs = NULL;
+      free (flaginfo.internal_relocs);
+      flaginfo.internal_relocs = NULL;
     }
 
   /* The value of the last C_FILE symbol is supposed to be the symbol
      index of the first external symbol.  Write it out again if
      necessary.  */
     }
 
   /* The value of the last C_FILE symbol is supposed to be the symbol
      index of the first external symbol.  Write it out again if
      necessary.  */
-  if (finfo.last_file_index != -1
-      && (unsigned int) finfo.last_file.n_value != obj_raw_syment_count (abfd))
+  if (flaginfo.last_file_index != -1
+      && (unsigned int) flaginfo.last_file.n_value != obj_raw_syment_count (abfd))
     {
       file_ptr pos;
 
     {
       file_ptr pos;
 
-      finfo.last_file.n_value = obj_raw_syment_count (abfd);
-      bfd_coff_swap_sym_out (abfd, &finfo.last_file,
-                            finfo.outsyms);
+      flaginfo.last_file.n_value = obj_raw_syment_count (abfd);
+      bfd_coff_swap_sym_out (abfd, &flaginfo.last_file,
+                            flaginfo.outsyms);
 
 
-      pos = obj_sym_filepos (abfd) + finfo.last_file_index * symesz;
+      pos = obj_sym_filepos (abfd) + flaginfo.last_file_index * symesz;
       if (bfd_seek (abfd, pos, SEEK_SET) != 0
       if (bfd_seek (abfd, pos, SEEK_SET) != 0
-         || bfd_bwrite (finfo.outsyms, symesz, abfd) != symesz)
+         || bfd_bwrite (flaginfo.outsyms, symesz, abfd) != symesz)
        return FALSE;
     }
 
        return FALSE;
     }
 
@@ -982,34 +1052,33 @@ _bfd_coff_final_link (bfd *abfd,
      static.  */
   if (info->task_link)
     {
      static.  */
   if (info->task_link)
     {
-      finfo.failed = FALSE;
+      flaginfo.failed = FALSE;
       coff_link_hash_traverse (coff_hash_table (info),
       coff_link_hash_traverse (coff_hash_table (info),
-                              _bfd_coff_write_task_globals, &finfo);
-      if (finfo.failed)
+                              _bfd_coff_write_task_globals, &flaginfo);
+      if (flaginfo.failed)
        goto error_return;
     }
 
   /* Write out the global symbols.  */
        goto error_return;
     }
 
   /* Write out the global symbols.  */
-  finfo.failed = FALSE;
-  coff_link_hash_traverse (coff_hash_table (info),
-                          _bfd_coff_write_global_sym, &finfo);
-  if (finfo.failed)
+  flaginfo.failed = FALSE;
+  bfd_hash_traverse (&info->hash->table, _bfd_coff_write_global_sym, &flaginfo);
+  if (flaginfo.failed)
     goto error_return;
 
   /* The outsyms buffer is used by _bfd_coff_write_global_sym.  */
     goto error_return;
 
   /* The outsyms buffer is used by _bfd_coff_write_global_sym.  */
-  if (finfo.outsyms != NULL)
+  if (flaginfo.outsyms != NULL)
     {
     {
-      free (finfo.outsyms);
-      finfo.outsyms = NULL;
+      free (flaginfo.outsyms);
+      flaginfo.outsyms = NULL;
     }
 
     }
 
-  if (info->relocatable && max_output_reloc_count > 0)
+  if (bfd_link_relocatable (info) && max_output_reloc_count > 0)
     {
       /* Now that we have written out all the global symbols, we know
         the symbol indices to use for relocs against them, and we can
         finally write out the relocs.  */
       amt = max_output_reloc_count * relsz;
     {
       /* Now that we have written out all the global symbols, we know
         the symbol indices to use for relocs against them, and we can
         finally write out the relocs.  */
       amt = max_output_reloc_count * relsz;
-      external_relocs = bfd_malloc (amt);
+      external_relocs = (bfd_byte *) bfd_malloc (amt);
       if (external_relocs == NULL)
        goto error_return;
 
       if (external_relocs == NULL)
        goto error_return;
 
@@ -1023,9 +1092,9 @@ _bfd_coff_final_link (bfd *abfd,
          if (o->reloc_count == 0)
            continue;
 
          if (o->reloc_count == 0)
            continue;
 
-         irel = finfo.section_info[o->target_index].relocs;
+         irel = flaginfo.section_info[o->target_index].relocs;
          irelend = irel + o->reloc_count;
          irelend = irel + o->reloc_count;
-         rel_hash = finfo.section_info[o->target_index].rel_hashes;
+         rel_hash = flaginfo.section_info[o->target_index].rel_hashes;
          erel = external_relocs;
          for (; irel < irelend; irel++, rel_hash++, erel += relsz)
            {
          erel = external_relocs;
          for (; irel < irelend; irel++, rel_hash++, erel += relsz)
            {
@@ -1046,10 +1115,10 @@ _bfd_coff_final_link (bfd *abfd,
                 elsewhere. */
              struct internal_reloc incount;
              bfd_byte *excount = (bfd_byte *)bfd_malloc (relsz);
                 elsewhere. */
              struct internal_reloc incount;
              bfd_byte *excount = (bfd_byte *)bfd_malloc (relsz);
-             
+
              memset (&incount, 0, sizeof (incount));
              incount.r_vaddr = o->reloc_count + 1;
              memset (&incount, 0, sizeof (incount));
              incount.r_vaddr = o->reloc_count + 1;
-             bfd_coff_swap_reloc_out (abfd, (PTR) &incount, (PTR) excount);
+             bfd_coff_swap_reloc_out (abfd, &incount, excount);
              if (bfd_bwrite (excount, relsz, abfd) != relsz)
                /* We'll leak, but it's an error anyway. */
                goto error_return;
              if (bfd_bwrite (excount, relsz, abfd) != relsz)
                /* We'll leak, but it's an error anyway. */
                goto error_return;
@@ -1066,19 +1135,19 @@ _bfd_coff_final_link (bfd *abfd,
     }
 
   /* Free up the section information.  */
     }
 
   /* Free up the section information.  */
-  if (finfo.section_info != NULL)
+  if (flaginfo.section_info != NULL)
     {
       unsigned int i;
 
       for (i = 0; i < abfd->section_count; i++)
        {
     {
       unsigned int i;
 
       for (i = 0; i < abfd->section_count; i++)
        {
-         if (finfo.section_info[i].relocs != NULL)
-           free (finfo.section_info[i].relocs);
-         if (finfo.section_info[i].rel_hashes != NULL)
-           free (finfo.section_info[i].rel_hashes);
+         if (flaginfo.section_info[i].relocs != NULL)
+           free (flaginfo.section_info[i].relocs);
+         if (flaginfo.section_info[i].rel_hashes != NULL)
+           free (flaginfo.section_info[i].rel_hashes);
        }
        }
-      free (finfo.section_info);
-      finfo.section_info = NULL;
+      free (flaginfo.section_info);
+      flaginfo.section_info = NULL;
     }
 
   /* If we have optimized stabs strings, output them.  */
     }
 
   /* If we have optimized stabs strings, output them.  */
@@ -1099,7 +1168,7 @@ _bfd_coff_final_link (bfd *abfd,
 
 #if STRING_SIZE_SIZE == 4
       H_PUT_32 (abfd,
 
 #if STRING_SIZE_SIZE == 4
       H_PUT_32 (abfd,
-               _bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE,
+               _bfd_stringtab_size (flaginfo.strtab) + STRING_SIZE_SIZE,
                strbuf);
 #else
  #error Change H_PUT_32 above
                strbuf);
 #else
  #error Change H_PUT_32 above
@@ -1109,54 +1178,54 @@ _bfd_coff_final_link (bfd *abfd,
          != STRING_SIZE_SIZE)
        return FALSE;
 
          != STRING_SIZE_SIZE)
        return FALSE;
 
-      if (! _bfd_stringtab_emit (abfd, finfo.strtab))
+      if (! _bfd_stringtab_emit (abfd, flaginfo.strtab))
        return FALSE;
 
       obj_coff_strings_written (abfd) = TRUE;
     }
 
        return FALSE;
 
       obj_coff_strings_written (abfd) = TRUE;
     }
 
-  _bfd_stringtab_free (finfo.strtab);
+  _bfd_stringtab_free (flaginfo.strtab);
 
 
-  /* Setting bfd_get_symcount to 0 will cause write_object_contents to
+  /* Setting symcount to 0 will cause write_object_contents to
      not try to write out the symbols.  */
      not try to write out the symbols.  */
-  bfd_get_symcount (abfd) = 0;
+  abfd->symcount = 0;
 
   return TRUE;
 
  error_return:
   if (debug_merge_allocated)
 
   return TRUE;
 
  error_return:
   if (debug_merge_allocated)
-    coff_debug_merge_hash_table_free (&finfo.debug_merge);
-  if (finfo.strtab != NULL)
-    _bfd_stringtab_free (finfo.strtab);
-  if (finfo.section_info != NULL)
+    coff_debug_merge_hash_table_free (&flaginfo.debug_merge);
+  if (flaginfo.strtab != NULL)
+    _bfd_stringtab_free (flaginfo.strtab);
+  if (flaginfo.section_info != NULL)
     {
       unsigned int i;
 
       for (i = 0; i < abfd->section_count; i++)
        {
     {
       unsigned int i;
 
       for (i = 0; i < abfd->section_count; i++)
        {
-         if (finfo.section_info[i].relocs != NULL)
-           free (finfo.section_info[i].relocs);
-         if (finfo.section_info[i].rel_hashes != NULL)
-           free (finfo.section_info[i].rel_hashes);
+         if (flaginfo.section_info[i].relocs != NULL)
+           free (flaginfo.section_info[i].relocs);
+         if (flaginfo.section_info[i].rel_hashes != NULL)
+           free (flaginfo.section_info[i].rel_hashes);
        }
        }
-      free (finfo.section_info);
+      free (flaginfo.section_info);
     }
     }
-  if (finfo.internal_syms != NULL)
-    free (finfo.internal_syms);
-  if (finfo.sec_ptrs != NULL)
-    free (finfo.sec_ptrs);
-  if (finfo.sym_indices != NULL)
-    free (finfo.sym_indices);
-  if (finfo.outsyms != NULL)
-    free (finfo.outsyms);
-  if (finfo.linenos != NULL)
-    free (finfo.linenos);
-  if (finfo.contents != NULL)
-    free (finfo.contents);
-  if (finfo.external_relocs != NULL)
-    free (finfo.external_relocs);
-  if (finfo.internal_relocs != NULL)
-    free (finfo.internal_relocs);
+  if (flaginfo.internal_syms != NULL)
+    free (flaginfo.internal_syms);
+  if (flaginfo.sec_ptrs != NULL)
+    free (flaginfo.sec_ptrs);
+  if (flaginfo.sym_indices != NULL)
+    free (flaginfo.sym_indices);
+  if (flaginfo.outsyms != NULL)
+    free (flaginfo.outsyms);
+  if (flaginfo.linenos != NULL)
+    free (flaginfo.linenos);
+  if (flaginfo.contents != NULL)
+    free (flaginfo.contents);
+  if (flaginfo.external_relocs != NULL)
+    free (flaginfo.external_relocs);
+  if (flaginfo.internal_relocs != NULL)
+    free (flaginfo.internal_relocs);
   if (external_relocs != NULL)
     free (external_relocs);
   return FALSE;
   if (external_relocs != NULL)
     free (external_relocs);
   return FALSE;
@@ -1221,25 +1290,23 @@ process_embedded_commands (bfd *output_bfd,
        free (copy);
       return 0;
     }
        free (copy);
       return 0;
     }
-  e = copy + sec->size;
+  e = (char *) copy + sec->size;
 
 
-  for (s = copy;  s < e ; )
+  for (s = (char *) copy; s < e ; )
     {
     {
-      if (s[0]!= '-')
+      if (s[0] != '-')
        {
          s++;
          continue;
        }
        {
          s++;
          continue;
        }
-      if (strncmp (s,"-attr", 5) == 0)
+      if (CONST_STRNEQ (s, "-attr"))
        {
          char *name;
          char *attribs;
          asection *asec;
          int loop = 1;
          int had_write = 0;
        {
          char *name;
          char *attribs;
          asection *asec;
          int loop = 1;
          int had_write = 0;
-         int had_read = 0;
          int had_exec= 0;
          int had_exec= 0;
-         int had_shared= 0;
 
          s += 5;
          s = get_name (s, &name);
 
          s += 5;
          s = get_name (s, &name);
@@ -1253,10 +1320,8 @@ process_embedded_commands (bfd *output_bfd,
                  had_write = 1;
                  break;
                case 'R':
                  had_write = 1;
                  break;
                case 'R':
-                 had_read = 1;
                  break;
                case 'S':
                  break;
                case 'S':
-                 had_shared = 1;
                  break;
                case 'X':
                  had_exec = 1;
                  break;
                case 'X':
                  had_exec = 1;
@@ -1274,11 +1339,20 @@ process_embedded_commands (bfd *output_bfd,
                asec->flags |= SEC_READONLY;
            }
        }
                asec->flags |= SEC_READONLY;
            }
        }
-      else if (strncmp (s,"-heap", 5) == 0)
-       s = dores_com (s+5, output_bfd, 1);
+      else if (CONST_STRNEQ (s, "-heap"))
+       s = dores_com (s + 5, output_bfd, 1);
+
+      else if (CONST_STRNEQ (s, "-stack"))
+       s = dores_com (s + 6, output_bfd, 0);
 
 
-      else if (strncmp (s,"-stack", 6) == 0)
-       s = dores_com (s+6, output_bfd, 0);
+      /* GNU extension for aligned commons.  */
+      else if (CONST_STRNEQ (s, "-aligncomm:"))
+       {
+         /* Common symbols must be aligned on reading, as it
+         is too late to do anything here, after they have
+         already been allocated, so just skip the directive.  */
+         s += 11;
+       }
 
       else
        s++;
 
       else
        s++;
@@ -1293,7 +1367,7 @@ process_embedded_commands (bfd *output_bfd,
    that symbol.  */
 
 static void
    that symbol.  */
 
 static void
-mark_relocs (struct coff_final_link_info *finfo, bfd *input_bfd)
+mark_relocs (struct coff_final_link_info *flaginfo, bfd *input_bfd)
 {
   asection * a;
 
 {
   asection * a;
 
@@ -1306,7 +1380,8 @@ mark_relocs (struct coff_final_link_info *finfo, bfd *input_bfd)
       struct internal_reloc *  irel;
       struct internal_reloc *  irelend;
 
       struct internal_reloc *  irel;
       struct internal_reloc *  irelend;
 
-      if ((a->flags & SEC_RELOC) == 0 || a->reloc_count  < 1)
+      if ((a->flags & SEC_RELOC) == 0 || a->reloc_count  < 1
+         || a->linker_mark == 0)
        continue;
       /* Don't mark relocs in excluded sections.  */
       if (a->output_section == bfd_abs_section_ptr)
        continue;
       /* Don't mark relocs in excluded sections.  */
       if (a->output_section == bfd_abs_section_ptr)
@@ -1315,11 +1390,11 @@ mark_relocs (struct coff_final_link_info *finfo, bfd *input_bfd)
       /* Read in the relocs.  */
       internal_relocs = _bfd_coff_read_internal_relocs
        (input_bfd, a, FALSE,
       /* Read in the relocs.  */
       internal_relocs = _bfd_coff_read_internal_relocs
        (input_bfd, a, FALSE,
-        finfo->external_relocs,
-        finfo->info->relocatable,
-        (finfo->info->relocatable
-         ? (finfo->section_info[ a->output_section->target_index ].relocs + a->output_section->reloc_count)
-         : finfo->internal_relocs)
+        flaginfo->external_relocs,
+        bfd_link_relocatable (flaginfo->info),
+        (bfd_link_relocatable (flaginfo->info)
+         ? (flaginfo->section_info[ a->output_section->target_index ].relocs + a->output_section->reloc_count)
+         : flaginfo->internal_relocs)
        );
 
       if (internal_relocs == NULL)
        );
 
       if (internal_relocs == NULL)
@@ -1333,7 +1408,8 @@ mark_relocs (struct coff_final_link_info *finfo, bfd *input_bfd)
         in the relocation table.  This will then be picked up in the
         skip/don't-skip pass.  */
       for (; irel < irelend; irel++)
         in the relocation table.  This will then be picked up in the
         skip/don't-skip pass.  */
       for (; irel < irelend; irel++)
-       finfo->sym_indices[ irel->r_symndx ] = -1;
+       if ((unsigned long) irel->r_symndx < obj_raw_syment_count (input_bfd))
+         flaginfo->sym_indices[irel->r_symndx] = -1;
     }
 }
 
     }
 }
 
@@ -1341,13 +1417,10 @@ mark_relocs (struct coff_final_link_info *finfo, bfd *input_bfd)
    handles all the sections and relocations of the input file at once.  */
 
 bfd_boolean
    handles all the sections and relocations of the input file at once.  */
 
 bfd_boolean
-_bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
+_bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd)
 {
   unsigned int n_tmask = coff_data (input_bfd)->local_n_tmask;
   unsigned int n_btshft = coff_data (input_bfd)->local_n_btshft;
 {
   unsigned int n_tmask = coff_data (input_bfd)->local_n_tmask;
   unsigned int n_btshft = coff_data (input_bfd)->local_n_btshft;
-#if 0
-  unsigned int n_btmask = coff_data (input_bfd)->local_n_btmask;
-#endif
   bfd_boolean (*adjust_symndx)
     (bfd *, struct bfd_link_info *, bfd *, asection *,
      struct internal_reloc *, bfd_boolean *);
   bfd_boolean (*adjust_symndx)
     (bfd *, struct bfd_link_info *, bfd *, asection *,
      struct internal_reloc *, bfd_boolean *);
@@ -1370,7 +1443,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
 
   /* Move all the symbols to the output file.  */
 
 
   /* Move all the symbols to the output file.  */
 
-  output_bfd = finfo->output_bfd;
+  output_bfd = flaginfo->output_bfd;
   strings = NULL;
   syment_base = obj_raw_syment_count (output_bfd);
   isymesz = bfd_coff_symesz (input_bfd);
   strings = NULL;
   syment_base = obj_raw_syment_count (output_bfd);
   isymesz = bfd_coff_symesz (input_bfd);
@@ -1379,10 +1452,10 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
   BFD_ASSERT (linesz == bfd_coff_linesz (output_bfd));
 
   copy = FALSE;
   BFD_ASSERT (linesz == bfd_coff_linesz (output_bfd));
 
   copy = FALSE;
-  if (! finfo->info->keep_memory)
+  if (! flaginfo->info->keep_memory)
     copy = TRUE;
   hash = TRUE;
     copy = TRUE;
   hash = TRUE;
-  if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
+  if (flaginfo->info->traditional_format)
     hash = FALSE;
 
   if (! _bfd_coff_get_external_symbols (input_bfd))
     hash = FALSE;
 
   if (! _bfd_coff_get_external_symbols (input_bfd))
@@ -1390,27 +1463,27 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
 
   esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
   esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
 
   esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
   esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
-  isymp = finfo->internal_syms;
-  secpp = finfo->sec_ptrs;
-  indexp = finfo->sym_indices;
+  isymp = flaginfo->internal_syms;
+  secpp = flaginfo->sec_ptrs;
+  indexp = flaginfo->sym_indices;
   output_index = syment_base;
   output_index = syment_base;
-  outsym = finfo->outsyms;
+  outsym = flaginfo->outsyms;
 
   if (coff_data (output_bfd)->pe
 
   if (coff_data (output_bfd)->pe
-      && ! process_embedded_commands (output_bfd, finfo->info, input_bfd))
+      && ! process_embedded_commands (output_bfd, flaginfo->info, input_bfd))
     return FALSE;
 
   /* If we are going to perform relocations and also strip/discard some
      symbols then we must make sure that we do not strip/discard those
      symbols that are going to be involved in the relocations.  */
     return FALSE;
 
   /* If we are going to perform relocations and also strip/discard some
      symbols then we must make sure that we do not strip/discard those
      symbols that are going to be involved in the relocations.  */
-  if ((   finfo->info->strip   != strip_none
-       || finfo->info->discard != discard_none)
-      && finfo->info->relocatable)
+  if ((   flaginfo->info->strip   != strip_none
+       || flaginfo->info->discard != discard_none)
+      && bfd_link_relocatable (flaginfo->info))
     {
       /* Mark the symbol array as 'not-used'.  */
       memset (indexp, 0, obj_raw_syment_count (input_bfd) * sizeof * indexp);
 
     {
       /* Mark the symbol array as 'not-used'.  */
       memset (indexp, 0, obj_raw_syment_count (input_bfd) * sizeof * indexp);
 
-      mark_relocs (finfo, input_bfd);
+      mark_relocs (flaginfo, input_bfd);
     }
 
   while (esym < esym_end)
     }
 
   while (esym < esym_end)
@@ -1449,10 +1522,10 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
        }
 
       /* Extract the flag indicating if this symbol is used by a
        }
 
       /* Extract the flag indicating if this symbol is used by a
-         relocation.  */
-      if ((finfo->info->strip != strip_none
-          || finfo->info->discard != discard_none)
-         && finfo->info->relocatable)
+        relocation.  */
+      if ((flaginfo->info->strip != strip_none
+          || flaginfo->info->discard != discard_none)
+         && bfd_link_relocatable (flaginfo->info))
        dont_skip_symbol = *indexp;
       else
        dont_skip_symbol = FALSE;
        dont_skip_symbol = *indexp;
       else
        dont_skip_symbol = FALSE;
@@ -1464,7 +1537,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
       add = 1 + isym.n_numaux;
 
       /* If we are stripping all symbols, we want to skip this one.  */
       add = 1 + isym.n_numaux;
 
       /* If we are stripping all symbols, we want to skip this one.  */
-      if (finfo->info->strip == strip_all && ! dont_skip_symbol)
+      if (flaginfo->info->strip == strip_all && ! dont_skip_symbol)
        skip = TRUE;
 
       if (! skip)
        skip = TRUE;
 
       if (! skip)
@@ -1493,8 +1566,8 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
 
            case COFF_SYMBOL_LOCAL:
              /* This is a local symbol.  Skip it if we are discarding
 
            case COFF_SYMBOL_LOCAL:
              /* This is a local symbol.  Skip it if we are discarding
-                 local symbols.  */
-             if (finfo->info->discard == discard_all && ! dont_skip_symbol)
+                local symbols.  */
+             if (flaginfo->info->discard == discard_all && ! dont_skip_symbol)
                skip = TRUE;
              break;
            }
                skip = TRUE;
              break;
            }
@@ -1504,20 +1577,22 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
       /* Skip section symbols for sections which are not going to be
         emitted.  */
       if (!skip
       /* Skip section symbols for sections which are not going to be
         emitted.  */
       if (!skip
-         && dont_skip_symbol == 0
+         && !dont_skip_symbol
          && isym.n_sclass == C_STAT
          && isym.n_type == T_NULL
          && isym.n_sclass == C_STAT
          && isym.n_type == T_NULL
-          && isym.n_numaux > 0
-         && (*secpp)->output_section == bfd_abs_section_ptr)
+         && isym.n_numaux > 0
+         && ((*secpp)->output_section == bfd_abs_section_ptr
+             || bfd_section_removed_from_list (output_bfd,
+                                               (*secpp)->output_section)))
        skip = TRUE;
 #endif
 
       /* If we stripping debugging symbols, and this is a debugging
        skip = TRUE;
 #endif
 
       /* If we stripping debugging symbols, and this is a debugging
-         symbol, then skip it.  FIXME: gas sets the section to N_ABS
-         for some types of debugging symbols; I don't know if this is
-         a bug or not.  In any case, we handle it here.  */
+        symbol, then skip it.  FIXME: gas sets the section to N_ABS
+        for some types of debugging symbols; I don't know if this is
+        a bug or not.  In any case, we handle it here.  */
       if (! skip
       if (! skip
-         && finfo->info->strip == strip_debugger
+         && flaginfo->info->strip == strip_debugger
          && ! dont_skip_symbol
          && (isym.n_scnum == N_DEBUG
              || (isym.n_scnum == N_ABS
          && ! dont_skip_symbol
          && (isym.n_scnum == N_DEBUG
              || (isym.n_scnum == N_ABS
@@ -1535,8 +1610,8 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
       /* If some symbols are stripped based on the name, work out the
         name and decide whether to skip this symbol.  */
       if (! skip
       /* If some symbols are stripped based on the name, work out the
         name and decide whether to skip this symbol.  */
       if (! skip
-         && (finfo->info->strip == strip_some
-             || finfo->info->discard == discard_l))
+         && (flaginfo->info->strip == strip_some
+             || flaginfo->info->discard == discard_l))
        {
          const char *name;
          char buf[SYMNMLEN + 1];
        {
          const char *name;
          char buf[SYMNMLEN + 1];
@@ -1546,19 +1621,19 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
            return FALSE;
 
          if (! dont_skip_symbol
            return FALSE;
 
          if (! dont_skip_symbol
-             && ((finfo->info->strip == strip_some
-                  && (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE,
+             && ((flaginfo->info->strip == strip_some
+                  && (bfd_hash_lookup (flaginfo->info->keep_hash, name, FALSE,
                                    FALSE) == NULL))
                   || (! global
                                    FALSE) == NULL))
                   || (! global
-                      && finfo->info->discard == discard_l
+                      && flaginfo->info->discard == discard_l
                       && bfd_is_local_label_name (input_bfd, name))))
            skip = TRUE;
        }
 
       /* If this is an enum, struct, or union tag, see if we have
                       && bfd_is_local_label_name (input_bfd, name))))
            skip = TRUE;
        }
 
       /* If this is an enum, struct, or union tag, see if we have
-         already output an identical type.  */
+        already output an identical type.  */
       if (! skip
       if (! skip
-         && (finfo->output_bfd->flags & BFD_TRADITIONAL_FORMAT) == 0
+         && !flaginfo->info->traditional_format
          && (isym.n_sclass == C_ENTAG
              || isym.n_sclass == C_STRTAG
              || isym.n_sclass == C_UNTAG)
          && (isym.n_sclass == C_ENTAG
              || isym.n_sclass == C_STRTAG
              || isym.n_sclass == C_UNTAG)
@@ -1579,28 +1654,28 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
            return FALSE;
 
          /* Ignore fake names invented by compiler; treat them all as
            return FALSE;
 
          /* Ignore fake names invented by compiler; treat them all as
-             the same name.  */
+            the same name.  */
          if (*name == '~' || *name == '.' || *name == '$'
              || (*name == bfd_get_symbol_leading_char (input_bfd)
                  && (name[1] == '~' || name[1] == '.' || name[1] == '$')))
            name = "";
 
          if (*name == '~' || *name == '.' || *name == '$'
              || (*name == bfd_get_symbol_leading_char (input_bfd)
                  && (name[1] == '~' || name[1] == '.' || name[1] == '$')))
            name = "";
 
-         mh = coff_debug_merge_hash_lookup (&finfo->debug_merge, name,
+         mh = coff_debug_merge_hash_lookup (&flaginfo->debug_merge, name,
                                             TRUE, TRUE);
          if (mh == NULL)
            return FALSE;
 
          /* Allocate memory to hold type information.  If this turns
                                             TRUE, TRUE);
          if (mh == NULL)
            return FALSE;
 
          /* Allocate memory to hold type information.  If this turns
-             out to be a duplicate, we pass this address to
-             bfd_release.  */
+            out to be a duplicate, we pass this address to
+            bfd_release.  */
          amt = sizeof (struct coff_debug_merge_type);
          amt = sizeof (struct coff_debug_merge_type);
-         mt = bfd_alloc (input_bfd, amt);
+         mt = (struct coff_debug_merge_type *) bfd_alloc (input_bfd, amt);
          if (mt == NULL)
            return FALSE;
          if (mt == NULL)
            return FALSE;
-         mt->class = isym.n_sclass;
+         mt->type_class = isym.n_sclass;
 
          /* Pick up the aux entry, which points to the end of the tag
 
          /* Pick up the aux entry, which points to the end of the tag
-             entries.  */
+            entries.  */
          bfd_coff_swap_aux_in (input_bfd, (esym + isymesz),
                                isym.n_type, isym.n_sclass, 0, isym.n_numaux,
                                &aux);
          bfd_coff_swap_aux_in (input_bfd, (esym + isymesz),
                                isym.n_type, isym.n_sclass, 0, isym.n_numaux,
                                &aux);
@@ -1621,7 +1696,8 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
              bfd_coff_swap_sym_in (input_bfd, esl, islp);
 
              amt = sizeof (struct coff_debug_merge_element);
              bfd_coff_swap_sym_in (input_bfd, esl, islp);
 
              amt = sizeof (struct coff_debug_merge_element);
-             *epp = bfd_alloc (input_bfd, amt);
+             *epp = (struct coff_debug_merge_element *)
+                 bfd_alloc (input_bfd, amt);
              if (*epp == NULL)
                return FALSE;
 
              if (*epp == NULL)
                return FALSE;
 
@@ -1631,7 +1707,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                return FALSE;
 
              amt = strlen (elename) + 1;
                return FALSE;
 
              amt = strlen (elename) + 1;
-             name_copy = bfd_alloc (input_bfd, amt);
+             name_copy = (char *) bfd_alloc (input_bfd, amt);
              if (name_copy == NULL)
                return FALSE;
              strcpy (name_copy, elename);
              if (name_copy == NULL)
                return FALSE;
              strcpy (name_copy, elename);
@@ -1661,7 +1737,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                              (bfd_byte *) obj_coff_external_syms (input_bfd))
                             / (long) isymesz)))
                    {
                              (bfd_byte *) obj_coff_external_syms (input_bfd))
                             / (long) isymesz)))
                    {
-                     (*epp)->tagndx = finfo->sym_indices[indx];
+                     (*epp)->tagndx = flaginfo->sym_indices[indx];
                      if ((*epp)->tagndx < 0)
                        (*epp)->tagndx = 0;
                    }
                      if ((*epp)->tagndx < 0)
                        (*epp)->tagndx = 0;
                    }
@@ -1674,8 +1750,8 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
            }
 
          /* See if we already have a definition which matches this
            }
 
          /* See if we already have a definition which matches this
-             type.  We always output the type if it has no elements,
-             for simplicity.  */
+            type.  We always output the type if it has no elements,
+            for simplicity.  */
          if (mt->elements == NULL)
            bfd_release (input_bfd, mt);
          else
          if (mt->elements == NULL)
            bfd_release (input_bfd, mt);
          else
@@ -1686,7 +1762,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                {
                  struct coff_debug_merge_element *me, *mel;
 
                {
                  struct coff_debug_merge_element *me, *mel;
 
-                 if (mtl->class != mt->class)
+                 if (mtl->type_class != mt->type_class)
                    continue;
 
                  for (me = mt->elements, mel = mtl->elements;
                    continue;
 
                  for (me = mt->elements, mel = mtl->elements;
@@ -1740,7 +1816,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
              name = _bfd_coff_internal_syment_name (input_bfd, &isym, NULL);
              if (name == NULL)
                return FALSE;
              name = _bfd_coff_internal_syment_name (input_bfd, &isym, NULL);
              if (name == NULL)
                return FALSE;
-             indx = _bfd_stringtab_add (finfo->strtab, name, hash, copy);
+             indx = _bfd_stringtab_add (flaginfo->strtab, name, hash, copy);
              if (indx == (bfd_size_type) -1)
                return FALSE;
              isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
              if (indx == (bfd_size_type) -1)
                return FALSE;
              isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
@@ -1767,7 +1843,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
 
            case C_FCN:
              if (obj_pe (input_bfd)
 
            case C_FCN:
              if (obj_pe (input_bfd)
-                 && strcmp (isym.n_name, ".bf") != 0
+                 && memcmp (isym.n_name, ".bf", sizeof ".bf") != 0
                  && isym.n_scnum > 0)
                {
                  /* For PE, .lf and .ef get their value left alone,
                  && isym.n_scnum > 0)
                {
                  /* For PE, .lf and .ef get their value left alone,
@@ -1795,7 +1871,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                isym.n_value += (*secpp)->output_offset;
                if (! obj_pe (input_bfd))
                  isym.n_value -= (*secpp)->vma;
                isym.n_value += (*secpp)->output_offset;
                if (! obj_pe (input_bfd))
                  isym.n_value -= (*secpp)->vma;
-               if (! obj_pe (finfo->output_bfd))
+               if (! obj_pe (flaginfo->output_bfd))
                  isym.n_value += (*secpp)->output_section->vma;
              }
            break;
                  isym.n_value += (*secpp)->output_section->vma;
              }
            break;
@@ -1810,19 +1886,19 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                 it).  We try to get this right, below, just before we
                 write the symbols out, but in the general case we may
                 have to write the symbol out twice.  */
                 it).  We try to get this right, below, just before we
                 write the symbols out, but in the general case we may
                 have to write the symbol out twice.  */
-             if (finfo->last_file_index != -1
-                 && finfo->last_file.n_value != (bfd_vma) output_index)
+             if (flaginfo->last_file_index != -1
+                 && flaginfo->last_file.n_value != (bfd_vma) output_index)
                {
                  /* We must correct the value of the last C_FILE
                {
                  /* We must correct the value of the last C_FILE
-                     entry.  */
-                 finfo->last_file.n_value = output_index;
-                 if ((bfd_size_type) finfo->last_file_index >= syment_base)
+                    entry.  */
+                 flaginfo->last_file.n_value = output_index;
+                 if ((bfd_size_type) flaginfo->last_file_index >= syment_base)
                    {
                      /* The last C_FILE symbol is in this input file.  */
                      bfd_coff_swap_sym_out (output_bfd,
                    {
                      /* The last C_FILE symbol is in this input file.  */
                      bfd_coff_swap_sym_out (output_bfd,
-                                            &finfo->last_file,
-                                            (finfo->outsyms
-                                             + ((finfo->last_file_index
+                                            &flaginfo->last_file,
+                                            (flaginfo->outsyms
+                                             + ((flaginfo->last_file_index
                                                  - syment_base)
                                                 * osymesz)));
                    }
                                                  - syment_base)
                                                 * osymesz)));
                    }
@@ -1834,23 +1910,23 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                         symbol.  We need to write it out again.  We
                         borrow *outsym temporarily.  */
                      bfd_coff_swap_sym_out (output_bfd,
                         symbol.  We need to write it out again.  We
                         borrow *outsym temporarily.  */
                      bfd_coff_swap_sym_out (output_bfd,
-                                            &finfo->last_file, outsym);
+                                            &flaginfo->last_file, outsym);
                      pos = obj_sym_filepos (output_bfd);
                      pos = obj_sym_filepos (output_bfd);
-                     pos += finfo->last_file_index * osymesz;
+                     pos += flaginfo->last_file_index * osymesz;
                      if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
                          || bfd_bwrite (outsym, osymesz, output_bfd) != osymesz)
                        return FALSE;
                    }
                }
 
                      if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
                          || bfd_bwrite (outsym, osymesz, output_bfd) != osymesz)
                        return FALSE;
                    }
                }
 
-             finfo->last_file_index = output_index;
-             finfo->last_file = isym;
+             flaginfo->last_file_index = output_index;
+             flaginfo->last_file = isym;
              break;
            }
 
          /* If doing task linking, convert normal global function symbols to
             static functions.  */
              break;
            }
 
          /* If doing task linking, convert normal global function symbols to
             static functions.  */
-         if (finfo->info->task_link && IS_EXTERNAL (input_bfd, isym))
+         if (flaginfo->info->task_link && IS_EXTERNAL (input_bfd, isym))
            isym.n_sclass = C_STAT;
 
          /* Output the symbol.  */
            isym.n_sclass = C_STAT;
 
          /* Output the symbol.  */
@@ -1869,7 +1945,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
              if (h == NULL)
                {
                  /* This can happen if there were errors earlier in
              if (h == NULL)
                {
                  /* This can happen if there were errors earlier in
-                     the link.  */
+                    the link.  */
                  bfd_set_error (bfd_error_bad_value);
                  return FALSE;
                }
                  bfd_set_error (bfd_error_bad_value);
                  return FALSE;
                }
@@ -1896,10 +1972,10 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
      already decided which symbols we are going to keep.  */
   esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
   esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
      already decided which symbols we are going to keep.  */
   esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
   esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
-  isymp = finfo->internal_syms;
-  indexp = finfo->sym_indices;
+  isymp = flaginfo->internal_syms;
+  indexp = flaginfo->sym_indices;
   sym_hash = obj_coff_sym_hashes (input_bfd);
   sym_hash = obj_coff_sym_hashes (input_bfd);
-  outsym = finfo->outsyms;
+  outsym = flaginfo->outsyms;
 
   while (esym < esym_end)
     {
 
   while (esym < esym_end)
     {
@@ -1923,9 +1999,10 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
              h = *sym_hash;
 
              /* The m68k-motorola-sysv assembler will sometimes
              h = *sym_hash;
 
              /* The m68k-motorola-sysv assembler will sometimes
-                 generate two symbols with the same name, but only one
-                 will have aux entries.  */
+                generate two symbols with the same name, but only one
+                will have aux entries.  */
              BFD_ASSERT (isymp->n_numaux == 0
              BFD_ASSERT (isymp->n_numaux == 0
+                         || h->numaux == 0
                          || h->numaux == isymp->n_numaux);
            }
 
                          || h->numaux == isymp->n_numaux);
            }
 
@@ -1941,7 +2018,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
              union internal_auxent aux;
              union internal_auxent *auxp;
 
              union internal_auxent aux;
              union internal_auxent *auxp;
 
-             if (h != NULL)
+             if (h != NULL && h->aux != NULL && (h->numaux > i))
                auxp = h->aux + i;
              else
                {
                auxp = h->aux + i;
              else
                {
@@ -1968,15 +2045,19 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                          if (strings == NULL)
                            return FALSE;
                        }
                          if (strings == NULL)
                            return FALSE;
                        }
-                     filename = strings + auxp->x_file.x_n.x_offset;
-                     indx = _bfd_stringtab_add (finfo->strtab, filename,
+                     if ((bfd_size_type) auxp->x_file.x_n.x_offset >= obj_coff_strings_len (input_bfd))
+                       filename = _("<corrupt>");
+                     else
+                       filename = strings + auxp->x_file.x_n.x_offset;
+                     indx = _bfd_stringtab_add (flaginfo->strtab, filename,
                                                 hash, copy);
                      if (indx == (bfd_size_type) -1)
                        return FALSE;
                      auxp->x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
                    }
                }
                                                 hash, copy);
                      if (indx == (bfd_size_type) -1)
                        return FALSE;
                      auxp->x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
                    }
                }
-             else if (isymp->n_sclass != C_STAT || isymp->n_type != T_NULL)
+             else if ((isymp->n_sclass != C_STAT || isymp->n_type != T_NULL)
+                      && isymp->n_sclass != C_NT_WEAK)
                {
                  unsigned long indx;
 
                {
                  unsigned long indx;
 
@@ -1990,18 +2071,18 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                          && indx < obj_raw_syment_count (input_bfd))
                        {
                          /* We look forward through the symbol for
                          && indx < obj_raw_syment_count (input_bfd))
                        {
                          /* We look forward through the symbol for
-                             the index of the next symbol we are going
-                             to include.  I don't know if this is
-                             entirely right.  */
-                         while ((finfo->sym_indices[indx] < 0
-                                 || ((bfd_size_type) finfo->sym_indices[indx]
+                            the index of the next symbol we are going
+                            to include.  I don't know if this is
+                            entirely right.  */
+                         while ((flaginfo->sym_indices[indx] < 0
+                                 || ((bfd_size_type) flaginfo->sym_indices[indx]
                                      < syment_base))
                                 && indx < obj_raw_syment_count (input_bfd))
                            ++indx;
                          if (indx >= obj_raw_syment_count (input_bfd))
                            indx = output_index;
                          else
                                      < syment_base))
                                 && indx < obj_raw_syment_count (input_bfd))
                            ++indx;
                          if (indx >= obj_raw_syment_count (input_bfd))
                            indx = output_index;
                          else
-                           indx = finfo->sym_indices[indx];
+                           indx = flaginfo->sym_indices[indx];
                          auxp->x_sym.x_fcnary.x_fcn.x_endndx.l = indx;
                        }
                    }
                          auxp->x_sym.x_fcnary.x_fcn.x_endndx.l = indx;
                        }
                    }
@@ -2011,7 +2092,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                    {
                      long symindx;
 
                    {
                      long symindx;
 
-                     symindx = finfo->sym_indices[indx];
+                     symindx = flaginfo->sym_indices[indx];
                      if (symindx < 0)
                        auxp->x_sym.x_tagndx.l = 0;
                      else
                      if (symindx < 0)
                        auxp->x_sym.x_tagndx.l = 0;
                      else
@@ -2031,12 +2112,12 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                      && isymp->_n._n_name[2] == 'f'
                      && isymp->_n._n_name[3] == '\0')
                    {
                      && isymp->_n._n_name[2] == 'f'
                      && isymp->_n._n_name[3] == '\0')
                    {
-                     if (finfo->last_bf_index != -1)
+                     if (flaginfo->last_bf_index != -1)
                        {
                        {
-                         finfo->last_bf.x_sym.x_fcnary.x_fcn.x_endndx.l =
+                         flaginfo->last_bf.x_sym.x_fcnary.x_fcn.x_endndx.l =
                            *indexp;
 
                            *indexp;
 
-                         if ((bfd_size_type) finfo->last_bf_index
+                         if ((bfd_size_type) flaginfo->last_bf_index
                              >= syment_base)
                            {
                              void *auxout;
                              >= syment_base)
                            {
                              void *auxout;
@@ -2045,13 +2126,13 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                                 file.  This will only happen if the
                                 assembler did not set up the .bf
                                 endndx symbols correctly.  */
                                 file.  This will only happen if the
                                 assembler did not set up the .bf
                                 endndx symbols correctly.  */
-                             auxout = (finfo->outsyms
-                                       + ((finfo->last_bf_index
+                             auxout = (flaginfo->outsyms
+                                       + ((flaginfo->last_bf_index
                                            - syment_base)
                                           * osymesz));
 
                              bfd_coff_swap_aux_out (output_bfd,
                                            - syment_base)
                                           * osymesz));
 
                              bfd_coff_swap_aux_out (output_bfd,
-                                                    &finfo->last_bf,
+                                                    &flaginfo->last_bf,
                                                     isymp->n_type,
                                                     isymp->n_sclass,
                                                     0, isymp->n_numaux,
                                                     isymp->n_type,
                                                     isymp->n_sclass,
                                                     0, isymp->n_numaux,
@@ -2062,18 +2143,18 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                              file_ptr pos;
 
                              /* We have already written out the last
                              file_ptr pos;
 
                              /* We have already written out the last
-                                 .bf aux entry.  We need to write it
-                                 out again.  We borrow *outsym
-                                 temporarily.  FIXME: This case should
-                                 be made faster.  */
+                                .bf aux entry.  We need to write it
+                                out again.  We borrow *outsym
+                                temporarily.  FIXME: This case should
+                                be made faster.  */
                              bfd_coff_swap_aux_out (output_bfd,
                              bfd_coff_swap_aux_out (output_bfd,
-                                                    &finfo->last_bf,
+                                                    &flaginfo->last_bf,
                                                     isymp->n_type,
                                                     isymp->n_sclass,
                                                     0, isymp->n_numaux,
                                                     outsym);
                              pos = obj_sym_filepos (output_bfd);
                                                     isymp->n_type,
                                                     isymp->n_sclass,
                                                     0, isymp->n_numaux,
                                                     outsym);
                              pos = obj_sym_filepos (output_bfd);
-                             pos += finfo->last_bf_index * osymesz;
+                             pos += flaginfo->last_bf_index * osymesz;
                              if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
                                  || (bfd_bwrite (outsym, osymesz, output_bfd)
                                      != osymesz))
                              if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
                                  || (bfd_bwrite (outsym, osymesz, output_bfd)
                                      != osymesz))
@@ -2082,14 +2163,14 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                        }
 
                      if (auxp->x_sym.x_fcnary.x_fcn.x_endndx.l != 0)
                        }
 
                      if (auxp->x_sym.x_fcnary.x_fcn.x_endndx.l != 0)
-                       finfo->last_bf_index = -1;
+                       flaginfo->last_bf_index = -1;
                      else
                        {
                          /* The endndx field of this aux entry must
                      else
                        {
                          /* The endndx field of this aux entry must
-                             be updated with the symbol number of the
-                             next .bf symbol.  */
-                         finfo->last_bf = *auxp;
-                         finfo->last_bf_index = (((outsym - finfo->outsyms)
+                            be updated with the symbol number of the
+                            next .bf symbol.  */
+                         flaginfo->last_bf = *auxp;
+                         flaginfo->last_bf_index = (((outsym - flaginfo->outsyms)
                                                   / osymesz)
                                                  + syment_base);
                        }
                                                   / osymesz)
                                                  + syment_base);
                        }
@@ -2114,8 +2195,8 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
     }
 
   /* Relocate the line numbers, unless we are stripping them.  */
     }
 
   /* Relocate the line numbers, unless we are stripping them.  */
-  if (finfo->info->strip == strip_none
-      || finfo->info->strip == strip_some)
+  if (flaginfo->info->strip == strip_none
+      || flaginfo->info->strip == strip_some)
     {
       for (o = input_bfd->sections; o != NULL; o = o->next)
        {
     {
       for (o = input_bfd->sections; o != NULL; o = o->next)
        {
@@ -2141,13 +2222,13 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
            continue;
 
          if (bfd_seek (input_bfd, o->line_filepos, SEEK_SET) != 0
            continue;
 
          if (bfd_seek (input_bfd, o->line_filepos, SEEK_SET) != 0
-             || bfd_bread (finfo->linenos, linesz * o->lineno_count,
+             || bfd_bread (flaginfo->linenos, linesz * o->lineno_count,
                           input_bfd) != linesz * o->lineno_count)
            return FALSE;
 
          offset = o->output_section->vma + o->output_offset - o->vma;
                           input_bfd) != linesz * o->lineno_count)
            return FALSE;
 
          offset = o->output_section->vma + o->output_offset - o->vma;
-         eline = finfo->linenos;
-         oeline = finfo->linenos;
+         eline = flaginfo->linenos;
+         oeline = flaginfo->linenos;
          elineend = eline + linesz * o->lineno_count;
          skipping = FALSE;
          for (; eline < elineend; eline += linesz)
          elineend = eline + linesz * o->lineno_count;
          skipping = FALSE;
          for (; eline < elineend; eline += linesz)
@@ -2164,7 +2245,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                {
                  long indx;
 
                {
                  long indx;
 
-                 indx = finfo->sym_indices[iline.l_addr.l_symndx];
+                 indx = flaginfo->sym_indices[iline.l_addr.l_symndx];
 
                  if (indx < 0)
                    {
 
                  if (indx < 0)
                    {
@@ -2190,7 +2271,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                         of the line numbers rather than an absolute
                         file index.  */
                      bfd_coff_swap_sym_in (output_bfd,
                         of the line numbers rather than an absolute
                         file index.  */
                      bfd_coff_swap_sym_in (output_bfd,
-                                           (finfo->outsyms
+                                           (flaginfo->outsyms
                                             + ((indx - syment_base)
                                                * osymesz)), &is);
                      if ((ISFCN (is.n_type)
                                             + ((indx - syment_base)
                                                * osymesz)), &is);
                      if ((ISFCN (is.n_type)
@@ -2199,7 +2280,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                        {
                          void *auxptr;
 
                        {
                          void *auxptr;
 
-                         auxptr = (finfo->outsyms
+                         auxptr = (flaginfo->outsyms
                                    + ((indx - syment_base + 1)
                                       * osymesz));
                          bfd_coff_swap_aux_in (output_bfd, auxptr,
                                    + ((indx - syment_base + 1)
                                       * osymesz));
                          bfd_coff_swap_aux_in (output_bfd, auxptr,
@@ -2208,7 +2289,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                          ia.x_sym.x_fcnary.x_fcn.x_lnnoptr =
                            (o->output_section->line_filepos
                             + o->output_section->lineno_count * linesz
                          ia.x_sym.x_fcnary.x_fcn.x_lnnoptr =
                            (o->output_section->line_filepos
                             + o->output_section->lineno_count * linesz
-                            + eline - finfo->linenos);
+                            + eline - flaginfo->linenos);
                          bfd_coff_swap_aux_out (output_bfd, &ia,
                                                 is.n_type, is.n_sclass, 0,
                                                 is.n_numaux, auxptr);
                          bfd_coff_swap_aux_out (output_bfd, &ia,
                                                 is.n_type, is.n_sclass, 0,
                                                 is.n_numaux, auxptr);
@@ -2221,7 +2302,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                }
 
              if (!skipping)
                }
 
              if (!skipping)
-               {
+               {
                  bfd_coff_swap_lineno_out (output_bfd, &iline, oeline);
                  oeline += linesz;
                }
                  bfd_coff_swap_lineno_out (output_bfd, &iline, oeline);
                  oeline += linesz;
                }
@@ -2229,9 +2310,9 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
 
          pos = o->output_section->line_filepos;
          pos += o->output_section->lineno_count * linesz;
 
          pos = o->output_section->line_filepos;
          pos += o->output_section->lineno_count * linesz;
-         amt = oeline - finfo->linenos;
+         amt = oeline - flaginfo->linenos;
          if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
          if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
-             || bfd_bwrite (finfo->linenos, amt, output_bfd) != amt)
+             || bfd_bwrite (flaginfo->linenos, amt, output_bfd) != amt)
            return FALSE;
 
          o->output_section->lineno_count += amt / linesz;
            return FALSE;
 
          o->output_section->lineno_count += amt / linesz;
@@ -2242,30 +2323,30 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
      symbol will be the first symbol in the next input file.  In the
      normal case, this will save us from writing out the C_FILE symbol
      again.  */
      symbol will be the first symbol in the next input file.  In the
      normal case, this will save us from writing out the C_FILE symbol
      again.  */
-  if (finfo->last_file_index != -1
-      && (bfd_size_type) finfo->last_file_index >= syment_base)
+  if (flaginfo->last_file_index != -1
+      && (bfd_size_type) flaginfo->last_file_index >= syment_base)
     {
     {
-      finfo->last_file.n_value = output_index;
-      bfd_coff_swap_sym_out (output_bfd, &finfo->last_file,
-                            (finfo->outsyms
-                             + ((finfo->last_file_index - syment_base)
+      flaginfo->last_file.n_value = output_index;
+      bfd_coff_swap_sym_out (output_bfd, &flaginfo->last_file,
+                            (flaginfo->outsyms
+                             + ((flaginfo->last_file_index - syment_base)
                                 * osymesz)));
     }
 
   /* Write the modified symbols to the output file.  */
                                 * osymesz)));
     }
 
   /* Write the modified symbols to the output file.  */
-  if (outsym > finfo->outsyms)
+  if (outsym > flaginfo->outsyms)
     {
       file_ptr pos;
       bfd_size_type amt;
 
       pos = obj_sym_filepos (output_bfd) + syment_base * osymesz;
     {
       file_ptr pos;
       bfd_size_type amt;
 
       pos = obj_sym_filepos (output_bfd) + syment_base * osymesz;
-      amt = outsym - finfo->outsyms;
+      amt = outsym - flaginfo->outsyms;
       if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
       if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
-         || bfd_bwrite (finfo->outsyms, amt, output_bfd) != amt)
+         || bfd_bwrite (flaginfo->outsyms, amt, output_bfd) != amt)
        return FALSE;
 
       BFD_ASSERT ((obj_raw_syment_count (output_bfd)
        return FALSE;
 
       BFD_ASSERT ((obj_raw_syment_count (output_bfd)
-                  + (outsym - finfo->outsyms) / osymesz)
+                  + (outsym - flaginfo->outsyms) / osymesz)
                  == output_index);
 
       obj_raw_syment_count (output_bfd) = output_index;
                  == output_index);
 
       obj_raw_syment_count (output_bfd) = output_index;
@@ -2291,10 +2372,10 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
          if ((o->flags & SEC_RELOC) != 0
              && o->reloc_count != 0)
            {
          if ((o->flags & SEC_RELOC) != 0
              && o->reloc_count != 0)
            {
-             ((*_bfd_error_handler)
-              (_("%s: relocs in section `%s', but it has no contents"),
-               bfd_archive_filename (input_bfd),
-               bfd_get_section_name (input_bfd, o)));
+             _bfd_error_handler
+               /* xgettext: c-format */
+               (_("%pB: relocs in section `%pA', but it has no contents"),
+                input_bfd, o);
              bfd_set_error (bfd_error_no_contents);
              return FALSE;
            }
              bfd_set_error (bfd_error_no_contents);
              return FALSE;
            }
@@ -2307,10 +2388,9 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
        contents = secdata->contents;
       else
        {
        contents = secdata->contents;
       else
        {
-         bfd_size_type x = o->rawsize ? o->rawsize : o->size;
-         if (! bfd_get_section_contents (input_bfd, o, finfo->contents, 0, x))
+         contents = flaginfo->contents;
+         if (! bfd_get_full_section_contents (input_bfd, o, &contents))
            return FALSE;
            return FALSE;
-         contents = finfo->contents;
        }
 
       if ((o->flags & SEC_RELOC) != 0)
        }
 
       if ((o->flags & SEC_RELOC) != 0)
@@ -2322,26 +2402,57 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
          /* Read in the relocs.  */
          target_index = o->output_section->target_index;
          internal_relocs = (_bfd_coff_read_internal_relocs
          /* Read in the relocs.  */
          target_index = o->output_section->target_index;
          internal_relocs = (_bfd_coff_read_internal_relocs
-                            (input_bfd, o, FALSE, finfo->external_relocs,
-                             finfo->info->relocatable,
-                             (finfo->info->relocatable
-                              ? (finfo->section_info[target_index].relocs
+                            (input_bfd, o, FALSE, flaginfo->external_relocs,
+                             bfd_link_relocatable (flaginfo->info),
+                             (bfd_link_relocatable (flaginfo->info)
+                              ? (flaginfo->section_info[target_index].relocs
                                  + o->output_section->reloc_count)
                                  + o->output_section->reloc_count)
-                              : finfo->internal_relocs)));
-         if (internal_relocs == NULL)
+                              : flaginfo->internal_relocs)));
+         if (internal_relocs == NULL
+             && o->reloc_count > 0)
            return FALSE;
 
            return FALSE;
 
+         /* Run through the relocs looking for relocs against symbols
+            coming from discarded sections and complain about them.  */
+         irel = internal_relocs;
+         for (; irel < &internal_relocs[o->reloc_count]; irel++)
+           {
+             struct coff_link_hash_entry *h;
+             asection *ps = NULL;
+             long symndx = irel->r_symndx;
+             if (symndx < 0)
+               continue;
+             h = obj_coff_sym_hashes (input_bfd)[symndx];
+             if (h == NULL)
+               continue;
+             while (h->root.type == bfd_link_hash_indirect
+                    || h->root.type == bfd_link_hash_warning)
+               h = (struct coff_link_hash_entry *) h->root.u.i.link;
+             if (h->root.type == bfd_link_hash_defined
+                 || h->root.type == bfd_link_hash_defweak)
+               ps = h->root.u.def.section;
+             if (ps == NULL)
+               continue;
+             /* Complain if definition comes from an excluded section.  */
+             if (ps->flags & SEC_EXCLUDE)
+               (*flaginfo->info->callbacks->einfo)
+                 /* xgettext: c-format */
+                 (_("%X`%s' referenced in section `%pA' of %pB: "
+                    "defined in discarded section `%pA' of %pB\n"),
+                  h->root.root.string, o, input_bfd, ps, ps->owner);
+           }
+
          /* Call processor specific code to relocate the section
          /* Call processor specific code to relocate the section
-             contents.  */
-         if (! bfd_coff_relocate_section (output_bfd, finfo->info,
+            contents.  */
+         if (! bfd_coff_relocate_section (output_bfd, flaginfo->info,
                                           input_bfd, o,
                                           contents,
                                           internal_relocs,
                                           input_bfd, o,
                                           contents,
                                           internal_relocs,
-                                          finfo->internal_syms,
-                                          finfo->sec_ptrs))
+                                          flaginfo->internal_syms,
+                                          flaginfo->sec_ptrs))
            return FALSE;
 
            return FALSE;
 
-         if (finfo->info->relocatable)
+         if (bfd_link_relocatable (flaginfo->info))
            {
              bfd_vma offset;
              struct internal_reloc *irelend;
            {
              bfd_vma offset;
              struct internal_reloc *irelend;
@@ -2350,7 +2461,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
              offset = o->output_section->vma + o->output_offset - o->vma;
              irel = internal_relocs;
              irelend = irel + o->reloc_count;
              offset = o->output_section->vma + o->output_offset - o->vma;
              irel = internal_relocs;
              irelend = irel + o->reloc_count;
-             rel_hash = (finfo->section_info[target_index].rel_hashes
+             rel_hash = (flaginfo->section_info[target_index].rel_hashes
                          + o->output_section->reloc_count);
              for (; irel < irelend; irel++, rel_hash++)
                {
                          + o->output_section->reloc_count);
              for (; irel < irelend; irel++, rel_hash++)
                {
@@ -2367,7 +2478,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
 
                  if (adjust_symndx)
                    {
 
                  if (adjust_symndx)
                    {
-                     if (! (*adjust_symndx) (output_bfd, finfo->info,
+                     if (! (*adjust_symndx) (output_bfd, flaginfo->info,
                                              input_bfd, o, irel,
                                              &adjusted))
                        return FALSE;
                                              input_bfd, o, irel,
                                              &adjusted))
                        return FALSE;
@@ -2397,7 +2508,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                    {
                      long indx;
 
                    {
                      long indx;
 
-                     indx = finfo->sym_indices[irel->r_symndx];
+                     indx = flaginfo->sym_indices[irel->r_symndx];
                      if (indx != -1)
                        irel->r_symndx = indx;
                      else
                      if (indx != -1)
                        irel->r_symndx = indx;
                      else
@@ -2407,20 +2518,18 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                          char buf[SYMNMLEN + 1];
 
                          /* This reloc is against a symbol we are
                          char buf[SYMNMLEN + 1];
 
                          /* This reloc is against a symbol we are
-                             stripping.  This should have been handled
+                            stripping.  This should have been handled
                             by the 'dont_skip_symbol' code in the while
                             loop at the top of this function.  */
                             by the 'dont_skip_symbol' code in the while
                             loop at the top of this function.  */
-                         is = finfo->internal_syms + irel->r_symndx;
+                         is = flaginfo->internal_syms + irel->r_symndx;
 
                          name = (_bfd_coff_internal_syment_name
                                  (input_bfd, is, buf));
                          if (name == NULL)
                            return FALSE;
 
 
                          name = (_bfd_coff_internal_syment_name
                                  (input_bfd, is, buf));
                          if (name == NULL)
                            return FALSE;
 
-                         if (! ((*finfo->info->callbacks->unattached_reloc)
-                                (finfo->info, name, input_bfd, o,
-                                 irel->r_vaddr)))
-                           return FALSE;
+                         (*flaginfo->info->callbacks->unattached_reloc)
+                           (flaginfo->info, name, input_bfd, o, irel->r_vaddr);
                        }
                    }
                }
                        }
                    }
                }
@@ -2432,7 +2541,8 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
       /* Write out the modified section contents.  */
       if (secdata == NULL || secdata->stab_info == NULL)
        {
       /* Write out the modified section contents.  */
       if (secdata == NULL || secdata->stab_info == NULL)
        {
-         file_ptr loc = o->output_offset * bfd_octets_per_byte (output_bfd);
+         file_ptr loc = (o->output_offset
+                         * bfd_octets_per_byte (output_bfd, o));
          if (! bfd_set_section_contents (output_bfd, o->output_section,
                                          contents, loc, o->size))
            return FALSE;
          if (! bfd_set_section_contents (output_bfd, o->output_section,
                                          contents, loc, o->size))
            return FALSE;
@@ -2440,32 +2550,33 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
       else
        {
          if (! (_bfd_write_section_stabs
       else
        {
          if (! (_bfd_write_section_stabs
-                (output_bfd, &coff_hash_table (finfo->info)->stab_info,
+                (output_bfd, &coff_hash_table (flaginfo->info)->stab_info,
                  o, &secdata->stab_info, contents)))
            return FALSE;
        }
     }
 
                  o, &secdata->stab_info, contents)))
            return FALSE;
        }
     }
 
-  if (! finfo->info->keep_memory
+  if (! flaginfo->info->keep_memory
       && ! _bfd_coff_free_symbols (input_bfd))
     return FALSE;
 
   return TRUE;
 }
 
       && ! _bfd_coff_free_symbols (input_bfd))
     return FALSE;
 
   return TRUE;
 }
 
-/* Write out a global symbol.  Called via coff_link_hash_traverse.  */
+/* Write out a global symbol.  Called via bfd_hash_traverse.  */
 
 bfd_boolean
 
 bfd_boolean
-_bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *data)
+_bfd_coff_write_global_sym (struct bfd_hash_entry *bh, void *data)
 {
 {
-  struct coff_final_link_info *finfo = (struct coff_final_link_info *) data;
+  struct coff_link_hash_entry *h = (struct coff_link_hash_entry *) bh;
+  struct coff_final_link_info *flaginfo = (struct coff_final_link_info *) data;
   bfd *output_bfd;
   struct internal_syment isym;
   bfd_size_type symesz;
   unsigned int i;
   file_ptr pos;
 
   bfd *output_bfd;
   struct internal_syment isym;
   bfd_size_type symesz;
   unsigned int i;
   file_ptr pos;
 
-  output_bfd = finfo->output_bfd;
+  output_bfd = flaginfo->output_bfd;
 
   if (h->root.type == bfd_link_hash_warning)
     {
 
   if (h->root.type == bfd_link_hash_warning)
     {
@@ -2478,9 +2589,9 @@ _bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *data)
     return TRUE;
 
   if (h->indx != -2
     return TRUE;
 
   if (h->indx != -2
-      && (finfo->info->strip == strip_all
-         || (finfo->info->strip == strip_some
-             && (bfd_hash_lookup (finfo->info->keep_hash,
+      && (flaginfo->info->strip == strip_all
+         || (flaginfo->info->strip == strip_some
+             && (bfd_hash_lookup (flaginfo->info->keep_hash,
                                   h->root.root.string, FALSE, FALSE)
                  == NULL))))
     return TRUE;
                                   h->root.root.string, FALSE, FALSE)
                  == NULL))))
     return TRUE;
@@ -2511,7 +2622,7 @@ _bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *data)
          isym.n_scnum = sec->target_index;
        isym.n_value = (h->root.u.def.value
                        + h->root.u.def.section->output_offset);
          isym.n_scnum = sec->target_index;
        isym.n_value = (h->root.u.def.value
                        + h->root.u.def.section->output_offset);
-       if (! obj_pe (finfo->output_bfd))
+       if (! obj_pe (flaginfo->output_bfd))
          isym.n_value += sec->vma;
       }
       break;
          isym.n_value += sec->vma;
       }
       break;
@@ -2534,20 +2645,20 @@ _bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *data)
       bfd_size_type indx;
 
       hash = TRUE;
       bfd_size_type indx;
 
       hash = TRUE;
-      if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
+      if (flaginfo->info->traditional_format)
        hash = FALSE;
        hash = FALSE;
-      indx = _bfd_stringtab_add (finfo->strtab, h->root.root.string, hash,
+      indx = _bfd_stringtab_add (flaginfo->strtab, h->root.root.string, hash,
                                 FALSE);
       if (indx == (bfd_size_type) -1)
        {
                                 FALSE);
       if (indx == (bfd_size_type) -1)
        {
-         finfo->failed = TRUE;
+         flaginfo->failed = TRUE;
          return FALSE;
        }
       isym._n._n_n._n_zeroes = 0;
       isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
     }
 
          return FALSE;
        }
       isym._n._n_n._n_zeroes = 0;
       isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
     }
 
-  isym.n_sclass = h->class;
+  isym.n_sclass = h->symbol_class;
   isym.n_type = h->type;
 
   if (isym.n_sclass == C_NULL)
   isym.n_type = h->type;
 
   if (isym.n_sclass == C_NULL)
@@ -2557,7 +2668,7 @@ _bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *data)
      defined globals to statics, then do that conversion now.  If the
      symbol is not being converted, just ignore it and it will be
      output during a later pass.  */
      defined globals to statics, then do that conversion now.  If the
      symbol is not being converted, just ignore it and it will be
      output during a later pass.  */
-  if (finfo->global_to_static)
+  if (flaginfo->global_to_static)
     {
       if (! IS_EXTERNAL (output_bfd, isym))
        return TRUE;
     {
       if (! IS_EXTERNAL (output_bfd, isym))
        return TRUE;
@@ -2568,23 +2679,23 @@ _bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *data)
   /* When a weak symbol is not overridden by a strong one,
      turn it into an external symbol when not building a
      shared or relocatable object.  */
   /* When a weak symbol is not overridden by a strong one,
      turn it into an external symbol when not building a
      shared or relocatable object.  */
-  if (! finfo->info->shared
-      && ! finfo->info->relocatable
-      && IS_WEAK_EXTERNAL (finfo->output_bfd, isym))
+  if (! bfd_link_pic (flaginfo->info)
+      && ! bfd_link_relocatable (flaginfo->info)
+      && IS_WEAK_EXTERNAL (flaginfo->output_bfd, isym))
     isym.n_sclass = C_EXT;
 
   isym.n_numaux = h->numaux;
 
     isym.n_sclass = C_EXT;
 
   isym.n_numaux = h->numaux;
 
-  bfd_coff_swap_sym_out (output_bfd, &isym, finfo->outsyms);
+  bfd_coff_swap_sym_out (output_bfd, &isym, flaginfo->outsyms);
 
   symesz = bfd_coff_symesz (output_bfd);
 
   pos = obj_sym_filepos (output_bfd);
   pos += obj_raw_syment_count (output_bfd) * symesz;
   if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
 
   symesz = bfd_coff_symesz (output_bfd);
 
   pos = obj_sym_filepos (output_bfd);
   pos += obj_raw_syment_count (output_bfd) * symesz;
   if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
-      || bfd_bwrite (finfo->outsyms, symesz, output_bfd) != symesz)
+      || bfd_bwrite (flaginfo->outsyms, symesz, output_bfd) != symesz)
     {
     {
-      finfo->failed = TRUE;
+      flaginfo->failed = TRUE;
       return FALSE;
     }
 
       return FALSE;
     }
 
@@ -2603,7 +2714,7 @@ _bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *data)
       auxp = h->aux + i;
 
       /* Look for a section aux entry here using the same tests that
       auxp = h->aux + i;
 
       /* Look for a section aux entry here using the same tests that
-         coff_swap_aux_out uses.  */
+        coff_swap_aux_out uses.  */
       if (i == 0
          && (isym.n_sclass == C_STAT
              || isym.n_sclass == C_HIDDEN)
       if (i == 0
          && (isym.n_sclass == C_STAT
              || isym.n_sclass == C_HIDDEN)
@@ -2619,24 +2730,22 @@ _bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *data)
              auxp->x_scn.x_scnlen = sec->size;
 
              /* For PE, an overflow on the final link reportedly does
              auxp->x_scn.x_scnlen = sec->size;
 
              /* For PE, an overflow on the final link reportedly does
-                 not matter.  FIXME: Why not?  */
+                not matter.  FIXME: Why not?  */
              if (sec->reloc_count > 0xffff
                  && (! obj_pe (output_bfd)
              if (sec->reloc_count > 0xffff
                  && (! obj_pe (output_bfd)
-                     || finfo->info->relocatable))
-               (*_bfd_error_handler)
-                 (_("%s: %s: reloc overflow: 0x%lx > 0xffff"),
-                  bfd_get_filename (output_bfd),
-                  bfd_get_section_name (output_bfd, sec),
-                  sec->reloc_count);
+                     || bfd_link_relocatable (flaginfo->info)))
+               _bfd_error_handler
+                 /* xgettext: c-format */
+                 (_("%pB: %pA: reloc overflow: %#x > 0xffff"),
+                  output_bfd, sec, sec->reloc_count);
 
              if (sec->lineno_count > 0xffff
                  && (! obj_pe (output_bfd)
 
              if (sec->lineno_count > 0xffff
                  && (! obj_pe (output_bfd)
-                     || finfo->info->relocatable))
-               (*_bfd_error_handler)
-                 (_("%s: warning: %s: line number overflow: 0x%lx > 0xffff"),
-                  bfd_get_filename (output_bfd),
-                  bfd_get_section_name (output_bfd, sec),
-                  sec->lineno_count);
+                     || bfd_link_relocatable (flaginfo->info)))
+               _bfd_error_handler
+                 /* xgettext: c-format */
+                 (_("%pB: warning: %pA: line number overflow: %#x > 0xffff"),
+                  output_bfd, sec, sec->lineno_count);
 
              auxp->x_scn.x_nreloc = sec->reloc_count;
              auxp->x_scn.x_nlinno = sec->lineno_count;
 
              auxp->x_scn.x_nreloc = sec->reloc_count;
              auxp->x_scn.x_nlinno = sec->lineno_count;
@@ -2648,10 +2757,10 @@ _bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *data)
 
       bfd_coff_swap_aux_out (output_bfd, auxp, isym.n_type,
                             isym.n_sclass, (int) i, isym.n_numaux,
 
       bfd_coff_swap_aux_out (output_bfd, auxp, isym.n_type,
                             isym.n_sclass, (int) i, isym.n_numaux,
-                            finfo->outsyms);
-      if (bfd_bwrite (finfo->outsyms, symesz, output_bfd) != symesz)
+                            flaginfo->outsyms);
+      if (bfd_bwrite (flaginfo->outsyms, symesz, output_bfd) != symesz)
        {
        {
-         finfo->failed = TRUE;
+         flaginfo->failed = TRUE;
          return FALSE;
        }
       ++obj_raw_syment_count (output_bfd);
          return FALSE;
        }
       ++obj_raw_syment_count (output_bfd);
@@ -2667,7 +2776,7 @@ _bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *data)
 bfd_boolean
 _bfd_coff_write_task_globals (struct coff_link_hash_entry *h, void *data)
 {
 bfd_boolean
 _bfd_coff_write_task_globals (struct coff_link_hash_entry *h, void *data)
 {
-  struct coff_final_link_info *finfo = (struct coff_final_link_info *) data;
+  struct coff_final_link_info *flaginfo = (struct coff_final_link_info *) data;
   bfd_boolean rtnval = TRUE;
   bfd_boolean save_global_to_static;
 
   bfd_boolean rtnval = TRUE;
   bfd_boolean save_global_to_static;
 
@@ -2680,10 +2789,10 @@ _bfd_coff_write_task_globals (struct coff_link_hash_entry *h, void *data)
        {
        case bfd_link_hash_defined:
        case bfd_link_hash_defweak:
        {
        case bfd_link_hash_defined:
        case bfd_link_hash_defweak:
-         save_global_to_static = finfo->global_to_static;
-         finfo->global_to_static = TRUE;
-         rtnval = _bfd_coff_write_global_sym (h, data);
-         finfo->global_to_static = save_global_to_static;
+         save_global_to_static = flaginfo->global_to_static;
+         flaginfo->global_to_static = TRUE;
+         rtnval = _bfd_coff_write_global_sym (&h->root.root, data);
+         flaginfo->global_to_static = save_global_to_static;
          break;
        default:
          break;
          break;
        default:
          break;
@@ -2696,7 +2805,7 @@ _bfd_coff_write_task_globals (struct coff_link_hash_entry *h, void *data)
 
 bfd_boolean
 _bfd_coff_reloc_link_order (bfd *output_bfd,
 
 bfd_boolean
 _bfd_coff_reloc_link_order (bfd *output_bfd,
-                           struct coff_final_link_info *finfo,
+                           struct coff_final_link_info *flaginfo,
                            asection *output_section,
                            struct bfd_link_order *link_order)
 {
                            asection *output_section,
                            struct bfd_link_order *link_order)
 {
@@ -2720,12 +2829,12 @@ _bfd_coff_reloc_link_order (bfd *output_bfd,
       file_ptr loc;
 
       size = bfd_get_reloc_size (howto);
       file_ptr loc;
 
       size = bfd_get_reloc_size (howto);
-      buf = bfd_zmalloc (size);
-      if (buf == NULL)
+      buf = (bfd_byte *) bfd_zmalloc (size);
+      if (buf == NULL && size != 0)
        return FALSE;
 
       rstat = _bfd_relocate_contents (howto, output_bfd,
        return FALSE;
 
       rstat = _bfd_relocate_contents (howto, output_bfd,
-                                     (bfd_vma) link_order->u.reloc.p->addend,\
+                                     (bfd_vma) link_order->u.reloc.p->addend,
                                      buf);
       switch (rstat)
        {
                                      buf);
       switch (rstat)
        {
@@ -2735,23 +2844,19 @@ _bfd_coff_reloc_link_order (bfd *output_bfd,
        case bfd_reloc_outofrange:
          abort ();
        case bfd_reloc_overflow:
        case bfd_reloc_outofrange:
          abort ();
        case bfd_reloc_overflow:
-         if (! ((*finfo->info->callbacks->reloc_overflow)
-                (finfo->info,
-                 (link_order->type == bfd_section_reloc_link_order
-                  ? bfd_section_name (output_bfd,
-                                      link_order->u.reloc.p->u.section)
-                  : link_order->u.reloc.p->u.name),
-                 howto->name, link_order->u.reloc.p->addend,
-                 (bfd *) NULL, (asection *) NULL, (bfd_vma) 0)))
-           {
-             free (buf);
-             return FALSE;
-           }
+         (*flaginfo->info->callbacks->reloc_overflow)
+           (flaginfo->info, NULL,
+            (link_order->type == bfd_section_reloc_link_order
+             ? bfd_section_name (link_order->u.reloc.p->u.section)
+             : link_order->u.reloc.p->u.name),
+            howto->name, link_order->u.reloc.p->addend,
+            (bfd *) NULL, (asection *) NULL, (bfd_vma) 0);
          break;
        }
          break;
        }
-      loc = link_order->offset * bfd_octets_per_byte (output_bfd);
+      loc = link_order->offset * bfd_octets_per_byte (output_bfd,
+                                                     output_section);
       ok = bfd_set_section_contents (output_bfd, output_section, buf,
       ok = bfd_set_section_contents (output_bfd, output_section, buf,
-                                     loc, size);
+                                    loc, size);
       free (buf);
       if (! ok)
        return FALSE;
       free (buf);
       if (! ok)
        return FALSE;
@@ -2759,9 +2864,9 @@ _bfd_coff_reloc_link_order (bfd *output_bfd,
 
   /* Store the reloc information in the right place.  It will get
      swapped and written out at the end of the final_link routine.  */
 
   /* Store the reloc information in the right place.  It will get
      swapped and written out at the end of the final_link routine.  */
-  irel = (finfo->section_info[output_section->target_index].relocs
+  irel = (flaginfo->section_info[output_section->target_index].relocs
          + output_section->reloc_count);
          + output_section->reloc_count);
-  rel_hash_ptr = (finfo->section_info[output_section->target_index].rel_hashes
+  rel_hash_ptr = (flaginfo->section_info[output_section->target_index].rel_hashes
                  + output_section->reloc_count);
 
   memset (irel, 0, sizeof (struct internal_reloc));
                  + output_section->reloc_count);
 
   memset (irel, 0, sizeof (struct internal_reloc));
@@ -2772,9 +2877,9 @@ _bfd_coff_reloc_link_order (bfd *output_bfd,
   if (link_order->type == bfd_section_reloc_link_order)
     {
       /* We need to somehow locate a symbol in the right section.  The
   if (link_order->type == bfd_section_reloc_link_order)
     {
       /* We need to somehow locate a symbol in the right section.  The
-         symbol must either have a value of zero, or we must adjust
-         the addend by the value of the symbol.  FIXME: Write this
-         when we need it.  The old linker couldn't handle this anyhow.  */
+        symbol must either have a value of zero, or we must adjust
+        the addend by the value of the symbol.  FIXME: Write this
+        when we need it.  The old linker couldn't handle this anyhow.  */
       abort ();
       *rel_hash_ptr = NULL;
       irel->r_symndx = 0;
       abort ();
       *rel_hash_ptr = NULL;
       irel->r_symndx = 0;
@@ -2784,7 +2889,7 @@ _bfd_coff_reloc_link_order (bfd *output_bfd,
       struct coff_link_hash_entry *h;
 
       h = ((struct coff_link_hash_entry *)
       struct coff_link_hash_entry *h;
 
       h = ((struct coff_link_hash_entry *)
-          bfd_wrapped_link_hash_lookup (output_bfd, finfo->info,
+          bfd_wrapped_link_hash_lookup (output_bfd, flaginfo->info,
                                         link_order->u.reloc.p->u.name,
                                         FALSE, FALSE, TRUE));
       if (h != NULL)
                                         link_order->u.reloc.p->u.name,
                                         FALSE, FALSE, TRUE));
       if (h != NULL)
@@ -2802,10 +2907,9 @@ _bfd_coff_reloc_link_order (bfd *output_bfd,
        }
       else
        {
        }
       else
        {
-         if (! ((*finfo->info->callbacks->unattached_reloc)
-                (finfo->info, link_order->u.reloc.p->u.name, (bfd *) NULL,
-                 (asection *) NULL, (bfd_vma) 0)))
-           return FALSE;
+         (*flaginfo->info->callbacks->unattached_reloc)
+           (flaginfo->info, link_order->u.reloc.p->u.name,
+            (bfd *) NULL, (asection *) NULL, (bfd_vma) 0);
          irel->r_symndx = 0;
        }
     }
          irel->r_symndx = 0;
        }
     }
@@ -2847,6 +2951,7 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
       struct internal_syment *sym;
       bfd_vma addend;
       bfd_vma val;
       struct internal_syment *sym;
       bfd_vma addend;
       bfd_vma val;
+      asection *sec;
       reloc_howto_type *howto;
       bfd_reloc_status_type rstat;
 
       reloc_howto_type *howto;
       bfd_reloc_status_type rstat;
 
@@ -2860,9 +2965,9 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
       else if (symndx < 0
               || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
        {
       else if (symndx < 0
               || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
        {
-         (*_bfd_error_handler)
-           ("%s: illegal symbol index %ld in relocs",
-            bfd_archive_filename (input_bfd), symndx);
+         _bfd_error_handler
+           /* xgettext: c-format */
+           (_("%pB: illegal symbol index %ld in relocs"), input_bfd, symndx);
          return FALSE;
        }
       else
          return FALSE;
        }
       else
@@ -2872,9 +2977,9 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
        }
 
       /* COFF treats common symbols in one of two ways.  Either the
        }
 
       /* COFF treats common symbols in one of two ways.  Either the
-         size of the symbol is included in the section contents, or it
-         is not.  We assume that the size is not included, and force
-         the rtype_to_howto function to adjust the addend as needed.  */
+        size of the symbol is included in the section contents, or it
+        is not.  We assume that the size is not included, and force
+        the rtype_to_howto function to adjust the addend as needed.  */
       if (sym != NULL && sym->n_scnum != 0)
        addend = - sym->n_value;
       else
       if (sym != NULL && sym->n_scnum != 0)
        addend = - sym->n_value;
       else
@@ -2886,23 +2991,21 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
        return FALSE;
 
       /* If we are doing a relocatable link, then we can just ignore
        return FALSE;
 
       /* If we are doing a relocatable link, then we can just ignore
-         a PC relative reloc that is pcrel_offset.  It will already
-         have the correct value.  If this is not a relocatable link,
-         then we should ignore the symbol value.  */
+        a PC relative reloc that is pcrel_offset.  It will already
+        have the correct value.  If this is not a relocatable link,
+        then we should ignore the symbol value.  */
       if (howto->pc_relative && howto->pcrel_offset)
        {
       if (howto->pc_relative && howto->pcrel_offset)
        {
-         if (info->relocatable)
+         if (bfd_link_relocatable (info))
            continue;
          if (sym != NULL && sym->n_scnum != 0)
            addend += sym->n_value;
        }
 
       val = 0;
            continue;
          if (sym != NULL && sym->n_scnum != 0)
            addend += sym->n_value;
        }
 
       val = 0;
-
+      sec = NULL;
       if (h == NULL)
        {
       if (h == NULL)
        {
-         asection *sec;
-
          if (symndx == -1)
            {
              sec = bfd_abs_section_ptr;
          if (symndx == -1)
            {
              sec = bfd_abs_section_ptr;
@@ -2911,7 +3014,13 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
          else
            {
              sec = sections[symndx];
          else
            {
              sec = sections[symndx];
-              val = (sec->output_section->vma
+
+             /* PR 19623: Relocations against symbols in
+                the absolute sections should ignored.  */
+             if (bfd_is_abs_section (sec))
+               continue;
+
+             val = (sec->output_section->vma
                     + sec->output_offset
                     + sym->n_value);
              if (! obj_pe (input_bfd))
                     + sec->output_offset
                     + sym->n_value);
              if (! obj_pe (input_bfd))
@@ -2923,24 +3032,61 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
          if (h->root.type == bfd_link_hash_defined
              || h->root.type == bfd_link_hash_defweak)
            {
          if (h->root.type == bfd_link_hash_defined
              || h->root.type == bfd_link_hash_defweak)
            {
-             asection *sec;
-
+             /* Defined weak symbols are a GNU extension. */
              sec = h->root.u.def.section;
              val = (h->root.u.def.value
                     + sec->output_section->vma
                     + sec->output_offset);
              sec = h->root.u.def.section;
              val = (h->root.u.def.value
                     + sec->output_section->vma
                     + sec->output_offset);
-             }
+           }
 
          else if (h->root.type == bfd_link_hash_undefweak)
 
          else if (h->root.type == bfd_link_hash_undefweak)
-           val = 0;
-
-         else if (! info->relocatable)
            {
            {
-             if (! ((*info->callbacks->undefined_symbol)
-                    (info, h->root.root.string, input_bfd, input_section,
-                     rel->r_vaddr - input_section->vma, TRUE)))
-               return FALSE;
+             if (h->symbol_class == C_NT_WEAK && h->numaux == 1)
+               {
+                 /* See _Microsoft Portable Executable and Common Object
+                    File Format Specification_, section 5.5.3.
+                    Note that weak symbols without aux records are a GNU
+                    extension.
+                    FIXME: All weak externals are treated as having
+                    characteristic IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY (1).
+                    These behave as per SVR4 ABI:  A library member
+                    will resolve a weak external only if a normal
+                    external causes the library member to be linked.
+                    See also linker.c: generic_link_check_archive_element. */
+                 struct coff_link_hash_entry *h2 =
+                   h->auxbfd->tdata.coff_obj_data->sym_hashes[
+                   h->aux->x_sym.x_tagndx.l];
+
+                 if (!h2 || h2->root.type == bfd_link_hash_undefined)
+                   {
+                     sec = bfd_abs_section_ptr;
+                     val = 0;
+                   }
+                 else
+                   {
+                     sec = h2->root.u.def.section;
+                     val = h2->root.u.def.value
+                       + sec->output_section->vma + sec->output_offset;
+                   }
+               }
+             else
+               /* This is a GNU extension.  */
+               val = 0;
            }
            }
+
+         else if (! bfd_link_relocatable (info))
+           (*info->callbacks->undefined_symbol)
+             (info, h->root.root.string, input_bfd, input_section,
+              rel->r_vaddr - input_section->vma, TRUE);
+       }
+
+      /* If the input section defining the symbol has been discarded
+        then zero this reloc field.  */
+      if (sec != NULL && discarded_section (sec))
+       {
+         _bfd_clear_contents (howto, input_bfd, input_section,
+                              contents, rel->r_vaddr - input_section->vma);
+         continue;
        }
 
       if (info->base_file)
        }
 
       if (info->base_file)
@@ -2952,16 +3098,16 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
                 absolute.  We output the address here to a file.
                 This file is then read by dlltool when generating the
                 reloc section.  Note that the base file is not
                 absolute.  We output the address here to a file.
                 This file is then read by dlltool when generating the
                 reloc section.  Note that the base file is not
-                portable between systems.  We write out a long here,
-                and dlltool reads in a long.  */
-             long addr = (rel->r_vaddr
+                portable between systems.  We write out a bfd_vma here,
+                and dlltool reads in a bfd_vma.  */
+             bfd_vma addr = (rel->r_vaddr
                           - input_section->vma
                           + input_section->output_offset
                           + input_section->output_section->vma);
              if (coff_data (output_bfd)->pe)
                addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
                           - input_section->vma
                           + input_section->output_offset
                           + input_section->output_section->vma);
              if (coff_data (output_bfd)->pe)
                addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
-             if (fwrite (&addr, 1, sizeof (long), (FILE *) info->base_file)
-                 != sizeof (long))
+             if (fwrite (&addr, 1, sizeof (bfd_vma), (FILE *) info->base_file)
+                 != sizeof (bfd_vma))
                {
                  bfd_set_error (bfd_error_system_call);
                  return FALSE;
                {
                  bfd_set_error (bfd_error_system_call);
                  return FALSE;
@@ -2981,11 +3127,10 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
        case bfd_reloc_ok:
          break;
        case bfd_reloc_outofrange:
        case bfd_reloc_ok:
          break;
        case bfd_reloc_outofrange:
-         (*_bfd_error_handler)
-           (_("%s: bad reloc address 0x%lx in section `%s'"),
-            bfd_archive_filename (input_bfd),
-            (unsigned long) rel->r_vaddr,
-            bfd_get_section_name (input_bfd, input_section));
+         _bfd_error_handler
+           /* xgettext: c-format */
+           (_("%pB: bad reloc address %#" PRIx64 " in section `%pA'"),
+            input_bfd, (uint64_t) rel->r_vaddr, input_section);
          return FALSE;
        case bfd_reloc_overflow:
          {
          return FALSE;
        case bfd_reloc_overflow:
          {
@@ -2995,7 +3140,7 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
            if (symndx == -1)
              name = "*ABS*";
            else if (h != NULL)
            if (symndx == -1)
              name = "*ABS*";
            else if (h != NULL)
-             name = h->root.root.string;
+             name = NULL;
            else
              {
                name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
            else
              {
                name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
@@ -3003,10 +3148,10 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
                  return FALSE;
              }
 
                  return FALSE;
              }
 
-           if (! ((*info->callbacks->reloc_overflow)
-                  (info, name, howto->name, (bfd_vma) 0, input_bfd,
-                   input_section, rel->r_vaddr - input_section->vma)))
-             return FALSE;
+           (*info->callbacks->reloc_overflow)
+             (info, (h ? &h->root : NULL), name, howto->name,
+              (bfd_vma) 0, input_bfd, input_section,
+              rel->r_vaddr - input_section->vma);
          }
        }
     }
          }
        }
     }
This page took 0.078582 seconds and 4 git commands to generate.