include/
[deliverable/binutils-gdb.git] / bfd / linker.c
index 14eeae4df0c858d63dcdd4f299951fb39ad2775b..327426e3c519d0efa77ac98b2cf903c0948d635d 100644 (file)
@@ -1,13 +1,14 @@
 /* linker.c -- BFD linker routines
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006, 2007, 2008
+   Free Software Foundation, Inc.
    Written by Steve Chamberlain and 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "bfdlink.h"
 #include "genlink.h"
@@ -149,9 +151,9 @@ SUBSUBSECTION
 
        Sometimes the <<_bfd_link_add_symbols>> function must store
        some information in the hash table entry to be used by the
-       <<_bfd_final_link>> function.  In such a case the <<creator>>
-       field of the hash table must be checked to make sure that the
-       hash table was created by an object file of the same format.
+       <<_bfd_final_link>> function.  In such a case the output bfd
+       xvec must be checked to make sure that the hash table was
+       created by an object file of the same format.
 
        The <<_bfd_final_link>> routine must be prepared to handle a
        hash entry without any extra information added by the
@@ -163,7 +165,7 @@ SUBSUBSECTION
        initialization function.
 
        See <<ecoff_link_add_externals>> for an example of how to
-       check the <<creator>> field before saving information (in this
+       check the output bfd before saving information (in this
        case, the ECOFF external symbol debugging information) in a
        hash table entry.
 
@@ -469,13 +471,12 @@ _bfd_link_hash_newfunc (struct bfd_hash_entry *entry,
 bfd_boolean
 _bfd_link_hash_table_init
   (struct bfd_link_hash_table *table,
-   bfd *abfd,
+   bfd *abfd ATTRIBUTE_UNUSED,
    struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
                                      struct bfd_hash_table *,
                                      const char *),
    unsigned int entsize)
 {
-  table->creator = abfd->xvec;
   table->undefs = NULL;
   table->undefs_tail = NULL;
   table->type = bfd_link_generic_hash_table;
@@ -562,11 +563,11 @@ bfd_wrapped_link_hash_lookup (bfd *abfd,
 
 #undef WRAP
 
-#undef REAL
+#undef  REAL
 #define REAL "__real_"
 
       if (*l == '_'
-         && strncmp (l, REAL, sizeof REAL - 1) == 0
+         && CONST_STRNEQ (l, REAL)
          && bfd_hash_lookup (info->wrap_hash, l + sizeof REAL - 1,
                              FALSE, FALSE) != NULL)
        {
@@ -1314,7 +1315,7 @@ generic_link_add_symbol_list (bfd *abfd,
          struct generic_link_hash_entry *h;
          struct bfd_link_hash_entry *bh;
 
-         name = bfd_asymbol_name (p);
+         string = name = bfd_asymbol_name (p);
          if (((p->flags & BSF_INDIRECT) != 0
               || bfd_is_ind_section (p->section))
              && pp + 1 < ppend)
@@ -1327,12 +1328,9 @@ generic_link_add_symbol_list (bfd *abfd,
            {
              /* The name of P is actually the warning string, and the
                 next symbol is the one to warn about.  */
-             string = name;
              pp++;
              name = bfd_asymbol_name (*pp);
            }
