PR ld/12365
authorAlan Modra <amodra@gmail.com>
Sun, 17 Apr 2011 23:15:13 +0000 (23:15 +0000)
committerAlan Modra <amodra@gmail.com>
Sun, 17 Apr 2011 23:15:13 +0000 (23:15 +0000)
PR ld/12672
bfd/
* bfd.c (BFD_PLUGIN): Define.
(BFD_FLAGS_SAVED, BFD_FLAGS_FOR_BFD_USE_MASK): Add BFD_PLUGIN.
* bfd-in2.h: Regenerate.
* elflink.c (elf_link_output_extsym): Strip undefined plugin syms.
* opncls.c (bfd_make_readable): Don't lose original bfd flags.
ld/
* ldfile.c (ldfile_try_open_bfd): Don't attempt any plugin action
when no_more_claiming.
* ldmain.c (add_archive_element): Likewise.
(multiple_definition): Remove plugin_multiple_definition call.
(notice): Remove plugin_notice call.
* ldlang.c (lang_list_insert_after, void lang_list_remove_tail): Move.
Delete prototype.
(plugin_insert): New static var.
(open_input_bfds): Only rescan libs after plugin insert point.
(lang_gc_sections): Omit plugin claimed files.
(lang_process): Set plugin_insert.  Only rescan when plugin adds
objects.
* plugin.h (no_more_claiming): Declare.
(plugin_notice, plugin_multiple_definition): Don't declare.
* plugin.c: Formatting.
(orig_notice_all, orig_allow_multiple_defs, orig_callbacks,
plugin_callbacks): New static vars.
(no_more_claiming): Make global.
(plugin_cached_allow_multiple_defs): Delete.
(plugin_get_ir_dummy_bfd): Set SEC_EXCLUDE on dummy .text section,
use newer bfd_make_section variant.  Make COMMON section too.
Error handling.  Correct setting of gp size.
(asymbol_from_plugin_symbol): Properly cast last arg of concat.
(message): Likewise for ACONCAT.
(asymbol_from_plugin_symbol): Use our COMMON section.
(get_symbols): When report_plugin_symbols, show visibility too.
(init_non_ironly_hash): Move.  Don't test non_ironly_hash.
(plugin_load_plugins): Save state of linker callbacks, set up to
call plugin_notice instead.  Call init_non_ironly_hash here.
(plugin_call_all_symbols_read): Set plugin_multiple_definition in
plugin callbacks.
(plugin_notice): Rewrite.
(plugin_multiple_definition): Make static, call original callback.
ld/testsuite/
* ld-plugin/plugin-7.d: Adjust for plugin changes.
* ld-plugin/plugin-8.d: Likewise.
* ld-plugin/plugin.exp: Pass --verbose=2 for visibility test, and
compare ld output to..
* ld-plugin/plugin-12.d: New.

13 files changed:
bfd/bfd-in2.h
bfd/bfd.c
bfd/elflink.c
bfd/opncls.c
ld/ldfile.c
ld/ldlang.c
ld/ldmain.c
ld/plugin.c
ld/plugin.h
ld/testsuite/ld-plugin/plugin-12.d [new file with mode: 0644]
ld/testsuite/ld-plugin/plugin-7.d
ld/testsuite/ld-plugin/plugin-8.d
ld/testsuite/ld-plugin/plugin.exp

index e7c410dc4ff6826c31f428fc736148606c2a380f..2c795b6cbbd430bff53e1b9b0171247d287bd242 100644 (file)
@@ -5110,14 +5110,17 @@ struct bfd
   /* Decompress sections in this BFD.  */
 #define BFD_DECOMPRESS 0x10000
 
+  /* BFD is a dummy, for plugins.  */
+#define BFD_PLUGIN 0x20000
+
   /* Flags bits to be saved in bfd_preserve_save.  */
 #define BFD_FLAGS_SAVED \
