OSDN Git Service

daily update
[pf3gnuchains/pf3gnuchains3x.git] / bfd / cofflink.c
index 4e61388..a29b687 100644 (file)
@@ -1,49 +1,38 @@
 /* COFF specific linker code.
-   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
-   Free Software Foundation, Inc.
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+   2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
-This file is part of BFD, the Binary File Descriptor library.
+   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
-(at your option) any later version.
+   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 3 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-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.  */
+   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., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 /* This file contains the COFF backend linker code.  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.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
-  PARAMS ((bfd *, struct bfd_link_info *));
-static bfd_boolean coff_link_check_archive_element
-  PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean *));
-static bfd_boolean coff_link_check_ar_symbols
-  PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean *));
-static bfd_boolean coff_link_add_symbols
-  PARAMS ((bfd *, struct bfd_link_info *));
-static char *dores_com
-  PARAMS ((char *, bfd *, int));
-static char *get_name
-  PARAMS ((char *, char **));
-static int process_embedded_commands
-  PARAMS ((bfd *, struct bfd_link_info *, bfd *));
-static void mark_relocs
-  PARAMS ((struct coff_final_link_info *, bfd *));
+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);
 
 /* Return TRUE if SYM is a weak, external symbol.  */
 #define IS_WEAK_EXTERNAL(abfd, sym)                    \
@@ -67,10 +56,9 @@ static void mark_relocs
 /* Create an entry in a COFF linker hash table.  */
 
 struct bfd_hash_entry *
-_bfd_coff_link_hash_newfunc (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
+_bfd_coff_link_hash_newfunc (struct bfd_hash_entry *entry,
+                            struct bfd_hash_table *table,
+                            const char *string)
 {
   struct coff_link_hash_entry *ret = (struct coff_link_hash_entry *) entry;
 
@@ -91,7 +79,7 @@ _bfd_coff_link_hash_newfunc (entry, table, string)
       /* 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;
@@ -103,22 +91,21 @@ _bfd_coff_link_hash_newfunc (entry, table, string)
 /* Initialize a COFF linker hash table.  */
 
 bfd_boolean
-_bfd_coff_link_hash_table_init (table, abfd, newfunc)
-     struct coff_link_hash_table *table;
-     bfd *abfd;
-     struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
-                                               struct bfd_hash_table *,
-                                               const char *));
+_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 *,
+                                                                  const char *),
+                               unsigned int entsize)
 {
-  table->stab_info = NULL;
-  return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
+  memset (&table->stab_info, 0, sizeof (table->stab_info));
+  return _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
 }
 
 /* Create a COFF linker hash table.  */
 
 struct bfd_link_hash_table *
-_bfd_coff_link_hash_table_create (abfd)
-     bfd *abfd;
+_bfd_coff_link_hash_table_create (bfd *abfd)
 {
   struct coff_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct coff_link_hash_table);
@@ -126,8 +113,10 @@ _bfd_coff_link_hash_table_create (abfd)
   ret = (struct coff_link_hash_table *) bfd_malloc (amt);
   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;
@@ -138,10 +127,9 @@ _bfd_coff_link_hash_table_create (abfd)
 /* Create an entry in a COFF debug merge hash table.  */
 
 struct bfd_hash_entry *
