PR22471, undefined reference to linker-defined symbols
[deliverable/binutils-gdb.git] / bfd / linker.c
index d4b053c9c6f905dffc7b1e7044fe9a90078fe599..9c19df4e5707b7739bf4006cd2fa810a6dfc661c 100644 (file)
@@ -1,5 +1,5 @@
 /* linker.c -- BFD linker routines
 /* linker.c -- BFD linker routines
-   Copyright (C) 1993-2014 Free Software Foundation, Inc.
+   Copyright (C) 1993-2017 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.
    Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -403,21 +403,12 @@ SUBSUBSECTION
 */
 
 static bfd_boolean generic_link_add_object_symbols
 */
 
 static bfd_boolean generic_link_add_object_symbols
-  (bfd *, struct bfd_link_info *, bfd_boolean collect);
-static bfd_boolean generic_link_add_symbols
-  (bfd *, struct bfd_link_info *, bfd_boolean);
-static bfd_boolean generic_link_check_archive_element_no_collect
-  (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, const char *,
-   bfd_boolean *);
-static bfd_boolean generic_link_check_archive_element_collect
-  (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, const char *,
-   bfd_boolean *);
+  (bfd *, struct bfd_link_info *);
 static bfd_boolean generic_link_check_archive_element
   (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, const char *,
 static bfd_boolean generic_link_check_archive_element
   (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, const char *,
-   bfd_boolean *, bfd_boolean);
+   bfd_boolean *);
 static bfd_boolean generic_link_add_symbol_list
 static bfd_boolean generic_link_add_symbol_list
-  (bfd *, struct bfd_link_info *, bfd_size_type count, asymbol **,
-   bfd_boolean);
+  (bfd *, struct bfd_link_info *, bfd_size_type count, asymbol **);
 static bfd_boolean generic_add_output_symbol
   (bfd *, size_t *psymalloc, asymbol *);
 static bfd_boolean default_data_link_order
 static bfd_boolean generic_add_output_symbol
   (bfd *, size_t *psymalloc, asymbol *);
 static bfd_boolean default_data_link_order
@@ -816,29 +807,6 @@ bfd_generic_link_read_symbols (bfd *abfd)
   return TRUE;
 }
 \f
   return TRUE;
 }
 \f
-/* Generic function to add symbols to from an object file to the
-   global hash table.  This version does not automatically collect
-   constructors by name.  */
-
-bfd_boolean
-_bfd_generic_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
-{
-  return generic_link_add_symbols (abfd, info, FALSE);
-}
-
-/* Generic function to add symbols from an object file to the global
-   hash table.  This version automatically collects constructors by
-   name, as the collect2 program does.  It should be used for any
-   target which does not provide some other mechanism for setting up
-   constructors and destructors; these are approximately those targets
-   for which gcc uses collect2 and do not support stabs.  */
-
-bfd_boolean
-_bfd_generic_link_add_symbols_collect (bfd *abfd, struct bfd_link_info *info)
-{
-  return generic_link_add_symbols (abfd, info, TRUE);
-}
-
 /* Indicate that we are only retrieving symbol values from this
    section.  We want the symbols to act as though the values in the
    file are absolute.  */
 /* Indicate that we are only retrieving symbol values from this
    section.  We want the symbols to act as though the values in the
    file are absolute.  */