-  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS)
+  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN)
 
   /* Flags bits which are for BFD use only.  */
 #define BFD_FLAGS_FOR_BFD_USE_MASK \
   (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
-   | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT)
+   | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT)
 
   /* Currently my_archive is tested before adding origin to
      anything. I believe that this can become always an add of
index 77582ec82fe8aedb106d2ce13d0287ab274937e0..c729d63170310aa2825acad8a7cd662231b26dad 100644 (file)
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -157,14 +157,17 @@ CODE_FRAGMENT
 .  {* Decompress sections in this BFD.  *}
 .#define BFD_DECOMPRESS 0x10000
 .
+.  {* BFD is a dummy, for plugins.  *}
+.#define BFD_PLUGIN 0x20000
+.
 .  {* Flags bits to be saved in bfd_preserve_save.  *}
 .#define BFD_FLAGS_SAVED \
-.  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS)
+.  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN)
 .
 .  {* Flags bits which are for BFD use only.  *}
 .#define BFD_FLAGS_FOR_BFD_USE_MASK \
 .  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
-.   | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT)
+.   | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT)
 .
 .  {* Currently my_archive is tested before adding origin to
 .     anything. I believe that this can become always an add of
index 9ccc841da215d2394a2ed7740f8ee425d01c6d72..227550380520d9de6270e37f3db3e02408c625c6 100644 (file)
@@ -8704,6 +8704,11 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
               || h->root.type == bfd_link_hash_defweak)
           && elf_discarded_section (h->root.u.def.section))
     strip = TRUE;
+  else if ((h->root.type == bfd_link_hash_undefined
+           || h->root.type == bfd_link_hash_undefweak)
+          && h->root.u.undef.abfd != NULL
+          && (h->root.u.undef.abfd->flags & BFD_PLUGIN) != 0)
+    strip = TRUE;
   else
     strip = FALSE;
 
index 3597daee01f73abeb803529cb51757fc01fc6f43..40432000c0abc3cb3984cbc022206efd9f7ab236 100644 (file)
@@ -875,7 +875,7 @@ bfd_make_readable (bfd *abfd)
   abfd->section_count = 0;
   abfd->usrdata = NULL;
   abfd->cacheable = FALSE;
-  abfd->flags = BFD_IN_MEMORY;
+  abfd->flags |= BFD_IN_MEMORY;
   abfd->mtime_set = FALSE;
 
   abfd->target_defaulted = TRUE;
index 5bbe1d8447e020d5b384e03d33fa726d45d55a32..96a3856e4a3aad4f7184688e2f75ed17bb22cfac 100644 (file)
@@ -313,7 +313,8 @@ success:
      will be needed when and if we want to bfd_create a new
      one using this one as a template.  */
   if (bfd_check_format (entry->the_bfd, bfd_object)
-      && plugin_active_plugins_p ())
+      && plugin_active_plugins_p ()
+      && !no_more_claiming)
     {
       int fd = open (attempt, O_RDONLY | O_BINARY);
       if (fd >= 0)
index 08bfa60f69d58333a6647e57f82c21ad2c608b6f..2c07fa4d358c9344d644d76961a5d65b67b0bb91 100644 (file)
@@ -86,13 +86,6 @@ static void print_statement_list (lang_statement_union_type *,
 static void print_statements (void);
 static void print_input_section (asection *, bfd_boolean);
 static bfd_boolean lang_one_common (struct bfd_link_hash_entry *, void *);
-#ifdef ENABLE_PLUGINS
-static void lang_list_insert_after (lang_statement_list_type *destlist,
-                                   lang_statement_list_type *srclist,
-                                   lang_statement_union_type **field);
-static void lang_list_remove_tail (lang_statement_list_type *destlist,
-                                  lang_statement_list_type *origlist);
-#endif /* ENABLE_PLUGINS */
 static void lang_record_phdrs (void);
 static void lang_do_version_exports_section (void);
 static void lang_finalize_version_expr_head
@@ -3180,6 +3173,9 @@ enum open_bfd_mode
     OPEN_BFD_FORCE = 1,
     OPEN_BFD_RESCAN = 2
   };
+#ifdef ENABLE_PLUGINS
+static lang_input_statement_type *plugin_insert = NULL;
+#endif
 
 static void
 open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
@@ -3236,6 +3232,10 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
                 force it to be researched unless the whole archive
                 has been loaded already.  Do the same for a rescan.  */
              if (mode != OPEN_BFD_NORMAL
+#ifdef ENABLE_PLUGINS
+                 && ((mode & OPEN_BFD_RESCAN) == 0
+                     || plugin_insert == NULL)
+#endif
                  && !s->input_statement.whole_archive
                  && s->input_statement.loaded
                  && bfd_check_format (s->input_statement.the_bfd,
@@ -3271,6 +3271,12 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
                    }
                }
            }
