OSDN Git Service

manually sync from the CVS repository
[pf3gnuchains/pf3gnuchains4x.git] / bfd / cofflink.c
index 1b059f6..3253e5e 100644 (file)
@@ -1,13 +1,13 @@
 /* COFF specific linker code.
-   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   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 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,
 
    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.  */
 
-#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 (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);
@@ -77,7 +79,7 @@ _bfd_coff_link_hash_newfunc (struct bfd_hash_entry *entry,
       /* 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;
@@ -93,10 +95,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 *,
-                                                                  const char *))
+                                                                  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.  */
@@ -107,12 +110,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);
 
-  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,
-                                       _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;
@@ -229,7 +233,7 @@ coff_link_check_ar_symbols (bfd *abfd,
          /* Auto import.  */
          if (!h
              && info->pei386_auto_import
-             && !strncmp (name,"__imp_", 6))
+             && 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
@@ -298,6 +302,11 @@ coff_link_add_symbols (bfd *abfd,
   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);
@@ -308,13 +317,11 @@ coff_link_add_symbols (bfd *abfd,
   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 = 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;
 
@@ -434,18 +441,19 @@ coff_link_add_symbols (bfd *abfd,
          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;
            }
 
@@ -474,20 +482,20 @@ coff_link_add_symbols (bfd *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
                  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
@@ -502,9 +510,8 @@ coff_link_add_symbols (bfd *abfd,
                               && (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
@@ -550,8 +557,8 @@ coff_link_add_symbols (bfd *abfd,
                 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
@@ -567,22 +574,27 @@ coff_link_add_symbols (bfd *abfd,
      optimize the handling of any .stab/.stabstr sections.  */
   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);
@@ -596,7 +608,8 @@ coff_link_add_symbols (bfd *abfd,
 
              if (! _bfd_link_section_stabs (abfd, &table->stab_info,
                                             stab, stabstr,
-                                            &secdata->stab_info))
+                                            &secdata->stab_info,
+                                            &string_offset))
                goto error_return;
            }
        }
@@ -686,7 +699,7 @@ _bfd_coff_final_link (bfd *abfd,
     {
       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)
            {
@@ -707,8 +720,10 @@ _bfd_coff_final_link (bfd *abfd,
              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)
@@ -757,7 +772,7 @@ _bfd_coff_final_link (bfd *abfd,
          the target_index fields are 1 based.  */
       amt = abfd->section_count + 1;
       amt *= sizeof (struct coff_link_section_info);
-      finfo.section_info = bfd_malloc (amt);
+      finfo.section_info = (struct coff_link_section_info *) bfd_malloc (amt);
       if (finfo.section_info == NULL)
        goto error_return;
       for (i = 0; i <= abfd->section_count; i++)
@@ -800,10 +815,12 @@ _bfd_coff_final_link (bfd *abfd,
          BFD_ASSERT (info->relocatable);
          amt = o->reloc_count;
          amt *= sizeof (struct internal_reloc);
-         finfo.section_info[o->target_index].relocs = bfd_malloc (amt);
+         finfo.section_info[o->target_index].relocs =
+              (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 = bfd_malloc (amt);
+         finfo.section_info[o->target_index].rel_hashes =
+              (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;
@@ -836,21 +853,21 @@ _bfd_coff_final_link (bfd *abfd,
 
   /* Allocate some buffers used while linking.  */
   amt = max_sym_count * sizeof (struct internal_syment);
-  finfo.internal_syms = bfd_malloc (amt);
+  finfo.internal_syms = (struct internal_syment *) bfd_malloc (amt);
   amt = max_sym_count * sizeof (asection *);
-  finfo.sec_ptrs = bfd_malloc (amt);
+  finfo.sec_ptrs = (asection **) bfd_malloc (amt);
   amt = max_sym_count * sizeof (long);
-  finfo.sym_indices = bfd_malloc (amt);
-  finfo.outsyms = bfd_malloc ((max_sym_count + 1) * symesz);
+  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_malloc (amt);
-  finfo.contents = bfd_malloc (max_contents_size);
+  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_malloc (amt);
+  finfo.external_relocs = (bfd_byte *) bfd_malloc (amt);
   if (! info->relocatable)
     {
       amt = max_reloc_count * sizeof (struct internal_reloc);
-      finfo.internal_relocs = bfd_malloc (amt);
+      finfo.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)
@@ -879,7 +896,7 @@ _bfd_coff_final_link (bfd *abfd,
 
   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))
@@ -1000,7 +1017,7 @@ _bfd_coff_final_link (bfd *abfd,
         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;
 
@@ -1073,7 +1090,7 @@ _bfd_coff_final_link (bfd *abfd,
     }
 
   /* 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;
@@ -1201,39 +1218,34 @@ process_embedded_commands (bfd *output_bfd,
   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;
+  e = (char *) copy + sec->size;
 
-  for (s = copy;  s < e ; )
+  for (s = (char *) copy; s < e ; )
     {
-      if (s[0]!= '-')
+      if (s[0] != '-')
        {
          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;
-         int had_read = 0;
          int had_exec= 0;
-         int had_shared= 0;
 
          s += 5;
          s = get_name (s, &name);
@@ -1247,10 +1259,8 @@ process_embedded_commands (bfd *output_bfd,
                  had_write = 1;
                  break;
                case 'R':
-                 had_read = 1;
                  break;
                case 'S':
-                 had_shared = 1;
                  break;
                case 'X':
                  had_exec = 1;
@@ -1268,11 +1278,20 @@ process_embedded_commands (bfd *output_bfd,
                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 (strncmp (s,"-stack", 6) == 0)
-       s = dores_com (s+6, output_bfd, 0);
+      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:"))
+       {
+         /* 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++;
@@ -1339,9 +1358,6 @@ _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)
     (bfd *, struct bfd_link_info *, bfd *, asection *,
      struct internal_reloc *, bfd_boolean *);
@@ -1588,10 +1604,10 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
              out to be a duplicate, we pass this address to
              bfd_release.  */
          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;
-         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.  */
@@ -1615,7 +1631,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);
-             *epp = bfd_alloc (input_bfd, amt);
+             *epp = (struct coff_debug_merge_element *)
+                  bfd_alloc (input_bfd, amt);
              if (*epp == NULL)
                return FALSE;
 
@@ -1625,7 +1642,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
                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);
@@ -1680,7 +1697,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *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;
@@ -1920,6 +1937,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *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);
            }
 
@@ -1935,7 +1953,7 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *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
                {
@@ -1970,7 +1988,8 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *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;
 
@@ -2276,16 +2295,18 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
        /* 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;
            }
@@ -2298,8 +2319,8 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *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;
        }
@@ -2424,10 +2445,8 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *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
@@ -2540,7 +2559,7 @@ _bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *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)
@@ -2558,7 +2577,7 @@ _bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *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 relocatable object.  */
   if (! finfo->info->shared
@@ -2609,9 +2628,7 @@ _bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *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?  */
@@ -2715,7 +2732,7 @@ _bfd_coff_reloc_link_order (bfd *output_bfd,
       file_ptr loc;
 
       size = bfd_get_reloc_size (howto);
-      buf = bfd_zmalloc (size);
+      buf = (bfd_byte *) bfd_zmalloc (size);
       if (buf == NULL)
        return FALSE;
 
@@ -2731,7 +2748,7 @@ _bfd_coff_reloc_link_order (bfd *output_bfd,
          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)
@@ -2856,8 +2873,7 @@ _bfd_coff_generic_relocate_section (bfd *output_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
@@ -2918,16 +2934,50 @@ _bfd_coff_generic_relocate_section (bfd *output_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->relocatable)
            {
@@ -2947,16 +2997,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
-                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;
@@ -2977,10 +3027,8 @@ _bfd_coff_generic_relocate_section (bfd *output_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:
          {
@@ -2990,7 +3038,7 @@ _bfd_coff_generic_relocate_section (bfd *output_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);
@@ -2999,8 +3047,9 @@ _bfd_coff_generic_relocate_section (bfd *output_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;
          }
        }