-_bfd_coff_debug_merge_hash_newfunc (entry, table, string)
-     struct bfd_hash_entry *entry;
-     struct bfd_hash_table *table;
-     const char *string;
+_bfd_coff_debug_merge_hash_newfunc (struct bfd_hash_entry *entry,
+                                   struct bfd_hash_table *table,
+                                   const char *string)
 {
   struct coff_debug_merge_hash_entry *ret =
     (struct coff_debug_merge_hash_entry *) entry;
@@ -171,17 +159,15 @@ _bfd_coff_debug_merge_hash_newfunc (entry, table, string)
    appropriate.  */
 
 bfd_boolean
-_bfd_coff_link_add_symbols (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+_bfd_coff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
 {
   switch (bfd_get_format (abfd))
     {
     case bfd_object:
       return coff_link_add_object_symbols (abfd, info);
     case bfd_archive:
-      return (_bfd_generic_link_add_archive_symbols
-             (abfd, info, coff_link_check_archive_element));
+      return _bfd_generic_link_add_archive_symbols
+       (abfd, info, coff_link_check_archive_element);
     default:
       bfd_set_error (bfd_error_wrong_format);
       return FALSE;
@@ -191,52 +177,17 @@ _bfd_coff_link_add_symbols (abfd, info)
 /* Add symbols from a COFF object file.  */
 
 static bfd_boolean
-coff_link_add_object_symbols (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+coff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 {
   if (! _bfd_coff_get_external_symbols (abfd))
     return FALSE;
   if (! coff_link_add_symbols (abfd, info))
     return FALSE;
 
-  if (! info->keep_memory)
-    {
-      if (! _bfd_coff_free_symbols (abfd))
-       return FALSE;
-    }
-  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
-   _bfd_generic_link_add_archive_symbols.  */
-
-static bfd_boolean
-coff_link_check_archive_element (abfd, info, pneeded)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     bfd_boolean *pneeded;
-{
-  if (! _bfd_coff_get_external_symbols (abfd))
+  if (! info->keep_memory
+      && ! _bfd_coff_free_symbols (abfd))
     return FALSE;
 
-  if (! coff_link_check_ar_symbols (abfd, info, pneeded))
-    return FALSE;
-
-  if (*pneeded)
-    {
-      if (! coff_link_add_symbols (abfd, info))
-       return FALSE;
-    }
-
-  if (! info->keep_memory || ! *pneeded)
-    {
-      if (! _bfd_coff_free_symbols (abfd))
-       return FALSE;
-    }
-
   return TRUE;
 }
 
@@ -244,10 +195,9 @@ coff_link_check_archive_element (abfd, info, pneeded)
    included in the link.  */
 
 static bfd_boolean
-coff_link_check_ar_symbols (abfd, info, pneeded)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     bfd_boolean *pneeded;
+coff_link_check_ar_symbols (bfd *abfd,
+                           struct bfd_link_info *info,
+                           bfd_boolean *pneeded)
 {
   bfd_size_type symesz;
   bfd_byte *esym;
@@ -263,7 +213,7 @@ coff_link_check_ar_symbols (abfd, info, pneeded)
       struct internal_syment sym;
       enum coff_symbol_classification classification;
 
-      bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
+      bfd_coff_swap_sym_in (abfd, esym, &sym);
 
       classification = bfd_coff_classify_symbol (abfd, &sym);
       if (classification == COFF_SYMBOL_GLOBAL
@@ -275,22 +225,17 @@ coff_link_check_ar_symbols (abfd, info, pneeded)
 
          /* 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)
-           {
-             if (!strncmp (name,"__imp_", 6))
-               {
-                 h =
-                    bfd_link_hash_lookup (info->hash, name + 6, FALSE, FALSE,
-                                          TRUE);
-               }
-           }
+         /* Auto import.  */
+         if (!h
+             && info->pei386_auto_import
+             && CONST_STRNEQ (name, "__imp_"))
+           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
@@ -312,12 +257,38 @@ coff_link_check_ar_symbols (abfd, info, pneeded)
   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
+   _bfd_generic_link_add_archive_symbols.  */
+
+static bfd_boolean
+coff_link_check_archive_element (bfd *abfd,
+                                struct bfd_link_info *info,
+                                bfd_boolean *pneeded)
+{
+  if (! _bfd_coff_get_external_symbols (abfd))
+    return FALSE;
+
+  if (! coff_link_check_ar_symbols (abfd, info, pneeded))
+    return FALSE;
+
+  if (*pneeded
+      && ! coff_link_add_symbols (abfd, info))
+    return FALSE;
+
+  if ((! info->keep_memory || ! *pneeded)
+      && ! _bfd_coff_free_symbols (abfd))
+    return FALSE;
+
+  return TRUE;
+}
+
 /* Add all the symbols from an object file to the hash table.  */
 
 static bfd_boolean
-coff_link_add_symbols (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+coff_link_add_symbols (bfd *abfd,
+                      struct bfd_link_info *info)
 {
   unsigned int n_tmask = coff_data (abfd)->local_n_tmask;
   unsigned int n_btshft = coff_data (abfd)->local_n_btshft;
@@ -331,6 +302,11 @@ coff_link_add_symbols (abfd, info)
   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);
@@ -341,13 +317,11 @@ coff_link_add_symbols (abfd, info)
   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 *);
   sym_hash = (struct coff_link_hash_entry **) bfd_zalloc (abfd, amt);
-  if (sym_hash == NULL && symcount != 0)
+  if (sym_hash == NULL)
     goto error_return;
   obj_coff_sym_hashes (abfd) = sym_hash;
 
@@ -361,7 +335,7 @@ coff_link_add_symbols (abfd, info)
       enum coff_symbol_classification classification;
       bfd_boolean copy;
 
-      bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
+      bfd_coff_swap_sym_in (abfd, esym, &sym);
 
       classification = bfd_coff_classify_symbol (abfd, &sym);
       if (classification != COFF_SYMBOL_LOCAL)
@@ -467,18 +441,19 @@ coff_link_add_symbols (abfd, info)
          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
-                 && (*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;
            }
 
@@ -507,20 +482,20 @@ coff_link_add_symbols (abfd, info)
            (*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
                  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
+             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)->class = sym.n_sclass;
+                 (*sym_hash)->symbol_class = sym.n_sclass;
                  if (sym.n_type != T_NULL)
                    {
                      /* We want to warn if the type changed, but not
@@ -535,9 +510,8 @@ coff_link_add_symbols (abfd, info)
                               && (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));
+                         (_("Warning: type of symbol `%s' changed from %d to %d in %B"),
+                          abfd, name, (*sym_hash)->type, sym.n_type);
 
                      /* We don't want to change from a meaningful
                         base type to a null one, but if we know
@@ -564,9 +538,9 @@ coff_link_add_symbols (abfd, info)
                      for (i = 0, eaux = esym + symesz, iaux = alloc;
                           i < sym.n_numaux;
                           i++, eaux += symesz, iaux++)
-                       bfd_coff_swap_aux_in (abfd, (PTR) eaux, sym.n_type,
+                       bfd_coff_swap_aux_in (abfd, eaux, sym.n_type,
                                              sym.n_sclass, (int) i,
-                                             sym.n_numaux, (PTR) iaux);
+                                             sym.n_numaux, iaux);
                      (*sym_hash)->aux = alloc;
                    }
                }
@@ -582,10 +556,9 @@ coff_link_add_symbols (abfd, info)
                 FIXME: This is not at all the right place to do this.
                 For example, it won't help objdump.  This needs to be
                 done when we swap in the section header.  */
-
              BFD_ASSERT ((*sym_hash)->numaux == 1);
-             if (section->_raw_size == 0)
-               section->_raw_size = (*sym_hash)->aux[0].x_scn.x_scnlen;
+             if (section->size == 0)
+               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
@@ -597,30 +570,35 @@ coff_link_add_symbols (abfd, info)
       sym_hash += sym.n_numaux + 1;
     }
 
-  /* If this is a non-traditional, non-relocateable link, try to
+  /* If this is a non-traditional, non-relocatable link, try to
      optimize the handling of any .stab/.stabstr sections.  */
-  if (! info->relocateable
+  if (! info->relocatable
       && ! 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 *stab, *stabstr;
+      asection *stabstr;
 
-      stab = bfd_get_section_by_name (abfd, ".stab");
-      if (stab != NULL)
-       {
-         stabstr = bfd_get_section_by_name (abfd, ".stabstr");
+      stabstr = bfd_get_section_by_name (abfd, ".stabstr");
 
-         if (stabstr != NULL)
+      if (stabstr != NULL)
+       {
+         bfd_size_type string_offset = 0;
+         asection *stab;
+         
+         for (stab = abfd->sections; stab; stab = stab->next)
+           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;
-
-             secdata = coff_section_data (abfd, stab);
+             struct coff_section_tdata *secdata
+               = coff_section_data (abfd, stab);
+             
              if (secdata == NULL)
                {
                  amt = sizeof (struct coff_section_tdata);
-                 stab->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
+                 stab->used_by_bfd = bfd_zalloc (abfd, amt);
                  if (stab->used_by_bfd == NULL)
                    goto error_return;
                  secdata = coff_section_data (abfd, stab);
@@ -630,7 +608,8 @@ coff_link_add_symbols (abfd, info)
 
              if (! _bfd_link_section_stabs (abfd, &table->stab_info,
                                             stab, stabstr,
-                                            &secdata->stab_info))
+                                            &secdata->stab_info,
+                                            &string_offset))
                goto error_return;
            }
        }
@@ -648,9 +627,8 @@ coff_link_add_symbols (abfd, info)
 /* Do the final link step.  */
 
 bfd_boolean
-_bfd_coff_final_link (abfd, info)
-     bfd *abfd;
-     struct bfd_link_info *info;
+_bfd_coff_final_link (bfd *abfd,
+                     struct bfd_link_info *info)
 {
   bfd_size_type symesz;
   struct coff_final_link_info finfo;
@@ -721,7 +699,7 @@ _bfd_coff_final_link (abfd, info)
     {
       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)
            {
@@ -739,17 +717,19 @@ _bfd_coff_final_link (abfd, info)
                  || info->strip == strip_some)
                o->lineno_count += sec->lineno_count;
 
-             if (info->relocateable)
+             if (info->relocatable)
                o->reloc_count += sec->reloc_count;
 
-             if (sec->_raw_size > max_contents_size)
-               max_contents_size = sec->_raw_size;
+             if (sec->rawsize > max_contents_size)
+               max_contents_size = sec->rawsize;
+             if (sec->size > max_contents_size)
+               max_contents_size = sec->size;
              if (sec->lineno_count > max_lineno_count)
                max_lineno_count = sec->lineno_count;
              if (sec->reloc_count > max_reloc_count)
                max_reloc_count = sec->reloc_count;
            }
-         else if (info->relocateable
+         else if (info->relocatable
                   && (p->type == bfd_section_reloc_link_order
                       || p->type == bfd_symbol_reloc_link_order))
            ++o->reloc_count;
@@ -782,9 +762,9 @@ _bfd_coff_final_link (abfd, info)
        }
     }
 
-  /* If doing a relocateable link, allocate space for the pointers we
+  /* If doing a relocatable link, allocate space for the pointers we
      need to keep.  */
-  if (info->relocateable)
+  if (info->relocatable)
     {
       unsigned int i;
 
@@ -830,17 +810,17 @@ _bfd_coff_final_link (abfd, info)
 
             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 relocateable link, which is not the
+            but only when doing a relocatable link, which is not the
             common case.  */
-         BFD_ASSERT (info->relocateable);
+         BFD_ASSERT (info->relocatable);
          amt = o->reloc_count;
          amt *= sizeof (struct internal_reloc);
          finfo.section_info[o->target_index].relocs =
-           (struct internal_reloc *) bfd_malloc (amt);
+              (struct internal_reloc *) bfd_malloc (amt);
          amt = o->reloc_count;
          amt *= sizeof (struct coff_link_hash_entry *);
          finfo.section_info[o->target_index].rel_hashes =
-           (struct coff_link_hash_entry **) bfd_malloc (amt);
+              (struct coff_link_hash_entry **) bfd_malloc (amt);
          if (finfo.section_info[o->target_index].relocs == NULL
              || finfo.section_info[o->target_index].rel_hashes == NULL)
            goto error_return;
@@ -877,14 +857,14 @@ _bfd_coff_final_link (abfd, info)
   amt = max_sym_count * sizeof (asection *);
   finfo.sec_ptrs = (asection **) bfd_malloc (amt);
   amt = max_sym_count * sizeof (long);
-  finfo.sym_indices = (long *) bfd_malloc (amt);
+  finfo.sym_indices = (long int *) bfd_malloc (amt);
   finfo.outsyms = (bfd_byte *) bfd_malloc ((max_sym_count + 1) * symesz);
   amt = max_lineno_count * bfd_coff_linesz (abfd);
   finfo.linenos = (bfd_byte *) bfd_malloc (amt);
   finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
   amt = max_reloc_count * relsz;
   finfo.external_relocs = (bfd_byte *) bfd_malloc (amt);
-  if (! info->relocateable)
+  if (! info->relocatable)
     {
       amt = max_reloc_count * sizeof (struct internal_reloc);
       finfo.internal_relocs = (struct internal_reloc *) bfd_malloc (amt);
@@ -896,7 +876,7 @@ _bfd_coff_final_link (abfd, info)
       || (finfo.linenos == NULL && max_lineno_count > 0)
       || (finfo.contents == NULL && max_contents_size > 0)
       || (finfo.external_relocs == NULL && max_reloc_count > 0)
-      || (! info->relocateable
+      || (! info->relocatable
          && finfo.internal_relocs == NULL
          && max_reloc_count > 0))
     goto error_return;
@@ -916,7 +896,7 @@ _bfd_coff_final_link (abfd, info)
 
   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))
@@ -996,8 +976,8 @@ _bfd_coff_final_link (abfd, info)
       file_ptr pos;
 
       finfo.last_file.n_value = obj_raw_syment_count (abfd);
-      bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
-                            (PTR) finfo.outsyms);
+      bfd_coff_swap_sym_out (abfd, &finfo.last_file,
+                            finfo.outsyms);
 
       pos = obj_sym_filepos (abfd) + finfo.last_file_index * symesz;
       if (bfd_seek (abfd, pos, SEEK_SET) != 0
@@ -1012,8 +992,7 @@ _bfd_coff_final_link (abfd, info)
     {
       finfo.failed = FALSE;
       coff_link_hash_traverse (coff_hash_table (info),
-                              _bfd_coff_write_task_globals,
-                              (PTR) &finfo);
+                              _bfd_coff_write_task_globals, &finfo);
       if (finfo.failed)
        goto error_return;
     }
@@ -1021,8 +1000,7 @@ _bfd_coff_final_link (abfd, info)
   /* Write out the global symbols.  */
   finfo.failed = FALSE;
   coff_link_hash_traverse (coff_hash_table (info),
-                          _bfd_coff_write_global_sym,
-                          (PTR) &finfo);
+                          _bfd_coff_write_global_sym, &finfo);
   if (finfo.failed)
     goto error_return;
 
@@ -1033,7 +1011,7 @@ _bfd_coff_final_link (abfd, info)
       finfo.outsyms = NULL;
     }
 
-  if (info->relocateable && max_output_reloc_count > 0)
+  if (info->relocatable && 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
@@ -1064,13 +1042,30 @@ _bfd_coff_final_link (abfd, info)
                  BFD_ASSERT ((*rel_hash)->indx >= 0);
                  irel->r_symndx = (*rel_hash)->indx;
                }
-             bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
+             bfd_coff_swap_reloc_out (abfd, irel, erel);
            }
 
-         if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
-             || (bfd_bwrite ((PTR) external_relocs,
-                            (bfd_size_type) relsz * o->reloc_count, abfd)
-                 != (bfd_size_type) relsz * o->reloc_count))
+         if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0)
+           goto error_return;
+         if (obj_pe (abfd) && o->reloc_count >= 0xffff)
+           {
+             /* In PE COFF, write the count of relocs as the first
+                reloc.  The header overflow bit will be set
+                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;
+             bfd_coff_swap_reloc_out (abfd, (PTR) &incount, (PTR) excount);
+             if (bfd_bwrite (excount, relsz, abfd) != relsz)
+               /* We'll leak, but it's an error anyway. */
+               goto error_return;
+             free (excount);
+           }
+         if (bfd_bwrite (external_relocs,
+                         (bfd_size_type) relsz * o->reloc_count, abfd)
+             != (bfd_size_type) relsz * o->reloc_count)
            goto error_return;
        }
 
@@ -1095,7 +1090,7 @@ _bfd_coff_final_link (abfd, info)
     }
 
   /* If we have optimized stabs strings, output them.  */