+#ifdef ENABLE_PLUGINS
+         /* If we have found the point at which a plugin added new
+            files, clear plugin_insert to enable archive rescan.  */
+         if (&s->input_statement == plugin_insert)
+           plugin_insert = NULL;
+#endif
          break;
        case lang_assignment_statement_enum:
          if (s->assignment_statement.exp->assign.hidden)
@@ -6279,6 +6285,10 @@ lang_gc_sections (void)
       LANG_FOR_EACH_INPUT_STATEMENT (f)
        {
          asection *sec;
+#ifdef ENABLE_PLUGINS
+         if (f->claimed)
+           continue;
+#endif
          for (sec = f->the_bfd->sections; sec != NULL; sec = sec->next)
            if ((sec->flags & SEC_DEBUGGING) == 0)
              sec->flags &= ~SEC_EXCLUDE;
@@ -6452,6 +6462,38 @@ find_replacements_insert_point (void)
      insert point.  */
   return lastobject;
 }
+
+/* Insert SRCLIST into DESTLIST after given element by chaining
+   on FIELD as the next-pointer.  (Counterintuitively does not need
+   a pointer to the actual after-node itself, just its chain field.)  */
+
+static void
+lang_list_insert_after (lang_statement_list_type *destlist,
+                       lang_statement_list_type *srclist,
+                       lang_statement_union_type **field)
+{
+  *(srclist->tail) = *field;
+  *field = srclist->head;
+  if (destlist->tail == field)
+    destlist->tail = srclist->tail;
+}
+
+/* Detach new nodes added to DESTLIST since the time ORIGLIST
+   was taken as a copy of it and leave them in ORIGLIST.  */
+
+static void
+lang_list_remove_tail (lang_statement_list_type *destlist,
+                      lang_statement_list_type *origlist)
+{
+  union lang_statement_union **savetail;
+  /* Check that ORIGLIST really is an earlier state of DESTLIST.  */
+  ASSERT (origlist->head == destlist->head);
+  savetail = origlist->tail;
+  origlist->head = *(savetail);
+  origlist->tail = destlist->tail;
+  destlist->tail = savetail;
+  *savetail = NULL;
+}
 #endif /* ENABLE_PLUGINS */
 
 void
@@ -6484,6 +6526,7 @@ lang_process (void)
     {
       lang_statement_list_type added;
       lang_statement_list_type files, inputfiles;
+
       /* Now all files are read, let the plugin(s) decide if there
         are any more to be added to the link before we call the
         emulation's after_open hook.  We create a private list of
@@ -6509,27 +6552,29 @@ lang_process (void)
        {
          /* If so, we will insert them into the statement list immediately
             after the first input file that was claimed by the plugin.  */
-         lang_input_statement_type *claim1 = find_replacements_insert_point ();
+         plugin_insert = find_replacements_insert_point ();
          /* If a plugin adds input files without having claimed any, we
             don't really have a good idea where to place them.  Just putting
             them at the start or end of the list is liable to leave them
             outside the crtbegin...crtend range.  */
-         ASSERT (claim1 != NULL);
-         /* Splice the new statement list into the old one after claim1.  */
-         lang_list_insert_after (stat_ptr, &added, &claim1->header.next);
+         ASSERT (plugin_insert != NULL);
+         /* Splice the new statement list into the old one.  */
+         lang_list_insert_after (stat_ptr, &added,
+                                 &plugin_insert->header.next);
          /* Likewise for the file chains.  */
          lang_list_insert_after (&input_file_chain, &inputfiles,
-                                 &claim1->next_real_file);
+                                 &plugin_insert->next_real_file);
          /* We must be careful when relinking file_chain; we may need to
             insert the new files at the head of the list if the insert
             point chosen is the dummy first input file.  */
-         if (claim1->filename)
-           lang_list_insert_after (&file_chain, &files, &claim1->next);
+         if (plugin_insert->filename)
+           lang_list_insert_after (&file_chain, &files, &plugin_insert->next);
          else
            lang_list_insert_after (&file_chain, &files, &file_chain.head);
+
+         /* Rescan archives in case new undefined symbols have appeared.  */
+         open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
        }
