bfd/
[deliverable/binutils-gdb.git] / bfd / linker.c
index 8d881c606065b1874d2345f06e74348225b3ba16..bfbd8861ddd50708121f84d031cfad872047b85b 100644 (file)
@@ -1,13 +1,14 @@
 /* linker.c -- BFD linker routines
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
 /* 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
    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,
    (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
 
    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 "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "bfdlink.h"
 #include "genlink.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
 
        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
 
        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
        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.
 
        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_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)
 {
    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;
   table->undefs = NULL;
   table->undefs_tail = NULL;
   table->type = bfd_link_generic_hash_table;
@@ -736,8 +737,8 @@ _bfd_generic_link_hash_table_free (struct bfd_link_hash_table *hash)
    the hash table pointing to different instances of the symbol
    structure.  */
 
    the hash table pointing to different instances of the symbol
    structure.  */
 
-static bfd_boolean
-generic_link_read_symbols (bfd *abfd)
+bfd_boolean
+bfd_generic_link_read_symbols (bfd *abfd)
 {
   if (bfd_get_outsymbols (abfd) == NULL)
     {
 {
   if (bfd_get_outsymbols (abfd) == NULL)
     {
@@ -833,7 +834,7 @@ generic_link_add_object_symbols (bfd *abfd,
   bfd_size_type symcount;
   struct bfd_symbol **outsyms;
 
   bfd_size_type symcount;
   struct bfd_symbol **outsyms;
 
-  if (! generic_link_read_symbols (abfd))
+  if (!bfd_generic_link_read_symbols (abfd))
     return FALSE;
   symcount = _bfd_generic_link_get_symcount (abfd);
   outsyms = _bfd_generic_link_get_symbols (abfd);
     return FALSE;
   symcount = _bfd_generic_link_get_symcount (abfd);
   outsyms = _bfd_generic_link_get_symbols (abfd);
@@ -1163,7 +1164,7 @@ generic_link_check_archive_element (bfd *abfd,
 
   *pneeded = FALSE;
 
 
   *pneeded = FALSE;
 
-  if (! generic_link_read_symbols (abfd))
+  if (!bfd_generic_link_read_symbols (abfd))
     return FALSE;
 
   pp = _bfd_generic_link_get_symbols (abfd);
     return FALSE;
 
   pp = _bfd_generic_link_get_symbols (abfd);
@@ -1314,7 +1315,7 @@ generic_link_add_symbol_list (bfd *abfd,
          struct generic_link_hash_entry *h;
          struct bfd_link_hash_entry *bh;
 
          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)
          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.  */
            {
              /* 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);
            }
              pp++;
              name = bfd_asymbol_name (*pp);
            }
-         else
-           string = NULL;
 
          bh = NULL;
          if (! (_bfd_generic_link_add_one_symbol
 
          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.  */
             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))
            {
              if (h->sym == NULL
                  || (! bfd_is_und_section (bfd_get_section (p))
@@ -2161,7 +2159,7 @@ _bfd_generic_link_output_symbols (bfd *output_bfd,
   asymbol **sym_ptr;
   asymbol **sym_end;
 
   asymbol **sym_ptr;
   asymbol **sym_end;
 
-  if (! generic_link_read_symbols (input_bfd))
+  if (!bfd_generic_link_read_symbols (input_bfd))
     return FALSE;
 
   /* Create a filename symbol if we are supposed to.  */
     return FALSE;
 
   /* Create a filename symbol if we are supposed to.  */
@@ -2244,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.  */
                 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;
                {
                  if (h->sym != NULL)
                    *sym_ptr = sym = h->sym;
@@ -2754,7 +2752,7 @@ default_indirect_link_order (bfd *output_bfd,
         have retrieved them by this point, but we are being called by
         a specific linker, presumably because we are linking
         different types of object files together.  */
         have retrieved them by this point, but we are being called by
         a specific linker, presumably because we are linking
         different types of object files together.  */
-      if (! generic_link_read_symbols (input_bfd))
+      if (!bfd_generic_link_read_symbols (input_bfd))
        return FALSE;
 
       /* Since we have been called by a specific linker, rather than
        return FALSE;
 
       /* Since we have been called by a specific linker, rather than
@@ -2798,18 +2796,36 @@ default_indirect_link_order (bfd *output_bfd,
        }
     }
 
        }
     }
 
-  /* Get and relocate the section contents.  */
-  sec_size = (input_section->rawsize > input_section->size
-             ? input_section->rawsize
-             : input_section->size);
-  contents = bfd_malloc (sec_size);
-  if (contents == NULL && sec_size != 0)
-    goto error_return;
-  new_contents = (bfd_get_relocated_section_contents
-                 (output_bfd, info, link_order, contents, info->relocatable,
-                  _bfd_generic_link_get_symbols (input_bfd)));
-  if (!new_contents)
-    goto error_return;
+  if ((output_section->flags & (SEC_GROUP | SEC_LINKER_CREATED)) == SEC_GROUP
+      && input_section->size != 0)
+    {
+      /* Group section contents are set by bfd_elf_set_group_contents.  */
+      if (!output_bfd->output_has_begun)
+       {
+         /* FIXME: This hack ensures bfd_elf_set_group_contents is called.  */
+         if (!bfd_set_section_contents (output_bfd, output_section, "", 0, 1))
+           goto error_return;
+       }
+      new_contents = output_section->contents;
+      BFD_ASSERT (new_contents != NULL);
+      BFD_ASSERT (input_section->output_offset == 0);
+    }
+  else
+    {
+      /* Get and relocate the section contents.  */
+      sec_size = (input_section->rawsize > input_section->size
+                 ? input_section->rawsize
+                 : input_section->size);
+      contents = bfd_malloc (sec_size);
+      if (contents == NULL && sec_size != 0)
+       goto error_return;
+      new_contents = (bfd_get_relocated_section_contents
+                     (output_bfd, info, link_order, contents,
+                      info->relocatable,
+                      _bfd_generic_link_get_symbols (input_bfd)));
+      if (!new_contents)
+       goto error_return;
+    }
 
   /* Output the section contents.  */
   loc = input_section->output_offset * bfd_octets_per_byte (output_bfd);
 
   /* Output the section contents.  */
   loc = input_section->output_offset * bfd_octets_per_byte (output_bfd);
@@ -2876,14 +2892,15 @@ FUNCTION
        bfd_section_already_linked
 
 SYNOPSIS
        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.
 
 
 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))
 .
 
 */
 .
 
 */
@@ -2923,7 +2940,7 @@ bfd_section_already_linked_table_lookup (const char *name)
                           TRUE, FALSE));
 }
 
                           TRUE, FALSE));
 }
 
-void
+bfd_boolean
 bfd_section_already_linked_table_insert
   (struct bfd_section_already_linked_hash_entry *already_linked_list,
    asection *sec)
 bfd_section_already_linked_table_insert
   (struct bfd_section_already_linked_hash_entry *already_linked_list,
    asection *sec)
@@ -2933,9 +2950,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);
   /* 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;
   l->sec = sec;
   l->next = already_linked_list->entry;
   already_linked_list->entry = l;
+  return TRUE;
 }
 
 static struct bfd_hash_entry *
 }
 
 static struct bfd_hash_entry *
@@ -2946,6 +2966,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);
 
   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;
   ret->entry = NULL;
 
   return &ret->root;
@@ -2969,7 +2992,8 @@ bfd_section_already_linked_table_free (void)
 /* This is used on non-ELF inputs.  */
 
 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;
 {
   flagword flags;
   const char *name;
@@ -3070,7 +3094,8 @@ _bfd_generic_section_already_linked (bfd *abfd, asection *sec)
     }
 
   /* This is the first section with this name.  Record it.  */
     }
 
   /* 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\n"));
 }
 
 /* Convert symbols in excluded output sections to use a kept section.  */
 }
 
 /* Convert symbols in excluded output sections to use a kept section.  */