-  if (coff_hash_table (info)->stab_info != NULL)
+  if (coff_hash_table (info)->stab_info.stabstr != NULL)
     {
       if (! _bfd_write_stab_strings (abfd, &coff_hash_table (info)->stab_info))
        return FALSE;
@@ -1175,17 +1170,15 @@ _bfd_coff_final_link (abfd, info)
   return FALSE;
 }
 
-/* parse out a -heap <reserved>,<commit> line */
+/* Parse out a -heap <reserved>,<commit> line.  */
 
 static char *
-dores_com (ptr, output_bfd, heap)
-     char *ptr;
-     bfd *output_bfd;
-     int heap;
+dores_com (char *ptr, bfd *output_bfd, int heap)
 {
   if (coff_data(output_bfd)->pe)
     {
       int val = strtoul (ptr, &ptr, 0);
+
       if (heap)
        pe_data(output_bfd)->pe_opthdr.SizeOfHeapReserve = val;
       else
@@ -1203,9 +1196,8 @@ dores_com (ptr, output_bfd, heap)
   return ptr;
 }
 
-static char *get_name(ptr, dst)
-char *ptr;
-char **dst;
+static char *
+get_name (char *ptr, char **dst)
 {
   while (*ptr == ' ')
     ptr++;
@@ -1216,85 +1208,91 @@ char **dst;
   return ptr+1;
 }
 
-/* Process any magic embedded commands in a section called .drectve */
+/* Process any magic embedded commands in a section called .drectve */
 
 static int
-process_embedded_commands (output_bfd, info,  abfd)
-     bfd *output_bfd;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     bfd *abfd;
+process_embedded_commands (bfd *output_bfd,
+                          struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                          bfd *abfd)
 {
   asection *sec = bfd_get_section_by_name (abfd, ".drectve");
   char *s;
   char *e;
-  char *copy;
+  bfd_byte *copy;
+
   if (!sec)
     return 1;
 
-  copy = bfd_malloc (sec->_raw_size);
-  if (!copy)
-    return 0;
-  if (! bfd_get_section_contents(abfd, sec, copy, (bfd_vma) 0, sec->_raw_size))
+  if (!bfd_malloc_and_get_section (abfd, sec, &copy))
     {
-      free (copy);
+      if (copy != NULL)
+       free (copy);
       return 0;
     }
-  e = copy + sec->_raw_size;
-  for (s = copy;  s < e ; )
+  e = (char *) copy + sec->size;
+
+  for (s = (char *) copy; s < e ; )
     {
-      if (s[0]!= '-') {
-       s++;
-       continue;
-      }
-      if (strncmp (s,"-attr", 5) == 0)
+      if (s[0] != '-')
+       {
+         s++;
+         continue;
+       }
+      if (CONST_STRNEQ (s, "-attr"))
        {
          char *name;
          char *attribs;
          asection *asec;
-
          int loop = 1;
          int had_write = 0;
-         int had_read = 0;
          int had_exec= 0;
-         int had_shared= 0;
+
          s += 5;
-         s = get_name(s, &name);
-         s = get_name(s, &attribs);
-         while (loop) {
-           switch (*attribs++)
-             {
-             case 'W':
-               had_write = 1;
-               break;
-             case 'R':
-               had_read = 1;
-               break;
-             case 'S':
-               had_shared = 1;
-               break;
-             case 'X':
-               had_exec = 1;
-               break;
-             default:
-               loop = 0;
-             }
-         }
+         s = get_name (s, &name);
+         s = get_name (s, &attribs);
+
+         while (loop)
+           {
+             switch (*attribs++)
+               {
+               case 'W':
+                 had_write = 1;
+                 break;
+               case 'R':
+                 break;
+               case 'S':
+                 break;
+               case 'X':
+                 had_exec = 1;
+                 break;
+               default:
+                 loop = 0;
+               }
+           }
          asec = bfd_get_section_by_name (abfd, name);
-         if (asec) {
-           if (had_exec)
-             asec->flags |= SEC_CODE;
-           if (!had_write)
-             asec->flags |= SEC_READONLY;
-         }
-       }
-      else if (strncmp (s,"-heap", 5) == 0)
-       {
-         s = dores_com (s+5, output_bfd, 1);
+         if (asec)
+           {
+             if (had_exec)
+               asec->flags |= SEC_CODE;
+             if (!had_write)
+               asec->flags |= SEC_READONLY;
+           }
        }
-      else if (strncmp (s,"-stack", 6) == 0)
+      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);
+
+      /* GNU extension for aligned commons.  */
+      else if (CONST_STRNEQ (s, "-aligncomm:"))
        {
-         s = dores_com (s+6, output_bfd, 0);
+         /* 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++;
     }
@@ -1305,13 +1303,10 @@ process_embedded_commands (output_bfd, info,  abfd)
 /* Place a marker against all symbols which are used by relocations.
    This marker can be picked up by the 'do we skip this symbol ?'
    loop in _bfd_coff_link_input_bfd() and used to prevent skipping
-   that symbol.
-   */
+   that symbol.  */
 
 static void
-mark_relocs (finfo, input_bfd)
-     struct coff_final_link_info *     finfo;
-     bfd *                             input_bfd;
+mark_relocs (struct coff_final_link_info *finfo, bfd *input_bfd)
 {
   asection * a;
 
@@ -1334,8 +1329,8 @@ mark_relocs (finfo, input_bfd)
       internal_relocs = _bfd_coff_read_internal_relocs
        (input_bfd, a, FALSE,
         finfo->external_relocs,
-        finfo->info->relocateable,
-        (finfo->info->relocateable
+        finfo->info->relocatable,
+        (finfo->info->relocatable
          ? (finfo->section_info[ a->output_section->target_index ].relocs + a->output_section->reloc_count)
          : finfo->internal_relocs)
        );
@@ -1349,12 +1344,9 @@ mark_relocs (finfo, input_bfd)
       /* Place a mark in the sym_indices array (whose entries have
         been initialised to 0) for all of the symbols that are used
         in the relocation table.  This will then be picked up in the
-        skip/don't pass */
-
+        skip/don't-skip pass.  */
       for (; irel < irelend; irel++)
-       {
-         finfo->sym_indices[ irel->r_symndx ] = -1;
-       }
+       finfo->sym_indices[ irel->r_symndx ] = -1;
     }
 }
 
@@ -1362,18 +1354,13 @@ mark_relocs (finfo, input_bfd)
    handles all the sections and relocations of the input file at once.  */
 
 bfd_boolean
-_bfd_coff_link_input_bfd (finfo, input_bfd)
-     struct coff_final_link_info *finfo;
-     bfd *input_bfd;
+_bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, 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;
-#if 0
-  unsigned int n_btmask = coff_data (input_bfd)->local_n_btmask;
-#endif
   bfd_boolean (*adjust_symndx)
-    PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
-            struct internal_reloc *, bfd_boolean *));
+    (bfd *, struct bfd_link_info *, bfd *, asection *,
+     struct internal_reloc *, bfd_boolean *);
   bfd *output_bfd;
   const char *strings;
   bfd_size_type syment_base;
@@ -1419,20 +1406,18 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
   output_index = syment_base;
   outsym = finfo->outsyms;
 
-  if (coff_data (output_bfd)->pe)
-    {
-      if (! process_embedded_commands (output_bfd, finfo->info, input_bfd))
-       return FALSE;
-    }
+  if (coff_data (output_bfd)->pe
+      && ! process_embedded_commands (output_bfd, finfo->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 */
+  /* 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->relocateable)
+      && finfo->info->relocatable)
     {
-      /* mark the symbol array as 'not-used' */
+      /* Mark the symbol array as 'not-used'.  */
       memset (indexp, 0, obj_raw_syment_count (input_bfd) * sizeof * indexp);
 
       mark_relocs (finfo, input_bfd);
@@ -1447,7 +1432,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
       bfd_boolean dont_skip_symbol;
       int add;
 
-      bfd_coff_swap_sym_in (input_bfd, (PTR) esym, (PTR) isymp);
+      bfd_coff_swap_sym_in (input_bfd, esym, isymp);
 
       /* Make a copy of *isymp so that the relocate_section function
         always sees the original values.  This is more reliable than
@@ -1477,7 +1462,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
          relocation.  */
       if ((finfo->info->strip != strip_none
           || finfo->info->discard != discard_none)
-         && finfo->info->relocateable)
+         && finfo->info->relocatable)
        dont_skip_symbol = *indexp;
       else
        dont_skip_symbol = FALSE;
@@ -1529,13 +1514,14 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
       /* Skip section symbols for sections which are not going to be
         emitted.  */
       if (!skip
+         && !dont_skip_symbol
          && isym.n_sclass == C_STAT
          && isym.n_type == T_NULL
-          && isym.n_numaux > 0)
-        {
-          if ((*secpp)->output_section == bfd_abs_section_ptr)
-            skip = TRUE;
-        }
+         && 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
@@ -1623,13 +1609,13 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
          mt = (struct coff_debug_merge_type *) bfd_alloc (input_bfd, amt);
          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
              entries.  */
-         bfd_coff_swap_aux_in (input_bfd, (PTR) (esym + isymesz),
+         bfd_coff_swap_aux_in (input_bfd, (esym + isymesz),
                                isym.n_type, isym.n_sclass, 0, isym.n_numaux,
-                               (PTR) &aux);
+                               &aux);
 
          /* Gather the elements.  */
          epp = &mt->elements;
@@ -1644,11 +1630,11 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
              char elebuf[SYMNMLEN + 1];
              char *name_copy;
 
-             bfd_coff_swap_sym_in (input_bfd, (PTR) esl, (PTR) islp);
+             bfd_coff_swap_sym_in (input_bfd, esl, islp);
 
              amt = sizeof (struct coff_debug_merge_element);
-             *epp = ((struct coff_debug_merge_element *)
-                     bfd_alloc (input_bfd, amt));
+             *epp = (struct coff_debug_merge_element *)
+                  bfd_alloc (input_bfd, amt);
              if (*epp == NULL)
                return FALSE;
 
@@ -1673,16 +1659,15 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
                  union internal_auxent eleaux;
                  long indx;
 
-                 bfd_coff_swap_aux_in (input_bfd, (PTR) (esl + isymesz),
+                 bfd_coff_swap_aux_in (input_bfd, (esl + isymesz),
                                        islp->n_type, islp->n_sclass, 0,
-                                       islp->n_numaux, (PTR) &eleaux);
+                                       islp->n_numaux, &eleaux);
                  indx = eleaux.x_sym.x_tagndx.l;
 
                  /* FIXME: If this tagndx entry refers to a symbol
                     defined later in this file, we just ignore it.
                     Handling this correctly would be tedious, and may
                     not be required.  */
-
                  if (indx > 0
                      && (indx
                          < ((esym -
@@ -1705,7 +1690,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
              type.  We always output the type if it has no elements,
              for simplicity.  */
          if (mt->elements == NULL)
-           bfd_release (input_bfd, (PTR) mt);
+           bfd_release (input_bfd, mt);
          else
            {
              struct coff_debug_merge_type *mtl;
@@ -1714,7 +1699,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
                {
                  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;
@@ -1741,7 +1726,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
              else
                {
                  /* This is a redefinition which can be merged.  */
-                 bfd_release (input_bfd, (PTR) mt);
+                 bfd_release (input_bfd, mt);
                  *indexp = mtl->indx;
                  add = (eslend - esym) / isymesz;
                  skip = TRUE;
@@ -1765,8 +1750,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
                 bfd_coff_symname_in_debug.  That is only true for
                 XCOFF, and XCOFF requires different linking code
                 anyhow.  */
-             name = _bfd_coff_internal_syment_name (input_bfd, &isym,
-                                                    (char *) NULL);
+             name = _bfd_coff_internal_syment_name (input_bfd, &isym, NULL);
              if (name == NULL)
                return FALSE;
              indx = _bfd_stringtab_add (finfo->strtab, name, hash, copy);
@@ -1839,7 +1823,6 @@ _bfd_coff_link_input_bfd (finfo, 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.  */
-
              if (finfo->last_file_index != -1
                  && finfo->last_file.n_value != (bfd_vma) output_index)
                {
@@ -1850,11 +1833,11 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
                    {
                      /* The last C_FILE symbol is in this input file.  */
                      bfd_coff_swap_sym_out (output_bfd,
-                                            (PTR) &finfo->last_file,
-                                            (PTR) (finfo->outsyms
-                                                   + ((finfo->last_file_index
-                                                       - syment_base)
-                                                      * osymesz)));
+                                            &finfo->last_file,
+                                            (finfo->outsyms
+                                             + ((finfo->last_file_index
+                                                 - syment_base)
+                                                * osymesz)));
                    }
                  else
                    {
@@ -1864,8 +1847,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
                         symbol.  We need to write it out again.  We
                         borrow *outsym temporarily.  */
                      bfd_coff_swap_sym_out (output_bfd,
-                                            (PTR) &finfo->last_file,
-                                            (PTR) outsym);
+                                            &finfo->last_file, outsym);
                      pos = obj_sym_filepos (output_bfd);
                      pos += finfo->last_file_index * osymesz;
                      if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
@@ -1885,8 +1867,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
            isym.n_sclass = C_STAT;
 
          /* Output the symbol.  */
-
-         bfd_coff_swap_sym_out (output_bfd, (PTR) &isym, (PTR) outsym);
+         bfd_coff_swap_sym_out (output_bfd, &isym, outsym);
 
          *indexp = output_index;
 
@@ -1926,13 +1907,13 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
   /* Fix up the aux entries.  This must be done in a separate pass,
      because we don't know the correct symbol indices until we have
      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;
   sym_hash = obj_coff_sym_hashes (input_bfd);
   outsym = finfo->outsyms;
+
   while (esym < esym_end)
     {
       int add;
@@ -1958,6 +1939,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
                  generate two symbols with the same name, but only one
                  will have aux entries.  */
              BFD_ASSERT (isymp->n_numaux == 0
+                         || h->numaux == 0
                          || h->numaux == isymp->n_numaux);
            }
 
@@ -1973,13 +1955,12 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
              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
                {
-                 bfd_coff_swap_aux_in (input_bfd, (PTR) esym, isymp->n_type,
-                                       isymp->n_sclass, i, isymp->n_numaux,
-                                       (PTR) &aux);
+                 bfd_coff_swap_aux_in (input_bfd, esym, isymp->n_type,
+                                       isymp->n_sclass, i, isymp->n_numaux, &aux);
                  auxp = &aux;
                }
 
@@ -2009,7 +1990,8 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
                      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;
 
@@ -2072,18 +2054,19 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
                          if ((bfd_size_type) finfo->last_bf_index
                              >= syment_base)
                            {
-                             PTR auxout;
+                             void *auxout;
 
                              /* The last .bf symbol is in this input
                                 file.  This will only happen if the
                                 assembler did not set up the .bf
                                 endndx symbols correctly.  */
-                             auxout = (PTR) (finfo->outsyms
-                                             + ((finfo->last_bf_index
-                                                 - syment_base)
-                                                * osymesz));
+                             auxout = (finfo->outsyms
+                                       + ((finfo->last_bf_index
+                                           - syment_base)
+                                          * osymesz));
+
                              bfd_coff_swap_aux_out (output_bfd,
-                                                    (PTR) &finfo->last_bf,
+                                                    &finfo->last_bf,
                                                     isymp->n_type,
                                                     isymp->n_sclass,
                                                     0, isymp->n_numaux,
@@ -2099,11 +2082,11 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
                                  temporarily.  FIXME: This case should
                                  be made faster.  */
                              bfd_coff_swap_aux_out (output_bfd,
-                                                    (PTR) &finfo->last_bf,
+                                                    &finfo->last_bf,
                                                     isymp->n_type,
                                                     isymp->n_sclass,
                                                     0, isymp->n_numaux,
-                                                    (PTR) outsym);
+                                                    outsym);
                              pos = obj_sym_filepos (output_bfd);
                              pos += finfo->last_bf_index * osymesz;
                              if (bfd_seek (output_bfd, pos, SEEK_SET) != 0
@@ -2130,9 +2113,9 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
 
              if (h == NULL)
                {
-                 bfd_coff_swap_aux_out (output_bfd, (PTR) auxp, isymp->n_type,
+                 bfd_coff_swap_aux_out (output_bfd, auxp, isymp->n_type,
                                         isymp->n_sclass, i, isymp->n_numaux,
-                                        (PTR) outsym);
+                                        outsym);
                  outsym += osymesz;
                }
 
@@ -2186,7 +2169,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
            {
              struct internal_lineno iline;
 
-             bfd_coff_swap_lineno_in (input_bfd, (PTR) eline, (PTR) &iline);
+             bfd_coff_swap_lineno_in (input_bfd, eline, &iline);
 
              if (iline.l_lnno != 0)
                iline.l_addr.l_paddr += offset;
@@ -2222,27 +2205,26 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
                         of the line numbers rather than an absolute
                         file index.  */
                      bfd_coff_swap_sym_in (output_bfd,
-                                           (PTR) (finfo->outsyms
-                                                  + ((indx - syment_base)
-                                                     * osymesz)),
-                                           (PTR) &is);
+                                           (finfo->outsyms
+                                            + ((indx - syment_base)
+                                               * osymesz)), &is);
                      if ((ISFCN (is.n_type)
                           || is.n_sclass == C_BLOCK)
                          && is.n_numaux >= 1)
                        {
-                         PTR auxptr;
+                         void *auxptr;
 
-                         auxptr = (PTR) (finfo->outsyms
-                                         + ((indx - syment_base + 1)
-                                            * osymesz));
+                         auxptr = (finfo->outsyms
+                                   + ((indx - syment_base + 1)
+                                      * osymesz));
                          bfd_coff_swap_aux_in (output_bfd, auxptr,
                                                is.n_type, is.n_sclass,
-                                               0, is.n_numaux, (PTR) &ia);
+                                               0, is.n_numaux, &ia);
                          ia.x_sym.x_fcnary.x_fcn.x_lnnoptr =
                            (o->output_section->line_filepos
                             + o->output_section->lineno_count * linesz
                             + eline - finfo->linenos);
-                         bfd_coff_swap_aux_out (output_bfd, (PTR) &ia,
+                         bfd_coff_swap_aux_out (output_bfd, &ia,
                                                 is.n_type, is.n_sclass, 0,
                                                 is.n_numaux, auxptr);
                        }
@@ -2255,8 +2237,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
 
              if (!skipping)
                {
-                 bfd_coff_swap_lineno_out (output_bfd, (PTR) &iline,
-                                           (PTR) oeline);
+                 bfd_coff_swap_lineno_out (output_bfd, &iline, oeline);
                  oeline += linesz;
                }
            }
@@ -2280,10 +2261,10 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
       && (bfd_size_type) finfo->last_file_index >= syment_base)
     {
       finfo->last_file.n_value = output_index;
-      bfd_coff_swap_sym_out (output_bfd, (PTR) &finfo->last_file,
-                            (PTR) (finfo->outsyms
-                                   + ((finfo->last_file_index - syment_base)
-                                      * osymesz)));
+      bfd_coff_swap_sym_out (output_bfd, &finfo->last_file,
+                            (finfo->outsyms
+                             + ((finfo->last_file_index - syment_base)
+                                * osymesz)));
     }
 
   /* Write the modified symbols to the output file.  */
@@ -2313,21 +2294,21 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
       struct coff_section_tdata *secdata;
 
       if (! o->linker_mark)
-       {
-         /* This section was omitted from the link.  */
-         continue;
-       }
+       /* This section was omitted from the link.  */
+       continue;
+
+      if ((o->flags & SEC_LINKER_CREATED) != 0)
+       continue;
 
       if ((o->flags & SEC_HAS_CONTENTS) == 0
-         || (o->_raw_size == 0 && (o->flags & SEC_RELOC) == 0))
+         || (o->size == 0 && (o->flags & SEC_RELOC) == 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)
+               (_("%B: relocs in section `%A', but it has no contents"),
+                input_bfd, o);
              bfd_set_error (bfd_error_no_contents);
              return FALSE;
            }
@@ -2340,8 +2321,8 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
        contents = secdata->contents;
       else
        {
-         if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
-                                         (file_ptr) 0, o->_raw_size))
+         bfd_size_type x = o->rawsize ? o->rawsize : o->size;
+         if (! bfd_get_section_contents (input_bfd, o, finfo->contents, 0, x))
            return FALSE;
          contents = finfo->contents;
        }
@@ -2356,8 +2337,8 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
          target_index = o->output_section->target_index;
          internal_relocs = (_bfd_coff_read_internal_relocs
                             (input_bfd, o, FALSE, finfo->external_relocs,
-                             finfo->info->relocateable,
-                             (finfo->info->relocateable
+                             finfo->info->relocatable,
+                             (finfo->info->relocatable
                               ? (finfo->section_info[target_index].relocs
                                  + o->output_section->reloc_count)
                               : finfo->internal_relocs)));
@@ -2374,7 +2355,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
                                           finfo->sec_ptrs))
            return FALSE;
 
-         if (finfo->info->relocateable)
+         if (finfo->info->relocatable)
            {
              bfd_vma offset;
              struct internal_reloc *irelend;
@@ -2393,7 +2374,6 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
                  *rel_hash = NULL;
 
                  /* Adjust the reloc address and symbol index.  */
-
                  irel->r_vaddr += offset;
 
                  if (irel->r_symndx == -1)
@@ -2444,7 +2424,6 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
                              stripping.  This should have been handled
                             by the 'dont_skip_symbol' code in the while
                             loop at the top of this function.  */
-
                          is = finfo->internal_syms + irel->r_symndx;
 
                          name = (_bfd_coff_internal_syment_name
@@ -2468,10 +2447,8 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
       if (secdata == NULL || secdata->stab_info == NULL)
        {
          file_ptr loc = o->output_offset * bfd_octets_per_byte (output_bfd);
-         bfd_size_type amt = (o->_cooked_size != 0
-                              ? o->_cooked_size : o->_raw_size);
          if (! bfd_set_section_contents (output_bfd, o->output_section,
-                                         contents, loc, amt))
+                                         contents, loc, o->size))
            return FALSE;
        }
       else
@@ -2483,11 +2460,9 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
        }
     }
 
-  if (! finfo->info->keep_memory)
-    {
-      if (! _bfd_coff_free_symbols (input_bfd))
-       return FALSE;
-    }
+  if (! finfo->info->keep_memory
+      && ! _bfd_coff_free_symbols (input_bfd))
+    return FALSE;
 
   return TRUE;
 }
@@ -2495,9 +2470,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
 /* Write out a global symbol.  Called via coff_link_hash_traverse.  */
 
 bfd_boolean
-_bfd_coff_write_global_sym (h, data)
-     struct coff_link_hash_entry *h;
-     PTR data;
+_bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *data)
 {
   struct coff_final_link_info *finfo = (struct coff_final_link_info *) data;
   bfd *output_bfd;
@@ -2588,7 +2561,7 @@ _bfd_coff_write_global_sym (h, data)
       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)
@@ -2606,17 +2579,17 @@ _bfd_coff_write_global_sym (h, data)
       isym.n_sclass = C_STAT;
     }
 
