2009-06-05 Tristan Gingold <gingold@adacore.com>
[deliverable/binutils-gdb.git] / bfd / linker.c
index f940d321bd056b567c979fb553cf60dd517ff3cc..66ec2faa3910dd988da5e31530e31a57cf99a8c2 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 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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.
 
@@ -309,7 +311,7 @@ SUBSUBSECTION
        of the <<bfd>> structure.
 
        Each section in the output file will have a list of
        of the <<bfd>> structure.
 
        Each section in the output file will have a list of
-       <<link_order>> structures attached to the <<link_order_head>>
+       <<link_order>> structures attached to the <<map_head.link_order>>
        field (the <<link_order>> structure is defined in
        <<bfdlink.h>>).  These structures describe how to create the
        contents of the output section in terms of the contents of
        field (the <<link_order>> structure is defined in
        <<bfdlink.h>>).  These structures describe how to create the
        contents of the output section in terms of the contents of
@@ -469,17 +471,17 @@ _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 *,
    struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
                                      struct bfd_hash_table *,
-                                     const char *))
+                                     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;
 
-  return bfd_hash_table_init (&table->table, newfunc);
+  return bfd_hash_table_init (&table->table, newfunc, entsize);
 }
 
 /* Look up a symbol in a link hash table.  If follow is TRUE, we
 }
 
 /* Look up a symbol in a link hash table.  If follow is TRUE, we
@@ -561,11 +563,11 @@ bfd_wrapped_link_hash_lookup (bfd *abfd,
 
 #undef WRAP
 
 
 #undef WRAP
 
-#undef REAL
+#undef  REAL
 #define REAL "__real_"
 
       if (*l == '_'
 #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)
        {
          && bfd_hash_lookup (info->wrap_hash, l + sizeof REAL - 1,
                              FALSE, FALSE) != NULL)
        {
@@ -709,7 +711,8 @@ _bfd_generic_link_hash_table_create (bfd *abfd)
   if (ret == NULL)
     return NULL;
   if (! _bfd_link_hash_table_init (&ret->root, abfd,
   if (ret == NULL)
     return NULL;
   if (! _bfd_link_hash_table_init (&ret->root, abfd,
-                                  _bfd_generic_link_hash_newfunc))
+                                  _bfd_generic_link_hash_newfunc,
+                                  sizeof (struct generic_link_hash_entry)))
     {
       free (ret);
       return NULL;
     {
       free (ret);
       return NULL;
@@ -734,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)
     {
@@ -831,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);
@@ -901,9 +904,10 @@ archive_hash_table_init
   (struct archive_hash_table *table,
    struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
                                      struct bfd_hash_table *,
   (struct archive_hash_table *table,
    struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
                                      struct bfd_hash_table *,
-                                     const char *))
+                                     const char *),
+   unsigned int entsize)
 {
 {
-  return bfd_hash_table_init (&table->table, newfunc);
+  return bfd_hash_table_init (&table->table, newfunc, entsize);
 }
 
 /* Look up an entry in an archive hash table.  */
 }
 
 /* Look up an entry in an archive hash table.  */
@@ -981,7 +985,8 @@ _bfd_generic_link_add_archive_symbols
 
   /* In order to quickly determine whether an symbol is defined in
      this archive, we build a hash table of the symbols.  */
 
   /* In order to quickly determine whether an symbol is defined in
      this archive, we build a hash table of the symbols.  */
-  if (! archive_hash_table_init (&arsym_hash, archive_hash_newfunc))
+  if (! archive_hash_table_init (&arsym_hash, archive_hash_newfunc,
+                                sizeof (struct archive_hash_entry)))
     return FALSE;
   for (arsym = arsyms, indx = 0; arsym < arsym_end; arsym++, indx++)
     {
     return FALSE;
   for (arsym = arsyms, indx = 0; arsym < arsym_end; arsym++, indx++)
     {
@@ -1159,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);
@@ -1310,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)
@@ -1323,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
@@ -1356,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))
@@ -1655,8 +1657,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
                s = name + 1;
                while (*s == '_')
                  ++s;
                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;
 
                  {
                    char c;
 
@@ -2009,7 +2010,7 @@ _bfd_generic_final_link (bfd *abfd, struct bfd_link_info *info)
 
   /* Mark all sections which will be included in the output file.  */
   for (o = abfd->sections; o != NULL; o = o->next)
 
   /* Mark all sections which will be included in the output file.  */
   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)
        p->u.indirect.section->linker_mark = TRUE;
 
       if (p->type == bfd_indirect_link_order)
        p->u.indirect.section->linker_mark = TRUE;
 