@@ -862,26 +830,22 @@ _bfd_generic_copy_link_hash_symbol_type (bfd *abfd ATTRIBUTE_UNUSED,
 {
 }
 
 {
 }
 
-/* Add symbols from an object file to the global hash table.  */
+/* Generic function to add symbols from an object file to the
+   global hash table.  */
 
 
-static bfd_boolean
-generic_link_add_symbols (bfd *abfd,
-                         struct bfd_link_info *info,
-                         bfd_boolean collect)
+bfd_boolean
+_bfd_generic_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
 {
   bfd_boolean ret;
 
   switch (bfd_get_format (abfd))
     {
     case bfd_object:
 {
   bfd_boolean ret;
 
   switch (bfd_get_format (abfd))
     {
     case bfd_object:
-      ret = generic_link_add_object_symbols (abfd, info, collect);
+      ret = generic_link_add_object_symbols (abfd, info);
       break;
     case bfd_archive:
       ret = (_bfd_generic_link_add_archive_symbols
       break;
     case bfd_archive:
       ret = (_bfd_generic_link_add_archive_symbols
-            (abfd, info,
-             (collect
-              ? generic_link_check_archive_element_collect
-              : generic_link_check_archive_element_no_collect)));
+            (abfd, info, generic_link_check_archive_element));
       break;
     default:
       bfd_set_error (bfd_error_wrong_format);
       break;
     default:
       bfd_set_error (bfd_error_wrong_format);
@@ -895,8 +859,7 @@ generic_link_add_symbols (bfd *abfd,
 
 static bfd_boolean
 generic_link_add_object_symbols (bfd *abfd,
 
 static bfd_boolean
 generic_link_add_object_symbols (bfd *abfd,
-                                struct bfd_link_info *info,
-                                bfd_boolean collect)
+                                struct bfd_link_info *info)
 {
   bfd_size_type symcount;
   struct bfd_symbol **outsyms;
 {
   bfd_size_type symcount;
   struct bfd_symbol **outsyms;
@@ -905,7 +868,7 @@ generic_link_add_object_symbols (bfd *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);
-  return generic_link_add_symbol_list (abfd, info, symcount, outsyms, collect);
+  return generic_link_add_symbol_list (abfd, info, symcount, outsyms);
 }
 \f
 /* Generic function to add symbols from an archive file to the global
 }
 \f
 /* Generic function to add symbols from an archive file to the global
@@ -1044,47 +1007,14 @@ _bfd_generic_link_add_archive_symbols
   return FALSE;
 }
 \f
   return FALSE;
 }
 \f
-/* See if we should include an archive element.  This version is used
-   when we do not want to automatically collect constructors based on
-   the symbol name, presumably because we have some other mechanism
-   for finding them.  */
-
-static bfd_boolean
-generic_link_check_archive_element_no_collect (bfd *abfd,
-                                              struct bfd_link_info *info,
-                                              struct bfd_link_hash_entry *h,
-                                              const char *name,
-                                              bfd_boolean *pneeded)
-{
-  return generic_link_check_archive_element (abfd, info, h, name, pneeded,
-                                            FALSE);
-}
-
-/* See if we should include an archive element.  This version is used
-   when we want to automatically collect constructors based on the
-   symbol name, as collect2 does.  */
-
-static bfd_boolean
-generic_link_check_archive_element_collect (bfd *abfd,
-                                           struct bfd_link_info *info,
-                                           struct bfd_link_hash_entry *h,
-                                           const char *name,
-                                           bfd_boolean *pneeded)
-{
-  return generic_link_check_archive_element (abfd, info, h, name, pneeded,
-                                            TRUE);
-}
-
-/* See if we should include an archive element.  Optionally collect
-   constructors.  */
+/* See if we should include an archive element.  */
 
 static bfd_boolean
 generic_link_check_archive_element (bfd *abfd,
                                    struct bfd_link_info *info,
                                    struct bfd_link_hash_entry *h,
                                    const char *name ATTRIBUTE_UNUSED,
 
 static bfd_boolean
 generic_link_check_archive_element (bfd *abfd,
                                    struct bfd_link_info *info,
                                    struct bfd_link_hash_entry *h,
                                    const char *name ATTRIBUTE_UNUSED,
-                                   bfd_boolean *pneeded,
-                                   bfd_boolean collect)
+                                   bfd_boolean *pneeded)
 {
   asymbol **pp, **ppend;
 
 {
   asymbol **pp, **ppend;
 
@@ -1134,7 +1064,7 @@ generic_link_check_archive_element (bfd *abfd,
            return FALSE;
          /* Potentially, the add_archive_element hook may have set a
             substitute BFD for us.  */
            return FALSE;
          /* Potentially, the add_archive_element hook may have set a
             substitute BFD for us.  */
-         return generic_link_add_object_symbols (abfd, info, collect);
+         return bfd_link_add_symbols (abfd, info);
        }
 
       /* P is a common symbol.  */
        }
 
       /* P is a common symbol.  */
@@ -1192,16 +1122,13 @@ generic_link_check_archive_element (bfd *abfd,
 
 /* Add the symbols from an object file to the global hash table.  ABFD
    is the object file.  INFO is the linker information.  SYMBOL_COUNT
 
 /* Add the symbols from an object file to the global hash table.  ABFD
    is the object file.  INFO is the linker information.  SYMBOL_COUNT
-   is the number of symbols.  SYMBOLS is the list of symbols.  COLLECT
-   is TRUE if constructors should be automatically collected by name
-   as is done by collect2.  */
+   is the number of symbols.  SYMBOLS is the list of symbols.  */
 
 static bfd_boolean
 generic_link_add_symbol_list (bfd *abfd,
                              struct bfd_link_info *info,
                              bfd_size_type symbol_count,
 
 static bfd_boolean
 generic_link_add_symbol_list (bfd *abfd,
                              struct bfd_link_info *info,
                              bfd_size_type symbol_count,
-                             asymbol **symbols,
-                             bfd_boolean collect)
+                             asymbol **symbols)
 {
   asymbol **pp, **ppend;
 
 {
   asymbol **pp, **ppend;
 
@@ -1247,7 +1174,7 @@ generic_link_add_symbol_list (bfd *abfd,
          bh = NULL;
          if (! (_bfd_generic_link_add_one_symbol
                 (info, abfd, name, p->flags, bfd_get_section (p),
          bh = NULL;
          if (! (_bfd_generic_link_add_one_symbol
                 (info, abfd, name, p->flags, bfd_get_section (p),
-                 p->value, string, FALSE, collect, &bh)))
+                 p->value, string, FALSE, FALSE, &bh)))
            return FALSE;
          h = (struct generic_link_hash_entry *) bh;
 
            return FALSE;
          h = (struct generic_link_hash_entry *) bh;
 
@@ -1442,13 +1369,23 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
 {
   enum link_row row;
   struct bfd_link_hash_entry *h;
 {
   enum link_row row;
   struct bfd_link_hash_entry *h;
+  struct bfd_link_hash_entry *inh = NULL;
   bfd_boolean cycle;
 
   BFD_ASSERT (section != NULL);
 
   if (bfd_is_ind_section (section)
       || (flags & BSF_INDIRECT) != 0)
   bfd_boolean cycle;
 
   BFD_ASSERT (section != NULL);
 
   if (bfd_is_ind_section (section)
       || (flags & BSF_INDIRECT) != 0)
-    row = INDR_ROW;
+    {
+      row = INDR_ROW;
+      /* Create the indirect symbol here.  This is for the benefit of
+        the plugin "notice" function.
+        STRING is the name of the symbol we want to indirect to.  */
+      inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE,
+                                         copy, FALSE);
+      if (inh == NULL)
+       return FALSE;
+    }
   else if ((flags & BSF_WARNING) != 0)
     row = WARN_ROW;
   else if ((flags & BSF_CONSTRUCTOR) != 0)
   else if ((flags & BSF_WARNING) != 0)
     row = WARN_ROW;
   else if ((flags & BSF_CONSTRUCTOR) != 0)
@@ -1465,10 +1402,12 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
   else if (bfd_is_com_section (section))
     {
       row = COMMON_ROW;
   else if (bfd_is_com_section (section))
     {
       row = COMMON_ROW;
-      if (strcmp (name, "__gnu_lto_slim") == 0)
-       (*_bfd_error_handler)
-         (_("%s: plugin needed to handle lto object"),
-          bfd_get_filename (abfd));
+      if (!bfd_link_relocatable (info)
+         && name[0] == '_'
+         && name[1] == '_'
+         && strcmp (name + (name[2] == '_'), "__gnu_lto_slim") == 0)
+       _bfd_error_handler
+         (_("%B: plugin needed to handle lto object"), abfd);
     }
   else
     row = DEF_ROW;
     }
   else
     row = DEF_ROW;
@@ -1493,8 +1432,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
       || (info->notice_hash != NULL
          && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
     {
       || (info->notice_hash != NULL
          && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
     {
-      if (! (*info->callbacks->notice) (info, h,
-                                       abfd, section, value, flags, string))
+      if (! (*info->callbacks->notice) (info, h, inh,
+                                       abfd, section, value, flags))
        return FALSE;
     }
 
        return FALSE;
     }
 
@@ -1504,9 +1443,14 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
   do
     {
       enum link_action action;
   do
     {
       enum link_action action;
+      int prev;
 
 
+      prev = h->type;
+      /* Treat symbols defined by early linker script pass as undefined.  */
+      if (h->ldscript_def)
+       prev = bfd_link_hash_undefined;
       cycle = FALSE;
       cycle = FALSE;
-      action = link_action[(int) row][(int) h->type];
+      action = link_action[(int) row][prev];
       switch (action)
        {
        case FAIL:
       switch (action)
        {
        case FAIL:
@@ -1533,9 +1477,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
          /* We have found a definition for a symbol which was
             previously common.  */
          BFD_ASSERT (h->type == bfd_link_hash_common);
          /* We have found a definition for a symbol which was
             previously common.  */
          BFD_ASSERT (h->type == bfd_link_hash_common);
-         if (! ((*info->callbacks->multiple_common)
-                (info, h, abfd, bfd_link_hash_defined, 0)))
-           return FALSE;
+         (*info->callbacks->multiple_common) (info, h, abfd,
+                                              bfd_link_hash_defined, 0);
          /* Fall through.  */
        case DEF:
        case DEFW:
          /* Fall through.  */
        case DEF:
        case DEFW:
@@ -1550,6 +1493,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
              h->type = bfd_link_hash_defined;
            h->u.def.section = section;
            h->u.def.value = value;
              h->type = bfd_link_hash_defined;
            h->u.def.section = section;
            h->u.def.value = value;
+           h->linker_def = 0;
+           h->ldscript_def = 0;
 
            /* If we have been asked to, we act like collect2 and
               identify all functions that might be global
 
            /* If we have been asked to, we act like collect2 and
               identify all functions that might be global
@@ -1591,10 +1536,9 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
                        if (oldtype == bfd_link_hash_defweak)
                          abort ();
 
                        if (oldtype == bfd_link_hash_defweak)
                          abort ();
 
-                       if (! ((*info->callbacks->constructor)
-                              (info, c == 'I',
-                               h->root.string, abfd, section, value)))
-                         return FALSE;
+                       (*info->callbacks->constructor) (info, c == 'I',
+                                                        h->root.string, abfd,
+                                                        section, value);
                      }
                  }
              }
                      }
                  }
              }
@@ -1649,6 +1593,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
            }
          else
            h->u.c.p->section = section;
            }
          else
            h->u.c.p->section = section;
+         h->linker_def = 0;
+         h->ldscript_def = 0;
          break;
 
        case REF:
          break;
 
        case REF:
@@ -1662,9 +1608,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
             already had a common definition.  Use the maximum of the
             two sizes, and use the section required by the larger symbol.  */
          BFD_ASSERT (h->type == bfd_link_hash_common);
             already had a common definition.  Use the maximum of the
             two sizes, and use the section required by the larger symbol.  */
          BFD_ASSERT (h->type == bfd_link_hash_common);
-         if (! ((*info->callbacks->multiple_common)
-                (info, h, abfd, bfd_link_hash_common, value)))
-           return FALSE;
+         (*info->callbacks->multiple_common) (info, h, abfd,
+                                              bfd_link_hash_common, value);
          if (value > h->u.c.size)
            {
              unsigned int power;
          if (value > h->u.c.size)
            {
              unsigned int power;
@@ -1702,9 +1647,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
        case CREF:
          /* We have found a common definition for a symbol which
             was already defined.  */
        case CREF:
          /* We have found a common definition for a symbol which
             was already defined.  */
-         if (! ((*info->callbacks->multiple_common)
-                (info, h, abfd, bfd_link_hash_common, value)))
-           return FALSE;
+         (*info->callbacks->multiple_common) (info, h, abfd,
+                                              bfd_link_hash_common, value);
          break;
 
        case MIND:
          break;
 
        case MIND:
@@ -1715,64 +1659,58 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
          /* Fall through.  */
        case MDEF:
          /* Handle a multiple definition.  */
          /* Fall through.  */
        case MDEF:
          /* Handle a multiple definition.  */
-         if (! ((*info->callbacks->multiple_definition)
-                (info, h, abfd, section, value)))
-           return FALSE;
+         (*info->callbacks->multiple_definition) (info, h,
+                                                  abfd, section, value);
          break;
 
        case CIND:
          /* Create an indirect symbol from an existing common symbol.  */
          BFD_ASSERT (h->type == bfd_link_hash_common);
          break;
 
        case CIND:
          /* Create an indirect symbol from an existing common symbol.  */
          BFD_ASSERT (h->type == bfd_link_hash_common);
-         if (! ((*info->callbacks->multiple_common)
-                (info, h, abfd, bfd_link_hash_indirect, 0)))
-           return FALSE;
+         (*info->callbacks->multiple_common) (info, h, abfd,
+                                              bfd_link_hash_indirect, 0);
          /* Fall through.  */
        case IND:
          /* Fall through.  */
        case IND:
-         /* Create an indirect symbol.  */
-         {
-           struct bfd_link_hash_entry *inh;
-
-           /* STRING is the name of the symbol we want to indirect
-              to.  */
-           inh = bfd_wrapped_link_hash_lookup (abfd, info, string, TRUE,
-                                               copy, FALSE);
-           if (inh == NULL)
+         if (inh->type == bfd_link_hash_indirect
+             && inh->u.i.link == h)
+           {
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("%B: indirect symbol `%s' to `%s' is a loop"),
+                abfd, name, string);
+             bfd_set_error (bfd_error_invalid_operation);
              return FALSE;
              return FALSE;
-           if (inh->type == bfd_link_hash_indirect
-               && inh->u.i.link == h)
-             {
-               (*_bfd_error_handler)
-                 (_("%B: indirect symbol `%s' to `%s' is a loop"),
-                  abfd, name, string);
-               bfd_set_error (bfd_error_invalid_operation);
-               return FALSE;
-             }
-           if (inh->type == bfd_link_hash_new)
-             {
-               inh->type = bfd_link_hash_undefined;
-               inh->u.undef.abfd = abfd;
-               bfd_link_add_undef (info->hash, inh);
-             }
+           }
+         if (inh->type == bfd_link_hash_new)
+           {
+             inh->type = bfd_link_hash_undefined;
+             inh->u.undef.abfd = abfd;
+             bfd_link_add_undef (info->hash, inh);
+           }
 
 
-           /* If the indirect symbol has been referenced, we need to
-              push the reference down to the symbol we are
-              referencing.  */
-           if (h->type != bfd_link_hash_new)
-             {
-               row = UNDEF_ROW;
-               cycle = TRUE;
-             }
+         /* If the indirect symbol has been referenced, we need to
+            push the reference down to the symbol we are referencing.  */
+         if (h->type != bfd_link_hash_new)
+           {
+             /* ??? If inh->type == bfd_link_hash_undefweak this
+                converts inh to bfd_link_hash_undefined.  */
+             row = UNDEF_ROW;
+             cycle = TRUE;
+           }
 
 
-           h->type = bfd_link_hash_indirect;
-           h->u.i.link = inh;
-         }
+         h->type = bfd_link_hash_indirect;
+         h->u.i.link = inh;
+         /* Not setting h = h->u.i.link here means that when cycle is
+            set above we'll always go to REFC, and then cycle again
+            to the indirected symbol.  This means that any successful
+            change of an existing symbol to indirect counts as a
+            reference.  ??? That may not be correct when the existing
+            symbol was defweak.  */
          break;
 
        case SET:
          /* Add an entry to a set.  */
          break;
 
        case SET:
          /* Add an entry to a set.  */
-         if (! (*info->callbacks->add_to_set) (info, h, BFD_RELOC_CTOR,
-                                               abfd, section, value))
-           return FALSE;
+         (*info->callbacks->add_to_set) (info, h, BFD_RELOC_CTOR,
+                                         abfd, section, value);
          break;
 
        case WARNC:
          break;
 
        case WARNC:
@@ -1781,10 +1719,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
          if (h->u.i.warning != NULL
              && (abfd->flags & BFD_PLUGIN) == 0)
            {
          if (h->u.i.warning != NULL
              && (abfd->flags & BFD_PLUGIN) == 0)
            {
-             if (! (*info->callbacks->warning) (info, h->u.i.warning,
-                                                h->root.string, abfd,
-                                                NULL, 0))
-               return FALSE;
+             (*info->callbacks->warning) (info, h->u.i.warning,
+                                          h->root.string, abfd, NULL, 0);
              /* Only issue a warning once.  */
              h->u.i.warning = NULL;
            }
              /* Only issue a warning once.  */
              h->u.i.warning = NULL;
            }
@@ -1806,11 +1742,13 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
        case WARN:
          /* Warn if this symbol has been referenced already from non-IR,
             otherwise add a warning.  */
        case WARN:
          /* Warn if this symbol has been referenced already from non-IR,
             otherwise add a warning.  */
-         if (h->non_ir_ref)
+         if ((!info->lto_plugin_active
+              && (h->u.undef.next != NULL || info->hash->undefs_tail == h))
+             || h->non_ir_ref_regular
+             || h->non_ir_ref_dynamic)
            {
            {
-             if (! (*info->callbacks->warning) (info, string, h->root.string,
-                                                hash_entry_bfd (h), NULL, 0))
-               return FALSE;
+             (*info->callbacks->warning) (info, string, h->root.string,
+                                          hash_entry_bfd (h), NULL, 0);
              break;
            }
          /* Fall through.  */
              break;
            }
          /* Fall through.  */
@@ -1896,7 +1834,7 @@ _bfd_generic_final_link (bfd *abfd, struct bfd_link_info *info)
   if (! generic_add_output_symbol (abfd, &outsymalloc, NULL))
     return FALSE;
 
   if (! generic_add_output_symbol (abfd, &outsymalloc, NULL))
     return FALSE;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     {
       /* Allocate space for the output relocs for each section.  */
       for (o = abfd->sections; o != NULL; o = o->next)
     {
       /* Allocate space for the output relocs for each section.  */
       for (o = abfd->sections; o != NULL; o = o->next)
@@ -2126,7 +2064,7 @@ _bfd_generic_link_output_symbols (bfd *output_bfd,
                  /* fall through */
                case bfd_link_hash_defined:
                  sym->flags |= BSF_GLOBAL;
                  /* fall through */
                case bfd_link_hash_defined:
                  sym->flags |= BSF_GLOBAL;
-                 sym->flags &=~ BSF_CONSTRUCTOR;
+                 sym->flags &=~ (BSF_WEAK | BSF_CONSTRUCTOR);
                  sym->value = h->root.u.def.value;
                  sym->section = h->root.u.def.section;
                  break;
                  sym->value = h->root.u.def.value;
                  sym->section = h->root.u.def.section;
                  break;
@@ -2162,7 +2100,7 @@ _bfd_generic_link_output_symbols (bfd *output_bfd,
              && bfd_hash_lookup (info->keep_hash, bfd_asymbol_name (sym),
                                  FALSE, FALSE) == NULL))
        output = FALSE;
              && bfd_hash_lookup (info->keep_hash, bfd_asymbol_name (sym),
                                  FALSE, FALSE) == NULL))
        output = FALSE;
-      else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
+      else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0)
        {
          /* If this symbol is marked as occurring now, rather
             than at the end, output it now.  This is used for
        {
          /* If this symbol is marked as occurring now, rather
             than at the end, output it now.  This is used for
@@ -2200,7 +2138,7 @@ _bfd_generic_link_output_symbols (bfd *output_bfd,
                  break;
                case discard_sec_merge:
                  output = TRUE;
                  break;
                case discard_sec_merge:
                  output = TRUE;
-                 if (info->relocatable
+                 if (bfd_link_relocatable (info)
                      || ! (sym->section->flags & SEC_MERGE))
                    break;
                  /* FALLTHROUGH */
                      || ! (sym->section->flags & SEC_MERGE))
                    break;
                  /* FALLTHROUGH */
@@ -2370,7 +2308,7 @@ _bfd_generic_reloc_link_order (bfd *abfd,
 {
   arelent *r;
 
 {
   arelent *r;
 
-  if (! info->relocatable)
+  if (! bfd_link_relocatable (info))
     abort ();
   if (sec->orelocation == NULL)
     abort ();
     abort ();
   if (sec->orelocation == NULL)
     abort ();
@@ -2401,9 +2339,8 @@ _bfd_generic_reloc_link_order (bfd *abfd,
       if (h == NULL
          || ! h->written)
        {
       if (h == NULL
          || ! h->written)
        {
-         if (! ((*info->callbacks->unattached_reloc)
-                (info, link_order->u.reloc.p->u.name, NULL, NULL, 0)))
-           return FALSE;
+         (*info->callbacks->unattached_reloc)
+           (info, link_order->u.reloc.p->u.name, NULL, NULL, 0);
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
        }
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
        }
@@ -2424,7 +2361,7 @@ _bfd_generic_reloc_link_order (bfd *abfd,
 
       size = bfd_get_reloc_size (r->howto);
       buf = (bfd_byte *) bfd_zmalloc (size);
 
       size = bfd_get_reloc_size (r->howto);
       buf = (bfd_byte *) bfd_zmalloc (size);
-      if (buf == NULL)
+      if (buf == NULL && size != 0)
        return FALSE;
       rstat = _bfd_relocate_contents (r->howto, abfd,
                                      (bfd_vma) link_order->u.reloc.p->addend,
        return FALSE;
       rstat = _bfd_relocate_contents (r->howto, abfd,
                                      (bfd_vma) link_order->u.reloc.p->addend,
@@ -2437,17 +2374,13 @@ _bfd_generic_reloc_link_order (bfd *abfd,
        case bfd_reloc_outofrange:
          abort ();
        case bfd_reloc_overflow:
        case bfd_reloc_outofrange:
          abort ();
        case bfd_reloc_overflow:
-         if (! ((*info->callbacks->reloc_overflow)
-                (info, NULL,
-                 (link_order->type == bfd_section_reloc_link_order
-                  ? bfd_section_name (abfd, link_order->u.reloc.p->u.section)
-                  : link_order->u.reloc.p->u.name),
-                 r->howto->name, link_order->u.reloc.p->addend,
-                 NULL, NULL, 0)))
-           {
-             free (buf);
-             return FALSE;
-           }
+         (*info->callbacks->reloc_overflow)
+           (info, NULL,
+            (link_order->type == bfd_section_reloc_link_order
+             ? bfd_section_name (abfd, link_order->u.reloc.p->u.section)
+             : link_order->u.reloc.p->u.name),
+            r->howto->name, link_order->u.reloc.p->addend,
+            NULL, NULL, 0);
          break;
        }
       loc = link_order->offset * bfd_octets_per_byte (abfd);
          break;
        }
       loc = link_order->offset * bfd_octets_per_byte (abfd);
@@ -2601,7 +2534,7 @@ default_indirect_link_order (bfd *output_bfd,
   BFD_ASSERT (input_section->output_offset == link_order->offset);
   BFD_ASSERT (input_section->size == link_order->size);
 
   BFD_ASSERT (input_section->output_offset == link_order->offset);
   BFD_ASSERT (input_section->size == link_order->size);
 
-  if (info->relocatable
+  if (bfd_link_relocatable (info)
       && input_section->reloc_count > 0
       && output_section->orelocation == NULL)
     {
       && input_section->reloc_count > 0
       && output_section->orelocation == NULL)
     {
@@ -2610,7 +2543,8 @@ default_indirect_link_order (bfd *output_bfd,
         because somebody is attempting to link together different
         types of object files.  Handling this case correctly is
         difficult, and sometimes impossible.  */
         because somebody is attempting to link together different
         types of object files.  Handling this case correctly is
         difficult, and sometimes impossible.  */
-      (*_bfd_error_handler)
+      _bfd_error_handler
+       /* xgettext:c-format */
        (_("Attempt to do relocatable link with %s input and %s output"),
         bfd_get_target (input_bfd), bfd_get_target (output_bfd));
       bfd_set_error (bfd_error_wrong_format);
        (_("Attempt to do relocatable link with %s input and %s output"),
         bfd_get_target (input_bfd), bfd_get_target (output_bfd));
       bfd_set_error (bfd_error_wrong_format);
@@ -2695,7 +2629,7 @@ default_indirect_link_order (bfd *output_bfd,
        goto error_return;
       new_contents = (bfd_get_relocated_section_contents
                      (output_bfd, info, link_order, contents,
        goto error_return;
       new_contents = (bfd_get_relocated_section_contents
                      (output_bfd, info, link_order, contents,
-                      info->relocatable,
+                      bfd_link_relocatable (info),
                       _bfd_generic_link_get_symbols (input_bfd)));
       if (!new_contents)
        goto error_return;
                       _bfd_generic_link_get_symbols (input_bfd)));
       if (!new_contents)
        goto error_return;
@@ -2886,7 +2820,7 @@ _bfd_handle_already_linked (asection *sec,
         files over IR because the first pass may contain a
         mix of LTO and normal objects and we must keep the
         first match, be it IR or real.  */
         files over IR because the first pass may contain a
         mix of LTO and normal objects and we must keep the
         first match, be it IR or real.  */
-      if (info->loading_lto_outputs
+      if (sec->owner->lto_output
          && (l->sec->owner->flags & BFD_PLUGIN) != 0)
        {
          l->sec = sec;
          && (l->sec->owner->flags & BFD_PLUGIN) != 0)
        {
          l->sec = sec;
@@ -2896,6 +2830,7 @@ _bfd_handle_already_linked (asection *sec,
 
     case SEC_LINK_DUPLICATES_ONE_ONLY:
       info->callbacks->einfo
 
     case SEC_LINK_DUPLICATES_ONE_ONLY:
       info->callbacks->einfo
+       /* xgettext:c-format */
        (_("%B: ignoring duplicate section `%A'\n"),
         sec->owner, sec);
       break;
        (_("%B: ignoring duplicate section `%A'\n"),
         sec->owner, sec);
       break;
@@ -2905,6 +2840,7 @@ _bfd_handle_already_linked (asection *sec,
        ;
       else if (sec->size != l->sec->size)
        info->callbacks->einfo
        ;
       else if (sec->size != l->sec->size)
        info->callbacks->einfo
+         /* xgettext:c-format */
          (_("%B: duplicate section `%A' has different size\n"),
           sec->owner, sec);
       break;
          (_("%B: duplicate section `%A' has different size\n"),
           sec->owner, sec);
       break;
@@ -2914,6 +2850,7 @@ _bfd_handle_already_linked (asection *sec,
        ;
       else if (sec->size != l->sec->size)
        info->callbacks->einfo
        ;
       else if (sec->size != l->sec->size)
        info->callbacks->einfo
+         /* xgettext:c-format */
          (_("%B: duplicate section `%A' has different size\n"),
           sec->owner, sec);
       else if (sec->size != 0)
          (_("%B: duplicate section `%A' has different size\n"),
           sec->owner, sec);
       else if (sec->size != 0)
@@ -2922,15 +2859,18 @@ _bfd_handle_already_linked (asection *sec,
 
          if (!bfd_malloc_and_get_section (sec->owner, sec, &sec_contents))
            info->callbacks->einfo
 
          if (!bfd_malloc_and_get_section (sec->owner, sec, &sec_contents))
            info->callbacks->einfo
+             /* xgettext:c-format */
              (_("%B: could not read contents of section `%A'\n"),
               sec->owner, sec);
          else if (!bfd_malloc_and_get_section (l->sec->owner, l->sec,
                                                &l_sec_contents))
            info->callbacks->einfo
              (_("%B: could not read contents of section `%A'\n"),
               sec->owner, sec);
          else if (!bfd_malloc_and_get_section (l->sec->owner, l->sec,
                                                &l_sec_contents))
            info->callbacks->einfo
+             /* xgettext:c-format */
              (_("%B: could not read contents of section `%A'\n"),
               l->sec->owner, l->sec);
          else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0)
            info->callbacks->einfo
              (_("%B: could not read contents of section `%A'\n"),
               l->sec->owner, l->sec);
          else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0)
            info->callbacks->einfo
+             /* xgettext:c-format */
              (_("%B: duplicate section `%A' has different contents\n"),
               sec->owner, sec);
 
              (_("%B: duplicate section `%A' has different contents\n"),
               sec->owner, sec);
 
@@ -3164,6 +3104,43 @@ bfd_generic_define_common_symbol (bfd *output_bfd,
   return TRUE;
 }
 
   return TRUE;
 }
 
+/*
+FUNCTION
+       bfd_generic_define_start_stop
+
+SYNOPSIS
+       struct bfd_link_hash_entry *bfd_generic_define_start_stop
+         (struct bfd_link_info *info,
+          const char *symbol, asection *sec);
+
+DESCRIPTION
+       Define a __start, __stop, .startof. or .sizeof. symbol.
+       Return the symbol or NULL if no such undefined symbol exists.
+
+.#define bfd_define_start_stop(output_bfd, info, symbol, sec) \
+.       BFD_SEND (output_bfd, _bfd_define_start_stop, (info, symbol, sec))
+.
+*/
+
+struct bfd_link_hash_entry *
+bfd_generic_define_start_stop (struct bfd_link_info *info,
+                              const char *symbol, asection *sec)
+{
+  struct bfd_link_hash_entry *h;
+
+  h = bfd_link_hash_lookup (info->hash, symbol, FALSE, FALSE, TRUE);
+  if (h != NULL
+      && (h->type == bfd_link_hash_undefined
+         || h->type == bfd_link_hash_undefweak))
+    {
+      h->type = bfd_link_hash_defined;
+      h->u.def.section = sec;
+      h->u.def.value = 0;
+      return h;
+    }
+  return NULL;
+}
+
 /*
 FUNCTION
        bfd_find_version_for_sym
 /*
 FUNCTION
        bfd_find_version_for_sym
@@ -3293,3 +3270,103 @@ bfd_hide_sym_by_version (struct bfd_elf_version_tree *verdefs,
   bfd_find_version_for_sym (verdefs, sym_name, &hidden);
   return hidden;
 }
   bfd_find_version_for_sym (verdefs, sym_name, &hidden);
   return hidden;
 }
+
+/*
+FUNCTION
+       bfd_link_check_relocs
+
+SYNOPSIS
+       bfd_boolean bfd_link_check_relocs
+         (bfd *abfd, struct bfd_link_info *info);
+
+DESCRIPTION
+       Checks the relocs in ABFD for validity.
+       Does not execute the relocs.
+       Return TRUE if everything is OK, FALSE otherwise.
+       This is the external entry point to this code.
+*/
+
+bfd_boolean
+bfd_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
+{
+  return BFD_SEND (abfd, _bfd_link_check_relocs, (abfd, info));
+}
+
+/*
+FUNCTION
+       _bfd_generic_link_check_relocs
+
+SYNOPSIS
+       bfd_boolean _bfd_generic_link_check_relocs
+         (bfd *abfd, struct bfd_link_info *info);
+
+DESCRIPTION
+        Stub function for targets that do not implement reloc checking.
+       Return TRUE.
+       This is an internal function.  It should not be called from
+       outside the BFD library.
+*/
+
+bfd_boolean
+_bfd_generic_link_check_relocs (bfd *abfd ATTRIBUTE_UNUSED,
+                               struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  return TRUE;
+}
+
+/*
+FUNCTION
+       bfd_merge_private_bfd_data
+
+SYNOPSIS
+       bfd_boolean bfd_merge_private_bfd_data
+         (bfd *ibfd, struct bfd_link_info *info);
+
+DESCRIPTION
+       Merge private BFD information from the BFD @var{ibfd} to the
+       the output file BFD when linking.  Return <<TRUE>> on success,
+       <<FALSE>> on error.  Possible error returns are:
+
+       o <<bfd_error_no_memory>> -
+       Not enough memory exists to create private data for @var{obfd}.
+
+.#define bfd_merge_private_bfd_data(ibfd, info) \
+.     BFD_SEND ((info)->output_bfd, _bfd_merge_private_bfd_data, \
+.              (ibfd, info))
+*/
+
+/*
+INTERNAL_FUNCTION
+       _bfd_generic_verify_endian_match
+
+SYNOPSIS
+       bfd_boolean _bfd_generic_verify_endian_match
+         (bfd *ibfd, struct bfd_link_info *info);
+
+DESCRIPTION
+       Can be used from / for bfd_merge_private_bfd_data to check that
+       endianness matches between input and output file.  Returns
+       TRUE for a match, otherwise returns FALSE and emits an error.
+*/
+
+bfd_boolean
+_bfd_generic_verify_endian_match (bfd *ibfd, struct bfd_link_info *info)
+{
+  bfd *obfd = info->output_bfd;
+
+  if (ibfd->xvec->byteorder != obfd->xvec->byteorder
+      && ibfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN
+      && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
+    {
+      if (bfd_big_endian (ibfd))
+       _bfd_error_handler (_("%B: compiled for a big endian system "
+                             "and target is little endian"), ibfd);
+      else
+       _bfd_error_handler (_("%B: compiled for a little endian system "
+                             "and target is big endian"), ibfd);
+      bfd_set_error (bfd_error_wrong_format);
+      return FALSE;
+    }
+
+  return TRUE;
+}
This page took 0.033061 seconds and 4 git commands to generate.