-  /* When a weak symbol is not overriden by a strong one,
+  /* When a weak symbol is not overridden by a strong one,
      turn it into an external symbol when not building a
-     shared or relocateable object.  */
+     shared or relocatable object.  */
   if (! finfo->info->shared
-      && ! finfo->info->relocateable
+      && ! finfo->info->relocatable
       && IS_WEAK_EXTERNAL (finfo->output_bfd, isym))
     isym.n_sclass = C_EXT;
 
   isym.n_numaux = h->numaux;
 
-  bfd_coff_swap_sym_out (output_bfd, (PTR) &isym, (PTR) finfo->outsyms);
+  bfd_coff_swap_sym_out (output_bfd, &isym, finfo->outsyms);
 
   symesz = bfd_coff_symesz (output_bfd);
 
@@ -2657,16 +2630,13 @@ _bfd_coff_write_global_sym (h, data)
          sec = h->root.u.def.section->output_section;
          if (sec != NULL)
            {
-             auxp->x_scn.x_scnlen = (sec->_cooked_size != 0
-                                     ? sec->_cooked_size
-                                     : sec->_raw_size);
+             auxp->x_scn.x_scnlen = sec->size;
 
              /* For PE, an overflow on the final link reportedly does
                  not matter.  FIXME: Why not?  */
-
              if (sec->reloc_count > 0xffff
                  && (! obj_pe (output_bfd)
-                     || finfo->info->relocateable))
+                     || finfo->info->relocatable))
                (*_bfd_error_handler)
                  (_("%s: %s: reloc overflow: 0x%lx > 0xffff"),
                   bfd_get_filename (output_bfd),
@@ -2675,7 +2645,7 @@ _bfd_coff_write_global_sym (h, data)
 
              if (sec->lineno_count > 0xffff
                  && (! obj_pe (output_bfd)
-                     || finfo->info->relocateable))
+                     || finfo->info->relocatable))
                (*_bfd_error_handler)
                  (_("%s: warning: %s: line number overflow: 0x%lx > 0xffff"),
                   bfd_get_filename (output_bfd),
@@ -2690,9 +2660,9 @@ _bfd_coff_write_global_sym (h, data)
            }
        }
 