-      /* Rescan any archives in case new undefined symbols have appeared.  */
-      open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
     }
 #endif /* ENABLE_PLUGINS */
 
@@ -6952,40 +6997,6 @@ lang_statement_append (lang_statement_list_type *list,
   list->tail = field;
 }
 
-#ifdef ENABLE_PLUGINS
-/* Insert SRCLIST into DESTLIST after given element by chaining
-   on FIELD as the next-pointer.  (Counterintuitively does not need
-   a pointer to the actual after-node itself, just its chain field.)  */
-
-static void
-lang_list_insert_after (lang_statement_list_type *destlist,
-                       lang_statement_list_type *srclist,
-                       lang_statement_union_type **field)
-{
-  *(srclist->tail) = *field;
-  *field = srclist->head;
-  if (destlist->tail == field)
-    destlist->tail = srclist->tail;
-}
-
-/* Detach new nodes added to DESTLIST since the time ORIGLIST
-   was taken as a copy of it and leave them in ORIGLIST.  */
-
-static void
-lang_list_remove_tail (lang_statement_list_type *destlist,
-                      lang_statement_list_type *origlist)
-{
-  union lang_statement_union **savetail;
-  /* Check that ORIGLIST really is an earlier state of DESTLIST.  */
-  ASSERT (origlist->head == destlist->head);
-  savetail = origlist->tail;
-  origlist->head = *(savetail);
-  origlist->tail = destlist->tail;
-  destlist->tail = savetail;
-  *savetail = NULL;
-}
-#endif /* ENABLE_PLUGINS */
-
 /* Set the output format type.  -oformat overrides scripts.  */
 
 void
index 005a89406902f8fcbf948a7b65674182762bfa98..52a4b04830a59196eb259c4d2713a8fc5d47984e 100644 (file)
@@ -804,7 +804,9 @@ add_archive_element (struct bfd_link_info *info,
      BFD, but we still want to output the original BFD filename.  */
   orig_input = *input;
 #ifdef ENABLE_PLUGINS
-  if (bfd_my_archive (abfd) != NULL && plugin_active_plugins_p ())
+  if (bfd_my_archive (abfd) != NULL
+      && plugin_active_plugins_p ()
+      && !no_more_claiming)
     {
       /* We must offer this archive member to the plugins to claim.  */
       int fd = open (bfd_my_archive (abfd)->filename, O_RDONLY | O_BINARY);
@@ -944,22 +946,11 @@ multiple_definition (struct bfd_link_info *info ATTRIBUTE_UNUSED,
                     asection *nsec,
                     bfd_vma nval)
 {
-#ifdef ENABLE_PLUGINS
-  /* We may get called back even when --allow-multiple-definition is in
-     effect, as the plugin infrastructure needs to use this hook in
-     order to swap out IR-only symbols for real ones.  In that case,
-     it will let us know not to continue by returning TRUE even if this
-     is not an IR-only vs. non-IR symbol conflict.  */
-  if (plugin_multiple_definition (info, name, obfd, osec, oval, nbfd,
-                                 nsec, nval))
-    return TRUE;
-#endif /* ENABLE_PLUGINS */
-
   /* If either section has the output_section field set to
      bfd_abs_section_ptr, it means that the section is being
      discarded, and this is not really a multiple definition at all.
-FIXME: It would be cleaner to somehow ignore symbols defined in
-sections which are being discarded.  */
+     FIXME: It would be cleaner to somehow ignore symbols defined in
+     sections which are being discarded.  */
   if ((osec->output_section != NULL
        && ! bfd_is_abs_section (osec)
        && bfd_is_abs_section (osec->output_section))
@@ -1456,17 +1447,8 @@ notice (struct bfd_link_info *info,
       return TRUE;
     }
 
-#ifdef ENABLE_PLUGINS
-  /* We should hide symbols in the dummy IR BFDs from the nocrossrefs list
-     and let the real object files that are generated and added later trip
-     the error instead.  Similarly would be better to trace the real symbol
-     from the real file than the temporary dummy.  */
-  if (!plugin_notice (info, name, abfd, section, value))
-    return TRUE;
-#endif /* ENABLE_PLUGINS */
-
   if (info->notice_hash != NULL
-       && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)
+      && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)
     {
       if (bfd_is_und_section (section))
        einfo ("%B: reference to %s\n", abfd, name);
index 6a14f22a4b5208c29f0873b99e77cba3817a6cbe..07f3afe9981a6000d687a4e71e408fc36ca4b2bd 100644 (file)
@@ -97,15 +97,18 @@ static const char *error_plugin = NULL;
    cases when establishing symbol resolutions.  */
 static struct bfd_hash_table *non_ironly_hash = NULL;
 
+/* State of linker "notice" and "multiple_definition" interfaces
+   before we poked at them.  */
+static bfd_boolean orig_notice_all;
+static bfd_boolean orig_allow_multiple_defs;
+
+/* Original linker callbacks, and the plugin version.  */
+static const struct bfd_link_callbacks *orig_callbacks;
+static struct bfd_link_callbacks plugin_callbacks;
+
 /* Set at all symbols read time, to avoid recursively offering the plugin
    its own newly-added input files and libs to claim.  */
-static bfd_boolean no_more_claiming = FALSE;
-
-/* If the --allow-multiple-definition command-line option is active, we
-   have to disable it so that BFD always calls our hook, and simulate the
-   effect (when not resolving IR vs. real symbols) ourselves by ensuring
-   TRUE is returned from the hook.  */
-static bfd_boolean plugin_cached_allow_multiple_defs = FALSE;
+bfd_boolean no_more_claiming = FALSE;
 
 /* List of tags to set in the constant leading part of the tv array. */
 static const enum ld_plugin_tag tv_header_tags[] =
@@ -130,6 +133,17 @@ static const enum ld_plugin_tag tv_header_tags[] =
 /* How many entries in the constant leading part of the tv array.  */
 static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags);
 
+/* Forward references.  */
+static bfd_boolean plugin_notice (struct bfd_link_info *info,
+                                 const char *name, bfd *abfd,
+                                 asection *section, bfd_vma value);
+static bfd_boolean plugin_multiple_definition (struct bfd_link_info *info,
+                                              const char *name,
+                                              bfd *obfd, asection *osec,
+                                              bfd_vma oval, bfd *nbfd,
+                                              asection *nsec,
+                                              bfd_vma nval);
+
 #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
 
 #define RTLD_NOW 0     /* Dummy value.  */
@@ -225,24 +239,30 @@ plugin_opt_plugin_arg (const char *arg)
 bfd *
 plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
 {
-  asection *sec;
   bfd *abfd;
 
   bfd_use_reserved_id = 1;
-  abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *)NULL),
+  abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *) NULL),
                     srctemplate);