@@ -3161,3 +3186,62 @@ _bfd_fix_excluded_sec_syms (bfd *obfd, struct bfd_link_info *info)
 {
   bfd_link_hash_traverse (info->hash, fix_syms, obfd);
 }
 {
   bfd_link_hash_traverse (info->hash, fix_syms, obfd);
 }
+
+/*
+FUNCTION
+       bfd_generic_define_common_symbol
+
+SYNOPSIS
+       bfd_boolean bfd_generic_define_common_symbol
+         (bfd *output_bfd, struct bfd_link_info *info,
+          struct bfd_link_hash_entry *h);
+
+DESCRIPTION
+       Convert common symbol @var{h} into a defined symbol.
+       Return TRUE on success and FALSE on failure.
+
+.#define bfd_define_common_symbol(output_bfd, info, h) \
+.       BFD_SEND (output_bfd, _bfd_define_common_symbol, (output_bfd, info, h))
+.
+*/
+
+bfd_boolean
+bfd_generic_define_common_symbol (bfd *output_bfd,
+                                 struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                                 struct bfd_link_hash_entry *h)
+{
+  unsigned int power_of_two;
+  bfd_vma alignment, size;
+  asection *section;
+
+  BFD_ASSERT (h != NULL && h->type == bfd_link_hash_common);
+
+  size = h->u.c.size;
+  power_of_two = h->u.c.p->alignment_power;
+  section = h->u.c.p->section;
+
+  /* Increase the size of the section to align the common symbol.
+     The alignment must be a power of two.  */
+  alignment = bfd_octets_per_byte (output_bfd) << power_of_two;
+  BFD_ASSERT (alignment != 0 && (alignment & -alignment) == alignment);
+  section->size += alignment - 1;
+  section->size &= -alignment;
+
+  /* Adjust the section's overall alignment if necessary.  */
+  if (power_of_two > section->alignment_power)
+    section->alignment_power = power_of_two;
+
+  /* Change the symbol from common to defined.  */
+  h->type = bfd_link_hash_defined;
+  h->u.def.section = section;
+  h->u.def.value = section->size;
+
+  /* Increase the size of the section.  */
+  section->size += size;
+
+  /* Make sure the section is allocated in memory, and make sure that
+     it is no longer a common section.  */
+  section->flags |= SEC_ALLOC;
+  section->flags &= ~SEC_IS_COMMON;
+  return TRUE;
+}
This page took 0.028019 seconds and 4 git commands to generate.