* linker.c (bfd_link_hash_traverse): Follow warning symbol link.
[deliverable/binutils-gdb.git] / bfd / cofflink.c
index ca144cc4929345f8709c94140625b66429b89422..bca136445de141eef3bb77cac9b734139810dad7 100644 (file)
@@ -1,13 +1,13 @@
 /* COFF specific linker code.
    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004 Free Software Foundation, Inc.
+   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)
 {
   memset (&table->stab_info, 0, sizeof (table->stab_info));
-  return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
+  return _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
 }
 
 /* Create a COFF linker hash table.  */
@@ -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;
 
@@ -437,7 +463,7 @@ coff_link_add_symbols (bfd *abfd,
                  || classification == COFF_SYMBOL_PE_SECTION)
              && coff_section_data (abfd, section) != NULL
              && coff_section_data (abfd, section)->comdat != NULL
-             && strncmp (name, "??_", 3) == 0
+             && CONST_STRNEQ (name, "??_")
              && strcmp (name, coff_section_data (abfd, section)->comdat->name) == 0)
            {
              if (*sym_hash == NULL)
@@ -476,20 +502,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
@@ -568,7 +594,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 +607,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 +719,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)
            {
@@ -766,7 +792,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++)
@@ -809,10 +835,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;
@@ -845,21 +873,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)
@@ -888,7 +916,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))
@@ -991,8 +1019,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;
 
@@ -1009,7 +1036,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;
 
@@ -1221,25 +1248,23 @@ process_embedded_commands (bfd *output_bfd,
        free (copy);
       return 0;
     }
-  e = copy + sec->size;
+  e = (char *) copy + sec->size;
 
-  for (s = copy;  s < e ; )
+  for (s = (char *) copy; s < e ; )
     {
-      if (s[0]!= '-')
+      if (s[0] != '-')
        {
          s++;
          continue;
        }
-      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);
@@ -1253,10 +1278,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;
@@ -1274,11 +1297,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++;
@@ -1345,9 +1377,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 *);
@@ -1504,11 +1533,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
 
@@ -1594,10 +1625,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.  */
@@ -1621,7 +1652,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;
 
@@ -1631,7 +1663,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);
@@ -1686,7 +1718,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;
@@ -1926,6 +1958,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);
            }
 
@@ -1941,7 +1974,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
                {
@@ -1976,7 +2009,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;
 
@@ -2330,6 +2364,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,
@@ -2452,11 +2515,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;
@@ -2546,7 +2610,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)
@@ -2681,7 +2745,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:
@@ -2719,7 +2783,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;
 
@@ -2735,7 +2799,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)
@@ -2932,28 +2996,37 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
 
          else if (h->root.type == bfd_link_hash_undefweak)
            {
-              if (h->class == C_NT_WEAK && h->numaux == 1)
+              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
-                  * characteristics IMAGE_WEAK_EXTERN_SEARCH_LIBRARY (2).
-                  * There are no known uses of the other two types of
-                  * weak externals.
-                  */
+                     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 =
-                   input_bfd->tdata.coff_obj_data->sym_hashes[
+                   h->auxbfd->tdata.coff_obj_data->sym_hashes[
                    h->aux->x_sym.x_tagndx.l];
 
-                 sec = h2->root.u.def.section;
-                 val = h2->root.u.def.value + sec->output_section->vma
-                   + sec->output_offset;
+                 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. */
+                /* This is a GNU extension.  */
                val = 0;
            }
 
@@ -2975,16 +3048,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;
@@ -3016,7 +3089,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);
@@ -3025,8 +3098,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.035857 seconds and 4 git commands to generate.