-  bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
-  bfd_make_writable (abfd);
-  bfd_copy_private_bfd_data (srctemplate, abfd);
-  bfd_set_gp_size (abfd, bfd_get_gp_size (abfd));
-  /* Create a minimal set of sections to own the symbols.  */
-  sec = bfd_make_section_old_way (abfd, ".text");
-  bfd_set_section_flags (abfd, sec,
-                        (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
-                         | SEC_ALLOC | SEC_LOAD | SEC_KEEP));
-  sec->output_section = sec;
-  sec->output_offset = 0;
-  return abfd;
+  if (abfd != NULL)
+    {
+      abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN;
+      bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
+      bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate));
+      if (bfd_make_writable (abfd)
+         && bfd_copy_private_bfd_data (srctemplate, abfd))
+       {
+         flagword flags;
+
+         /* Create sections to own the symbols.  */
+         flags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
+                  | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE);
+         if (bfd_make_section_anyway_with_flags (abfd, ".text", flags))
+           return abfd;
+       }
+    }
+  einfo (_("could not create dummy IR bfd: %F%E\n"));
+  return NULL;
 }
 
 /* Check if the BFD passed in is an IR dummy object file.  */
@@ -254,9 +274,9 @@ is_ir_dummy_bfd (const bfd *abfd)
      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))->claimed;
+  return (abfd
+         && abfd->usrdata
+         && ((lang_input_statement_type *)(abfd->usrdata))->claimed);
 }
 
 /* Helpers to convert between BFD and GOLD symbol formats.  */
@@ -269,7 +289,7 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
 
   asym->the_bfd = abfd;
   asym->name = (ldsym->version
-               ? concat (ldsym->name, "@", ldsym->version, NULL)
+               ? concat (ldsym->name, "@", ldsym->version, (const char *) NULL)
                : ldsym->name);
   asym->value = 0;
   switch (ldsym->def)