-      bfd_coff_swap_aux_out (output_bfd, (PTR) auxp, isym.n_type,
+      bfd_coff_swap_aux_out (output_bfd, auxp, isym.n_type,
                             isym.n_sclass, (int) i, isym.n_numaux,
-                            (PTR) finfo->outsyms);
+                            finfo->outsyms);
       if (bfd_bwrite (finfo->outsyms, symesz, output_bfd) != symesz)
        {
          finfo->failed = TRUE;
@@ -2709,9 +2679,7 @@ _bfd_coff_write_global_sym (h, data)
    the dirty work, if the symbol we are processing needs conversion.  */
 
 bfd_boolean
-_bfd_coff_write_task_globals (h, data)
-     struct coff_link_hash_entry *h;
-     PTR data;
+_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;
   bfd_boolean rtnval = TRUE;
@@ -2741,11 +2709,10 @@ _bfd_coff_write_task_globals (h, data)
 /* Handle a link order which is supposed to generate a reloc.  */
 
 bfd_boolean
-_bfd_coff_reloc_link_order (output_bfd, finfo, output_section, link_order)
-     bfd *output_bfd;
-     struct coff_final_link_info *finfo;
-     asection *output_section;
-     struct bfd_link_order *link_order;
+_bfd_coff_reloc_link_order (bfd *output_bfd,
+                           struct coff_final_link_info *finfo,
+                           asection *output_section,
+                           struct bfd_link_order *link_order)
 {
   reloc_howto_type *howto;
   struct internal_reloc *irel;
@@ -2783,7 +2750,7 @@ _bfd_coff_reloc_link_order (output_bfd, finfo, output_section, link_order)
          abort ();
        case bfd_reloc_overflow:
          if (! ((*finfo->info->callbacks->reloc_overflow)
-                (finfo->info,
+                (finfo->info, NULL,
                  (link_order->type == bfd_section_reloc_link_order
                   ? bfd_section_name (output_bfd,
                                       link_order->u.reloc.p->u.section)
@@ -2797,7 +2764,7 @@ _bfd_coff_reloc_link_order (output_bfd, finfo, output_section, link_order)
          break;
        }
       loc = link_order->offset * bfd_octets_per_byte (output_bfd);
-      ok = bfd_set_section_contents (output_bfd, output_section, (PTR) buf,
+      ok = bfd_set_section_contents (output_bfd, output_section, buf,
                                      loc, size);
       free (buf);
       if (! ok)
@@ -2806,7 +2773,6 @@ _bfd_coff_reloc_link_order (output_bfd, finfo, output_section, link_order)
 
   /* 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
          + output_section->reloc_count);
   rel_hash_ptr = (finfo->section_info[output_section->target_index].rel_hashes
@@ -2865,7 +2831,6 @@ _bfd_coff_reloc_link_order (output_bfd, finfo, output_section, link_order)
      routines anyhow.  r_extern is only used for ECOFF.  */
 
   /* FIXME: What is the right value for r_offset?  Is zero OK?  */
-
   ++output_section->reloc_count;
 
   return TRUE;
@@ -2875,17 +2840,14 @@ _bfd_coff_reloc_link_order (output_bfd, finfo, output_section, link_order)
    simple relocs.  */
 
 bfd_boolean
-_bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
-                                   input_section, contents, relocs, syms,
-                                   sections)
-     bfd *output_bfd;
-     struct bfd_link_info *info;
-     bfd *input_bfd;
-     asection *input_section;
-     bfd_byte *contents;
-     struct internal_reloc *relocs;
-     struct internal_syment *syms;
-     asection **sections;
+_bfd_coff_generic_relocate_section (bfd *output_bfd,
+                                   struct bfd_link_info *info,
+                                   bfd *input_bfd,
+                                   asection *input_section,
+                                   bfd_byte *contents,
+                                   struct internal_reloc *relocs,
+                                   struct internal_syment *syms,
+                                   asection **sections)
 {
   struct internal_reloc *rel;
   struct internal_reloc *relend;
@@ -2913,8 +2875,7 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
               || (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);
+           ("%B: illegal symbol index %ld in relocs", input_bfd, symndx);
          return FALSE;
        }
       else
@@ -2927,7 +2888,6 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
          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
@@ -2938,13 +2898,13 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
       if (howto == NULL)
        return FALSE;
 
-      /* If we are doing a relocateable link, then we can just ignore
+      /* 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 relocateable link,
+         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 (info->relocateable)
+         if (info->relocatable)
            continue;
          if (sym != NULL && sym->n_scnum != 0)
            addend += sym->n_value;
@@ -2976,18 +2936,52 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
          if (h->root.type == bfd_link_hash_defined
              || h->root.type == bfd_link_hash_defweak)
            {
+             /* Defined weak symbols are a GNU extension. */
              asection *sec;
 
              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)
-           val = 0;
+           {
+              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. */
+                 asection *sec;
+                 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 (! info->relocateable)
+         else if (! info->relocatable)
            {
              if (! ((*info->callbacks->undefined_symbol)
                     (info, h->root.root.string, input_bfd, input_section,
@@ -3005,16 +2999,16 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_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
-                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;
-             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;
@@ -3035,10 +3029,8 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
          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));
+           (_("%B: bad reloc address 0x%lx in section `%A'"),
+            input_bfd, input_section, (unsigned long) rel->r_vaddr);
          return FALSE;
        case bfd_reloc_overflow:
          {
@@ -3048,7 +3040,7 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
            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);
@@ -3057,8 +3049,9 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
              }
 
            if (! ((*info->callbacks->reloc_overflow)
-                  (info, name, howto->name, (bfd_vma) 0, input_bfd,
-                   input_section, rel->r_vaddr - input_section->vma)))
+                  (info, (h ? &h->root : NULL), name, howto->name,
+                   (bfd_vma) 0, input_bfd, input_section,
+                   rel->r_vaddr - input_section->vma)))
              return FALSE;
          }
        }