build as needed
[platform/upstream/binutils.git] / ld / plugin.c
index 0d5339f..f02a97f 100644 (file)
@@ -1,5 +1,5 @@
 /* Plugin control for the GNU linker.
-   Copyright 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+   Copyright (C) 2010-2014 Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
 
@@ -127,8 +127,9 @@ static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags);
 
 /* Forward references.  */
 static bfd_boolean plugin_notice (struct bfd_link_info *,
-                                 struct bfd_link_hash_entry *, bfd *,
-                                 asection *, bfd_vma, flagword, const char *);
+                                 struct bfd_link_hash_entry *,
+                                 struct bfd_link_hash_entry *,
+                                 bfd *, asection *, bfd_vma, flagword);
 
 #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
 
@@ -217,6 +218,17 @@ plugin_opt_plugin_arg (const char *arg)
   if (!last_plugin)
     return set_plugin_error (_("<no plugin>"));
 
+  /* Ignore -pass-through= from GCC driver.  */
+  if (*arg == '-')
+    {
+      const char *p = arg + 1;
+
+      if (*p == '-')
+       ++p;
+      if (strncmp (p, "pass-through=", 13) == 0)
+       return 0;
+    }
+
   newarg = xmalloc (sizeof *newarg);
   newarg->arg = arg;
   newarg->next = NULL;
@@ -259,17 +271,12 @@ plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
 }
 
 /* Check if the BFD passed in is an IR dummy object file.  */
-static bfd_boolean
+static inline bfd_boolean
 is_ir_dummy_bfd (const bfd *abfd)
 {
   /* ABFD can sometimes legitimately be NULL, e.g. when called from one
-     of the linker callbacks for a symbol in the *ABS* or *UND* sections.
-     Likewise, the usrdata field may be NULL if ABFD was added by the
-     backend without a corresponding input statement, as happens e.g.
-     when processing DT_NEEDED dependencies.  */
-  return (abfd
-         && abfd->usrdata
-         && ((lang_input_statement_type *)(abfd->usrdata))->flags.claimed);
+     of the linker callbacks for a symbol in the *ABS* or *UND* sections.  */
+  return abfd != NULL && (abfd->flags & BFD_PLUGIN) != 0;
 }
 
 /* Helpers to convert between BFD and GOLD symbol formats.  */
@@ -830,6 +837,7 @@ plugin_load_plugins (void)
   plugin_callbacks = *orig_callbacks;
   plugin_callbacks.notice = &plugin_notice;
   link_info.notice_all = TRUE;
+  link_info.lto_plugin_active = TRUE;
   link_info.callbacks = &plugin_callbacks;
 }
 
@@ -950,16 +958,21 @@ plugin_call_cleanup (void)
 static bfd_boolean
 plugin_notice (struct bfd_link_info *info,
               struct bfd_link_hash_entry *h,
+              struct bfd_link_hash_entry *inh,
               bfd *abfd,
               asection *section,
               bfd_vma value,
-              flagword flags,
-              const char *string)
+              flagword flags)
 {
+  struct bfd_link_hash_entry *orig_h = h;
+
   if (h != NULL)
     {
       bfd *sym_bfd;
 
+      if (h->type == bfd_link_hash_warning)
+       h = h->u.i.link;
+
       /* Nothing to do here if this def/ref is from an IR dummy BFD.  */
       if (is_ir_dummy_bfd (abfd))
        ;
@@ -969,16 +982,15 @@ plugin_notice (struct bfd_link_info *info,
       else if (bfd_is_ind_section (section)
               || (flags & BSF_INDIRECT) != 0)
        {
+         /* ??? Some of this is questionable.  See comments in
+            _bfd_generic_link_add_one_symbol for case IND.  */
          if (h->type != bfd_link_hash_new)
            {
-             struct bfd_link_hash_entry *inh;
-
              h->non_ir_ref = TRUE;
-             inh = bfd_wrapped_link_hash_lookup (abfd, info, string, FALSE,
-                                                 FALSE, FALSE);
-             if (inh != NULL)
-               inh->non_ir_ref = TRUE;
+             inh->non_ir_ref = TRUE;
            }
+         else if (inh->type == bfd_link_hash_new)
+           inh->non_ir_ref = TRUE;
        }
 
       /* Nothing to do here for warning symbols.  */
@@ -1019,23 +1031,12 @@ plugin_notice (struct bfd_link_info *info,
     }
 
   /* Continue with cref/nocrossref/trace-sym processing.  */
-  if (h == NULL
+  if (orig_h == NULL
       || orig_notice_all
       || (info->notice_hash != NULL
-         && bfd_hash_lookup (info->notice_hash, h->root.string,
+         && bfd_hash_lookup (info->notice_hash, orig_h->root.string,
                              FALSE, FALSE) != NULL))
-    return (*orig_callbacks->notice) (info, h,
-                                     abfd, section, value, flags, string);
+    return (*orig_callbacks->notice) (info, orig_h, inh,
+                                     abfd, section, value, flags);
   return TRUE;
 }
-
-/* Return true if bfd is a dynamic library that should be reloaded.  */
-
-bfd_boolean
-plugin_should_reload (bfd *abfd)
-{
-  return ((abfd->flags & DYNAMIC) != 0
-         && bfd_get_flavour (abfd) == bfd_target_elf_flavour
-         && bfd_get_format (abfd) == bfd_object
-         && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0);
-}