@@ -487,9 +507,9 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
       /* Find out which section owns the symbol.  Since it's not undef,
         it must have an owner; if it's not a common symbol, both defs
         and weakdefs keep it in the same place. */
-      owner_sec = (blhe->type == bfd_link_hash_common)
-       ? blhe->u.c.p->section
-       : blhe->u.def.section;
+      owner_sec = (blhe->type == bfd_link_hash_common
+                  ? blhe->u.c.p->section
+                  : blhe->u.def.section);
 
       /* We need to know if the sym is referenced from non-IR files.  Or
         even potentially-referenced, perhaps in a future final link if
@@ -539,10 +559,12 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
                            ? LDPR_PREEMPTED_IR
                            : LDPR_PREEMPTED_REG);
 
-report_symbol:
+    report_symbol:
       if (report_plugin_symbols)
-       einfo ("%P: %B: symbol `%s' definition: %d, resolution: %d\n",
-              abfd, syms[n].name, syms[n].def, syms[n].resolution);
+       einfo (_("%P: %B: symbol `%s' "
+                "definition: %d, visibility: %d, resolution: %d\n"),
+              abfd, syms[n].name,
+              syms[n].def, syms[n].visibility, syms[n].resolution);
     }
   return LDPS_OK;
 }
@@ -599,14 +621,13 @@ message (int level, const char *format, ...)
     case LDPL_FATAL:
     case LDPL_ERROR:
     default:
-       {
-         char *newfmt = ACONCAT ((level == LDPL_FATAL
-                                  ? "%P%F: " : "%P%X: ",
-                                  format, "\n", NULL));
-         fflush (stdout);
-         vfinfo (stderr, newfmt, args, TRUE);
-         fflush (stderr);
-       }
+      {
+       char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%P%F: " : "%P%X: ",
+                                format, "\n", (const char *) NULL));
+       fflush (stdout);
+       vfinfo (stderr, newfmt, args, TRUE);
+       fflush (stderr);
+      }
       break;
     }
 
@@ -714,6 +735,27 @@ plugin_active_plugins_p (void)
   return plugins_list != NULL;
 }
 
+/* Init the non_ironly hash table.  */
+static void
+init_non_ironly_hash (void)
+{
+  struct bfd_sym_chain *sym;
+
+  non_ironly_hash
+    = (struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table));
+  if (!bfd_hash_table_init_n (non_ironly_hash,
+                             bfd_hash_newfunc,
+                             sizeof (struct bfd_hash_entry),
+                             61))
+    einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
+
+  for (sym = &entry_symbol; sym != NULL; sym = sym->next)
+    if (sym->name
+       && !bfd_hash_lookup (non_ironly_hash, sym->name, TRUE, TRUE))
+      einfo (_("%P%X: hash table failure adding symbol %s\n"),
+            sym->name);
+}
+
 /* Load up and initialise all plugins after argument parsing.  */
 int
 plugin_load_plugins (void)
@@ -761,7 +803,13 @@ plugin_load_plugins (void)
   /* Since plugin(s) inited ok, assume they're going to want symbol
      resolutions, which needs us to track which symbols are referenced
      by non-IR files using the linker's notice callback.  */
+  orig_notice_all = link_info.notice_all;
+  orig_callbacks = link_info.callbacks;
+  plugin_callbacks = *orig_callbacks;
+  plugin_callbacks.notice = &plugin_notice;
   link_info.notice_all = TRUE;
+  link_info.callbacks = &plugin_callbacks;
+  init_non_ironly_hash ();
 
   return 0;
 }
@@ -803,8 +851,9 @@ plugin_call_all_symbols_read (void)
      as the plugin infrastructure relies on the multiple_definition
      callback to swap out the dummy IR-only BFDs for new real ones
      when it starts opening the files added during this callback.  */
-  plugin_cached_allow_multiple_defs = link_info.allow_multiple_definition;
+  orig_allow_multiple_defs = link_info.allow_multiple_definition;
   link_info.allow_multiple_definition = FALSE;
+  plugin_callbacks.multiple_definition = &plugin_multiple_definition;
 
   while (curplug)
     {
@@ -847,30 +896,6 @@ plugin_call_cleanup (void)
              plugin_error_plugin ());
 }
 
