* linker.c (bfd_link_hash_traverse): Follow warning symbol link.
[deliverable/binutils-gdb.git] / bfd / cofflink.c
index 12a693e0edad2006252900cab3015d6af188a59b..bca136445de141eef3bb77cac9b734139810dad7 100644 (file)
@@ -1,6 +1,6 @@
 /* COFF specific linker code.
    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004, 2005, 2006, 2007, 2008, 2009 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.
@@ -197,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;
@@ -243,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;
@@ -267,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;
 }
 
@@ -999,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;
 
@@ -1514,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
 
@@ -2343,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,
@@ -2465,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;
@@ -2694,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:
@@ -2959,7 +3010,7 @@ _bfd_coff_generic_relocate_section (bfd *output_bfd,
                     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];
 
                  if (!h2 || h2->root.type == bfd_link_hash_undefined)
This page took 0.02772 seconds and 4 git commands to generate.