@@ -2038,7 +2039,7 @@ _bfd_generic_final_link (bfd *abfd, struct bfd_link_info *info)
       for (o = abfd->sections; o != NULL; o = o->next)
        {
          o->reloc_count = 0;
       for (o = abfd->sections; o != NULL; o = o->next)
        {
          o->reloc_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_section_reloc_link_order
                  || p->type == bfd_symbol_reloc_link_order)
            {
              if (p->type == bfd_section_reloc_link_order
                  || p->type == bfd_symbol_reloc_link_order)
@@ -2094,7 +2095,7 @@ _bfd_generic_final_link (bfd *abfd, struct bfd_link_info *info)
   /* Handle all the link order information for the sections.  */
   for (o = abfd->sections; o != NULL; o = o->next)
     {
   /* Handle all the link order information for the sections.  */
   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)
        {
          switch (p->type)
            {
        {
          switch (p->type)
            {
@@ -2158,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.  */
@@ -2241,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;
@@ -2363,12 +2364,11 @@ _bfd_generic_link_output_symbols (bfd *output_bfd,
        abort ();
 
       /* If this symbol is in a section which is not being included
        abort ();
 
       /* If this symbol is in a section which is not being included
-        in the output file, then we don't want to output the symbol.
-
-        Gross.  .bss and similar sections won't have the linker_mark
-        field set.  */
-      if ((sym->section->flags & SEC_HAS_CONTENTS) != 0
-         && ! sym->section->linker_mark)
+        in the output file, then we don't want to output the
+        symbol.  */
+      if (!bfd_is_abs_section (sym->section)
+         && bfd_section_removed_from_list (output_bfd,
+                                           sym->section->output_section))
        output = FALSE;
 
       if (output)
        output = FALSE;
 
       if (output)
@@ -2612,11 +2612,11 @@ bfd_new_link_order (bfd *abfd, asection *section)
 
   new->type = bfd_undefined_link_order;
 
 
   new->type = bfd_undefined_link_order;
 
-  if (section->link_order_tail != NULL)
-    section->link_order_tail->next = new;
+  if (section->map_tail.link_order != NULL)
+    section->map_tail.link_order->next = new;
   else
   else
-    section->link_order_head = new;
-  section->link_order_tail = new;
+    section->map_head.link_order = new;
+  section->map_tail.link_order = new;
 
   return new;
 }
 
   return new;
 }
@@ -2718,11 +2718,10 @@ default_indirect_link_order (bfd *output_bfd,
 
   BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0);
 
 
   BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0);
 
-  if (link_order->size == 0)
-    return TRUE;
-
   input_section = link_order->u.indirect.section;
   input_bfd = input_section->owner;
   input_section = link_order->u.indirect.section;
   input_bfd = input_section->owner;
+  if (input_section->size == 0)
+    return TRUE;
 
   BFD_ASSERT (input_section->output_section == output_section);
   BFD_ASSERT (input_section->output_offset == link_order->offset);
 
   BFD_ASSERT (input_section->output_section == output_section);
   BFD_ASSERT (input_section->output_offset == link_order->offset);
@@ -2753,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
@@ -2797,23 +2796,41 @@ 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.  */
 
   /* Output the section contents.  */
-  loc = link_order->offset * bfd_octets_per_byte (output_bfd);
+  loc = input_section->output_offset * bfd_octets_per_byte (output_bfd);
   if (! bfd_set_section_contents (output_bfd, output_section,
   if (! bfd_set_section_contents (output_bfd, output_section,
-                                 new_contents, loc, link_order->size))
+                                 new_contents, loc, input_section->size))
     goto error_return;
 
   if (contents != NULL)
     goto error_return;
 
   if (contents != NULL)
@@ -2875,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))
 .
 
 */
 .
 
 */
@@ -2922,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)
@@ -2932,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 *
@@ -2945,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;
@@ -2954,7 +2978,9 @@ bfd_boolean
 bfd_section_already_linked_table_init (void)
 {
   return bfd_hash_table_init_n (&_bfd_section_already_linked_table,
 bfd_section_already_linked_table_init (void)
 {
   return bfd_hash_table_init_n (&_bfd_section_already_linked_table,
-                               already_linked_newfunc, 42);
+                               already_linked_newfunc,
+                               sizeof (struct bfd_section_already_linked_hash_entry),
+                               42);
 }
 
 void
 }
 
 void
@@ -2966,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;
@@ -3067,5 +3094,246 @@ _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.  */
+
+static bfd_boolean
+fix_syms (struct bfd_link_hash_entry *h, void *data)
+{
+  bfd *obfd = (bfd *) data;
+
+  if (h->type == bfd_link_hash_warning)
+    h = h->u.i.link;
+
+  if (h->type == bfd_link_hash_defined
+      || h->type == bfd_link_hash_defweak)
+    {
+      asection *s = h->u.def.section;
+      if (s != NULL
+         && s->output_section != NULL
+         && (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;
+
+         /* 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;
+       }
+    }
+
+  return TRUE;
 }
 }
+
+void
+_bfd_fix_excluded_sec_syms (bfd *obfd, struct bfd_link_info *info)
+{
+  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;
+}
+
+/*
+FUNCTION
+       bfd_find_version_for_sym 
+
+SYNOPSIS
+       struct bfd_elf_version_tree * bfd_find_version_for_sym
+         (struct bfd_elf_version_tree *verdefs,
+          const char *sym_name, bfd_boolean *hide);
+
+DESCRIPTION
+       Search an elf version script tree for symbol versioning
+       info and export / don't-export status for a given symbol.
+       Return non-NULL on success and NULL on failure; also sets
+       the output @samp{hide} boolean parameter.
+
+*/
+
+struct bfd_elf_version_tree *
+bfd_find_version_for_sym (struct bfd_elf_version_tree *verdefs,
+                     const char *sym_name,
+                     bfd_boolean *hide)
+{
+  struct bfd_elf_version_tree *t;
+  struct bfd_elf_version_tree *local_ver, *global_ver, *exist_ver;
+
+  local_ver = NULL;
+  global_ver = NULL;
+  exist_ver = NULL;
+  for (t = verdefs; t != NULL; t = t->next)
+    {
+      if (t->globals.list != NULL)
+       {
+         struct bfd_elf_version_expr *d = NULL;
+
+         while ((d = (*t->match) (&t->globals, d, sym_name)) != NULL)
+           {
+             global_ver = t;
+             if (d->symver)
+               exist_ver = t;
+             d->script = 1;
+             /* If the match is a wildcard pattern, keep looking for
+                a more explicit, perhaps even local, match.  */
+             if (d->literal)
+               break;
+           }
+
+         if (d != NULL)
+           break;
+       }
+
+      if (t->locals.list != NULL)
+       {
+         struct bfd_elf_version_expr *d = NULL;
+
+         while ((d = (*t->match) (&t->locals, d, sym_name)) != NULL)
+           {
+             local_ver = t;
+             /* If the match is a wildcard pattern, keep looking for
+                a more explicit, perhaps even global, match.  */
+             if (d->literal)
+               {
+                 /* An exact match overrides a global wildcard.  */
+                 global_ver = NULL;
+                 break;
+               }
+           }
+
+         if (d != NULL)
+           break;
+       }
+    }
+
+  if (global_ver != NULL)
+    {
+      /* If we already have a versioned symbol that matches the
+        node for this symbol, then we don't want to create a
+        duplicate from the unversioned symbol.  Instead hide the
+        unversioned symbol.  */
+      *hide = exist_ver == global_ver;
+      return global_ver;
+    }
+
+  if (local_ver != NULL)
+    {
+      *hide = TRUE;
+      return local_ver;
+    }
+
+  return NULL;
+}
+
This page took 0.038624 seconds and 4 git commands to generate.