-/* Lazily init the non_ironly hash table.  */
-static void
-init_non_ironly_hash (void)
-{
-  struct bfd_sym_chain *sym;
-
-  if (non_ironly_hash == NULL)
-    {
-      non_ironly_hash =
-       (struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table));
-      if (!bfd_hash_table_init_n (non_ironly_hash,
-                                 bfd_hash_newfunc,
-                                 sizeof (struct bfd_hash_entry),
-                                 61))
-       einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
-
-      for (sym = &entry_symbol; sym != NULL; sym = sym->next)
-       if (sym->name
-           && !bfd_hash_lookup (non_ironly_hash, sym->name, TRUE, TRUE))
-         einfo (_("%P%X: hash table failure adding symbol %s\n"),
-                sym->name);
-    }
-}
-
 /* To determine which symbols should be resolved LDPR_PREVAILING_DEF
    and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
    the linker adds them to the linker hash table.  If we see a symbol
@@ -879,32 +904,38 @@ init_non_ironly_hash (void)
    it was referenced only by IR files.  We have to notice_all symbols,
    because we won't necessarily know until later which ones will be
    contributed by IR files.  */
-bfd_boolean
-plugin_notice (struct bfd_link_info *info ATTRIBUTE_UNUSED,
-              const char *name, bfd *abfd,
-              asection *section, bfd_vma value ATTRIBUTE_UNUSED)
+static bfd_boolean
+plugin_notice (struct bfd_link_info *info,
+              const char *name,
+              bfd *abfd,
+              asection *section,
+              bfd_vma value)
 {
-  bfd_boolean is_ref = bfd_is_und_section (section);
-  bfd_boolean is_dummy = is_ir_dummy_bfd (abfd);
-  init_non_ironly_hash ();
-  /* We only care about refs, not defs, indicated by section pointing
-     to the undefined section (according to the bfd linker notice callback
-     interface definition).  */
-  if (is_ref && !is_dummy)
-    {
-      /* This is a ref from a non-IR file, so note the ref'd symbol
-        in the non-IR-only hash.  */
-      if (!bfd_hash_lookup (non_ironly_hash, name, TRUE, TRUE))
-       einfo (_("%P%X: %s: hash table failure adding symbol %s\n"),
-              abfd->filename, name);
-    }
-  else if (!is_ref && is_dummy)
+  if (name != NULL)
     {
-      /* No further processing since this is a def from an IR dummy BFD.  */
-      return FALSE;
+      /* No further processing if this def/ref is from an IR dummy BFD.  */
+      if (is_ir_dummy_bfd (abfd))
+       return TRUE;
+
+      /* We only care about refs, not defs, indicated by section
+        pointing to the undefined section (according to the bfd
+        linker notice callback interface definition).  */
+      if (bfd_is_und_section (section))
+       {
+         /* This is a ref from a non-IR file, so note the ref'd
+            symbol in the non-IR-only hash.  */
+         if (!bfd_hash_lookup (non_ironly_hash, name, TRUE, TRUE))
+           einfo (_("%P%X: %s: hash table failure adding symbol %s\n"),
+                  abfd->filename, name);
+       }
     }
 
   /* Continue with cref/nocrossref/trace-sym processing.  */
+  if (name == NULL
+      || orig_notice_all
+      || (info->notice_hash != NULL
+         && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
+    return (*orig_callbacks->notice) (info, name, abfd, section, value);
   return TRUE;
 }
 
@@ -917,10 +948,9 @@ plugin_notice (struct bfd_link_info *info ATTRIBUTE_UNUSED,
    real BFD.  We return true if this was not-really-a-clash because
    we've fixed it up, or anyway if --allow-multiple-definition was in
    effect (before we disabled it to ensure we got called back).  */
-bfd_boolean
+static bfd_boolean
 plugin_multiple_definition (struct bfd_link_info *info, const char *name,
-                           bfd *obfd, asection *osec ATTRIBUTE_UNUSED,
-                           bfd_vma oval ATTRIBUTE_UNUSED,
+                           bfd *obfd, asection *osec, bfd_vma oval,
                            bfd *nbfd, asection *nsec, bfd_vma nval)
 {
   if (is_ir_dummy_bfd (obfd))
@@ -937,5 +967,10 @@ plugin_multiple_definition (struct bfd_link_info *info, const char *name,
       blhe->u.def.value = nval;
       return TRUE;
     }
-  return plugin_cached_allow_multiple_defs;
+
+  if (orig_allow_multiple_defs)
+    return TRUE;
+
+  return (*orig_callbacks->multiple_definition) (info, name, obfd, osec, oval,
+                                                nbfd, nsec, nval);
 }
index 6ba8fa89c9c0aabce2418b576e5dc8d5e4698d8a..7b39e729ea9c115c9afcfb2c2b72898baf3bf629 100644 (file)
 /* Report plugin symbols.  */
 extern bfd_boolean report_plugin_symbols;
 
+/* Set at all symbols read time, to avoid recursively offering the plugin
+   its own newly-added input files and libs to claim.  */
+extern bfd_boolean no_more_claiming;
+
 /* This is the only forward declaration we need to avoid having
    to include the plugin-api.h header in order to use this file.  */
 struct ld_plugin_input_file;
@@ -62,17 +66,4 @@ extern void plugin_call_cleanup (void);
    add_symbols hook has been called so that it can be read when linking.  */
 extern bfd *plugin_get_ir_dummy_bfd (const char *name, bfd *template);
 
-/* Notice-symbol bfd linker callback hook.  */
-extern bfd_boolean plugin_notice (struct bfd_link_info *info,
-                                 const char *name, bfd *abfd,
-                                 asection *section, bfd_vma value);
-
-/* Multiple-definition bfd linker callback hook.  */
-extern bfd_boolean plugin_multiple_definition (struct bfd_link_info *info,
-                                              const char *name,
-                                              bfd *obfd, asection *osec,
-                                              bfd_vma oval, bfd *nbfd,
-                                              asection *nsec,
-                                              bfd_vma nval);
-
 #endif /* !def GLD_PLUGIN_H */
diff --git a/ld/testsuite/ld-plugin/plugin-12.d b/ld/testsuite/ld-plugin/plugin-12.d
new file mode 100644 (file)
index 0000000..10d7725
--- /dev/null
@@ -0,0 +1,6 @@
+#...
+.*: symbol `func' definition: 0, visibility: 0, resolution: 2
+.*: symbol `func1' definition: 0, visibility: 1, resolution: 3
+.*: symbol `func2' definition: 0, visibility: 2, resolution: 3
+.*: symbol `func3' definition: 0, visibility: 3, resolution: 3
+#pass
index 75f25e01b27e2e979399b2bfc102381207da382e..ba0ed946641a1d9aed7bfb1833260efdd024d474 100644 (file)
@@ -26,5 +26,6 @@ hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED
 hook called: claim_file tmpdir/text.o \[@0/.* not claimed
 #...
 hook called: all symbols read.
+`func' referenced in section `\.text' of tmpdir/main.o: defined in discarded section .*
 hook called: cleanup.
 #...
index e72b0392c037798a4c13d9da7abf2a03f5f2db4a..8411c313e9b329ea43ed45748176ba8162332312 100644 (file)
@@ -30,5 +30,6 @@ hook called: claim_file tmpdir/text.o \[@0/.* not claimed
 hook called: all symbols read.
 Sym: '_?func' Resolution: LDPR_PREVAILING_DEF
 Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY
+`func' referenced in section `\.text' of tmpdir/main.o: defined in discarded section .*
 hook called: cleanup.
 #...
index 8952f1dec26cf8f4aec43f05842327814da9ae41..02319bfb1a0df9f7ff370a059ebe2f42bc84fd6b 100644 (file)
@@ -152,8 +152,8 @@ set plugin_extra_elf_tests [list \
                        -plugin-opt sym:${_}func2::0:2:0 \
                        -plugin-opt sym:${_}func3::0:3:0 \
                        -plugin-opt dumpresolutions \
-    $testobjfiles $libs" "" "" {{ld plugin-ignore.d} \
-                               {readelf -s plugin-vis-1.d}} "main.x" ] \
+                       -plugin-opt add:tmpdir/func.o \
+    $testobjfiles $libs --verbose=2" "" "" {{ld plugin-12.d}} "main.x" ] \
 ]
 
 if { !$can_compile || $failed_compile } {