2011-08-08 Tristan Gingold <gingold@adacore.com>
[deliverable/binutils-gdb.git] / bfd / cofflink.c
index 91a382288d62c6eac5dc0b44d9ce9e05a06a5ab4..27257baa9c48490aee28857e0bb927b56f8e69d0 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, 2011 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"
@@ -78,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;
@@ -94,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.  */
@@ -108,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;
@@ -194,7 +197,8 @@ coff_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 static bfd_boolean
 coff_link_check_ar_symbols (bfd *abfd,
                            struct bfd_link_info *info,
-                           bfd_boolean *pneeded)
+                           bfd_boolean *pneeded,
+                           bfd **subsbfd)
 {
   bfd_size_type symesz;
   bfd_byte *esym;
@@ -230,7 +234,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
@@ -240,7 +244,8 @@ coff_link_check_ar_symbols (bfd *abfd,
          if (h != (struct bfd_link_hash_entry *) NULL
              && h->type == bfd_link_hash_undefined)
            {
-             if (! (*info->callbacks->add_archive_element) (info, abfd, name))
+             if (!(*info->callbacks
+                   ->add_archive_element) (info, abfd, name, subsbfd))
                return FALSE;
              *pneeded = TRUE;
              return TRUE;
@@ -264,20 +269,38 @@ coff_link_check_archive_element (bfd *abfd,
                                 struct bfd_link_info *info,
                                 bfd_boolean *pneeded)
 {
-  if (! _bfd_coff_get_external_symbols (abfd))
-    return FALSE;
+  bfd *oldbfd;
+  bfd_boolean needed;
 
-  if (! coff_link_check_ar_symbols (abfd, info, pneeded))
+  if (!_bfd_coff_get_external_symbols (abfd))
     return FALSE;
 
-  if (*pneeded
-      && ! coff_link_add_symbols (abfd, info))
+  oldbfd = abfd;
+  if (!coff_link_check_ar_symbols (abfd, info, pneeded, &abfd))
     return FALSE;
 
-  if ((! info->keep_memory || ! *pneeded)
-      && ! _bfd_coff_free_symbols (abfd))
-    return FALSE;
+  needed = *pneeded;
+  if (needed)
+    {
+      /* Potentially, the add_archive_element hook may have set a
+        substitute BFD for us.  */
+      if (abfd != oldbfd)
+       {
+         if (!info->keep_memory
+             && !_bfd_coff_free_symbols (oldbfd))
+           return FALSE;
+         if (!_bfd_coff_get_external_symbols (abfd))
+           return FALSE;
+       }
+      if (!coff_link_add_symbols (abfd, info))
+       return FALSE;
+    }
 
+  if (!info->keep_memory || !needed)
+    {
+      if (!_bfd_coff_free_symbols (abfd))
+       return FALSE;
+    }
   return TRUE;
 }
 
@@ -299,6 +322,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);
@@ -309,13 +337,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;
 
@@ -366,7 +392,11 @@ coff_link_add_symbols (bfd *abfd,
              section = coff_section_from_bfd_index (abfd, sym.n_scnum);
              if (! obj_pe (abfd))
                value -= section->vma;
-             break;
+             /* Treat a symbol from a discarded section as undefined.  */
+             if (bfd_is_abs_section (section)
+                 || !bfd_is_abs_section (section->output_section))
+               break;
+             /* Fall thru */
 
            case COFF_SYMBOL_UNDEFINED:
              flags = 0;
@@ -435,18 +465,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;
            }
 
@@ -475,20 +506,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
@@ -503,9 +534,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
@@ -551,8 +581,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
@@ -568,7 +598,7 @@ 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 *stabstr;
@@ -581,7 +611,7 @@ coff_link_add_symbols (bfd *abfd,
          asection *stab;
          
          for (stab = abfd->sections; stab; stab = stab->next)
-           if (strncmp (".stab", stab->name, 5) == 0
+           if (CONST_STRNEQ (stab->name, ".stab")
                && (!stab->name[5]
                    || (stab->name[5] == '.' && ISDIGIT (stab->name[6]))))
            {
@@ -693,7 +723,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)
            {
@@ -714,8 +744,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)
@@ -764,7 +796,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++)
@@ -807,10 +839,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;
@@ -843,21 +877,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)
@@ -886,7 +920,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))
@@ -989,8 +1023,7 @@ _bfd_coff_final_link (bfd *abfd,
 
   /* Write out the global symbols.  */
   finfo.failed = FALSE;
-  coff_link_hash_traverse (coff_hash_table (info),
-                          _bfd_coff_write_global_sym, &finfo);
+  bfd_hash_traverse (&info->hash->table, _bfd_coff_write_global_sym, &finfo);
   if (finfo.failed)
     goto error_return;
 
@@ -1007,7 +1040,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;
 
@@ -1080,7 +1113,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;
@@ -1208,39 +1241,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);
@@ -1254,10 +1282,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;
@@ -1275,11 +1301,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++;
@@ -1346,9 +1381,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 *);
@@ -1505,11 +1537,13 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
       /* Skip section symbols for sections which are not going to be
         emitted.  */
       if (!skip
-         && dont_skip_symbol == 0
+         && !dont_skip_symbol
          && isym.n_sclass == C_STAT
          && isym.n_type == T_NULL
-          && isym.n_numaux > 0
-         && (*secpp)->output_section == bfd_abs_section_ptr)
+         && isym.n_numaux > 0
+         && ((*secpp)->output_section == bfd_abs_section_ptr
+             || bfd_section_removed_from_list (output_bfd,
+                                               (*secpp)->output_section)))
        skip = TRUE;
 #endif
 