-         else
-           string = NULL;
 
          bh = NULL;
          if (! (_bfd_generic_link_add_one_symbol
@@ -1360,7 +1358,7 @@ generic_link_add_symbol_list (bfd *abfd,
             hash table other than the generic hash table, so we only
             do this if we are certain that the hash table is a
             generic one.  */
-         if (info->hash->creator == abfd->xvec)
+         if (info->output_bfd->xvec == abfd->xvec)
            {
              if (h->sym == NULL
                  || (! bfd_is_und_section (bfd_get_section (p))
@@ -1659,8 +1657,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
                s = name + 1;
                while (*s == '_')
                  ++s;
-               if (s[0] == 'G'
-                   && strncmp (s, CONS_PREFIX, CONS_PREFIX_LEN - 1) == 0)
+               if (s[0] == 'G' && CONST_STRNEQ (s, CONS_PREFIX))
                  {
                    char c;
 
@@ -2245,7 +2242,7 @@ _bfd_generic_link_output_symbols (bfd *output_bfd,
                 this routine will be called with a hash table
                 other than a generic hash table, so we double
                 check that.  */
-             if (info->hash->creator == input_bfd->xvec)
+             if (info->output_bfd->xvec == input_bfd->xvec)
                {
                  if (h->sym != NULL)
                    *sym_ptr = sym = h->sym;
@@ -2877,14 +2874,15 @@ FUNCTION
        bfd_section_already_linked
 
 SYNOPSIS
-        void bfd_section_already_linked (bfd *abfd, asection *sec);
+        void bfd_section_already_linked (bfd *abfd, asection *sec,
+                                        struct bfd_link_info *info);
 
 DESCRIPTION
        Check if @var{sec} has been already linked during a reloceatable
        or final link.
 
-.#define bfd_section_already_linked(abfd, sec) \
-.       BFD_SEND (abfd, _section_already_linked, (abfd, sec))
+.#define bfd_section_already_linked(abfd, sec, info) \
+.       BFD_SEND (abfd, _section_already_linked, (abfd, sec, info))
 .
 
 */
@@ -2924,7 +2922,7 @@ bfd_section_already_linked_table_lookup (const char *name)
                           TRUE, FALSE));
 }
 
-void
+bfd_boolean
 bfd_section_already_linked_table_insert
   (struct bfd_section_already_linked_hash_entry *already_linked_list,
    asection *sec)
@@ -2934,9 +2932,12 @@ bfd_section_already_linked_table_insert
   /* Allocate the memory from the same obstack as the hash table is
      kept in.  */
   l = bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
+  if (l == NULL)
+    return FALSE;
   l->sec = sec;
   l->next = already_linked_list->entry;
   already_linked_list->entry = l;
+  return TRUE;
 }
 
 static struct bfd_hash_entry *
@@ -2947,6 +2948,9 @@ already_linked_newfunc (struct bfd_hash_entry *entry ATTRIBUTE_UNUSED,
   struct bfd_section_already_linked_hash_entry *ret =
     bfd_hash_allocate (table, sizeof *ret);
 
+  if (ret == NULL)
+    return NULL;
+
   ret->entry = NULL;
 
   return &ret->root;
@@ -2970,7 +2974,8 @@ bfd_section_already_linked_table_free (void)
 /* This is used on non-ELF inputs.  */
 
 void
-_bfd_generic_section_already_linked (bfd *abfd, asection *sec)
+_bfd_generic_section_already_linked (bfd *abfd, asection *sec,
+                                    struct bfd_link_info *info)
 {
   flagword flags;
   const char *name;
@@ -3071,10 +3076,11 @@ _bfd_generic_section_already_linked (bfd *abfd, asection *sec)
     }
 
   /* This is the first section with this name.  Record it.  */
-  bfd_section_already_linked_table_insert (already_linked_list, sec);
+  if (! bfd_section_already_linked_table_insert (already_linked_list, sec))
+    info->callbacks->einfo (_("%F%P: already_linked_table: %E"));
 }
 
-/* Convert symbols in excluded output sections to absolute.  */
+/* Convert symbols in excluded output sections to use a kept section.  */
 
 static bfd_boolean
 fix_syms (struct bfd_link_hash_entry *h, void *data)
@@ -3093,8 +3099,64 @@ fix_syms (struct bfd_link_hash_entry *h, void *data)
          && (s->output_section->flags & SEC_EXCLUDE) != 0
          && bfd_section_removed_from_list (obfd, s->output_section))
        {
+         asection *op, *op1;
+
          h->u.def.value += s->output_offset + s->output_section->vma;
-         h->u.def.section = bfd_abs_section_ptr;
+
+         /* Find preceding kept section.  */
+         for (op1 = s->output_section->prev; op1 != NULL; op1 = op1->prev)
+           if ((op1->flags & SEC_EXCLUDE) == 0
+               && !bfd_section_removed_from_list (obfd, op1))
+             break;
+
+         /* Find following kept section.  Start at prev->next because
+            other sections may have been added after S was removed.  */
+         if (s->output_section->prev != NULL)
+           op = s->output_section->prev->next;
+         else
+           op = s->output_section->owner->sections;
+         for (; op != NULL; op = op->next)
+           if ((op->flags & SEC_EXCLUDE) == 0
+               && !bfd_section_removed_from_list (obfd, op))
+             break;
+
+         /* Choose better of two sections, based on flags.  The idea
+            is to choose a section that will be in the same segment
+            as S would have been if it was kept.  */
+         if (op1 == NULL)
+           {
+             if (op == NULL)
+               op = bfd_abs_section_ptr;
+           }
+         else if (op == NULL)
+           op = op1;
+         else if (((op1->flags ^ op->flags)
+                   & (SEC_ALLOC | SEC_THREAD_LOCAL)) != 0)
+           {
+             if (((op->flags ^ s->flags)
+                  & (SEC_ALLOC | SEC_THREAD_LOCAL)) != 0)
+               op = op1;
+           }
+         else if (((op1->flags ^ op->flags) & SEC_READONLY) != 0)
+           {
+             if (((op->flags ^ s->flags) & SEC_READONLY) != 0)
+               op = op1;
+           }
+         else if (((op1->flags ^ op->flags) & SEC_CODE) != 0)
+           {
+             if (((op->flags ^ s->flags) & SEC_CODE) != 0)
+               op = op1;
+           }
+         else
+           {
+             /* Flags we care about are the same.  Prefer the following
+                section if that will result in a positive valued sym.  */
+             if (h->u.def.value < op->vma)
+               op = op1;
+           }
+
+         h->u.def.value -= op->vma;
+         h->u.def.section = op;
        }
     }
 
This page took 0.026859 seconds and 4 git commands to generate.