@@ -1595,10 +1629,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.  */
@@ -1622,7 +1656,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;
 
@@ -1632,7 +1667,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);
@@ -1687,7 +1722,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;
@@ -1927,6 +1962,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);
            }
 
@@ -1942,7 +1978,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
                {
@@ -1977,7 +2013,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;
 
@@ -2283,16 +2320,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;
            }
@@ -2305,8 +2344,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;
        }
@@ -2329,6 +2368,35 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
          if (internal_relocs == NULL)
            return FALSE;
 
+         /* Run through the relocs looking for relocs against symbols
+            coming from discarded sections and complain about them.  */
+         irel = internal_relocs;
+         for (; irel < &internal_relocs[o->reloc_count]; irel++)
+           {
+             struct coff_link_hash_entry *h;
+             asection *ps = NULL;
+             long symndx = irel->r_symndx;
+             if (symndx < 0)
+               continue;
+             h = obj_coff_sym_hashes (input_bfd)[symndx];
+             if (h == NULL)
+               continue;
+             while (h->root.type == bfd_link_hash_indirect
+                    || h->root.type == bfd_link_hash_warning)
+               h = (struct coff_link_hash_entry *) h->root.u.i.link;
+             if (h->root.type == bfd_link_hash_defined
+                 || h->root.type == bfd_link_hash_defweak)
+               ps = h->root.u.def.section;
+             if (ps == NULL)
+               continue;
+             /* Complain if definition comes from an excluded section.  */
+             if (ps->flags & SEC_EXCLUDE)
+               (*finfo->info->callbacks->einfo)
+                 (_("%X`%s' referenced in section `%A' of %B: "
+                    "defined in discarded section `%A' of %B\n"),
+                  h->root.root.string, o, input_bfd, ps, ps->owner);
+           }
+
          /* Call processor specific code to relocate the section
              contents.  */
          if (! bfd_coff_relocate_section (output_bfd, finfo->info,
@@ -2431,10 +2499,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
@@ -2453,11 +2519,12 @@ _bfd_coff_link_input_bfd (struct coff_final_link_info *finfo, bfd *input_bfd)
   return TRUE;
 }
 
-/* Write out a global symbol.  Called via coff_link_hash_traverse.  */
+/* Write out a global symbol.  Called via bfd_hash_traverse.  */
 
 bfd_boolean
-_bfd_coff_write_global_sym (struct coff_link_hash_entry *h, void *data)
+_bfd_coff_write_global_sym (struct bfd_hash_entry *bh, void *data)
 {
+  struct coff_link_hash_entry *h = (struct coff_link_hash_entry *) bh;
   struct coff_final_link_info *finfo = (struct coff_final_link_info *) data;
   bfd *output_bfd;
   struct internal_syment isym;
@@ -2547,7 +2614,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)
@@ -2565,7 +2632,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
@@ -2616,9 +2683,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?  */
@@ -2684,7 +2749,7 @@ _bfd_coff_write_task_globals (struct coff_link_hash_entry *h, void *data)
        case bfd_link_hash_defweak:
          save_global_to_static = finfo->global_to_static;
          finfo->global_to_static = TRUE;
-         rtnval = _bfd_coff_write_global_sym (h, data);
+         rtnval = _bfd_coff_write_global_sym (&h->root.root, data);
          finfo->global_to_static = save_global_to_static;
          break;
        default:
@@ -2722,7 +2787,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;
 
@@ -2738,7 +2803,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)
@@ -2863,8 +2928,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
@@ -2925,16 +2989,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)
            {
@@ -2954,16 +3052,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;
@@ -2984,10 +3082,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:
          {
@@ -2997,7 +3093,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);
@@ -3006,8 +3102,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;
          }
        }
This page took 0.046523 seconds and 4 git commands to generate.