]> Git Repo - binutils.git/blobdiff - ld/ldmain.c
Applied patch series for LD plugin interface (six parts).
[binutils.git] / ld / ldmain.c
index 3ba0592b78f1f3c7f82b1ef81e839e383e871f3b..04b56335e87cff50f130309b8053fde151f0b650 100644 (file)
 #include "ldfile.h"
 #include "ldemul.h"
 #include "ldctor.h"
+#ifdef ENABLE_PLUGINS
+#include "plugin.h"
+#include "plugin-api.h"
+#include "libbfd.h"
+#endif /* ENABLE_PLUGINS */
 
 /* Somewhere above, sys/stat.h got included.  */
 #if !defined(S_ISDIR) && defined(S_IFDIR)
@@ -116,7 +121,7 @@ static const char *get_sysroot
 static char *get_emulation
   (int, char **);
 static bfd_boolean add_archive_element
-  (struct bfd_link_info *, bfd *, const char *);
+  (struct bfd_link_info *, bfd *, const char *, bfd **);
 static bfd_boolean multiple_definition
   (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma,
    bfd *, asection *, bfd_vma);
@@ -253,6 +258,7 @@ main (int argc, char **argv)
   command_line.warn_mismatch = TRUE;
   command_line.warn_search_mismatch = TRUE;
   command_line.check_section_addresses = -1;
+  command_line.disable_target_specific_optimizations = -1;
 
   /* We initialize DEMANGLING based on the environment variable
      COLLECT_NO_DEMANGLE.  The gcc collect2 program will demangle the
@@ -473,6 +479,12 @@ main (int argc, char **argv)
 
   lang_finish ();
 
+#ifdef ENABLE_PLUGINS
+  /* Now everything is finished, we can tell the plugins to clean up.  */
+  if (plugin_call_cleanup ())
+    info_msg (_("%P: %s: error in plugin cleanup (ignored)\n"), plugin_error_plugin ());
+#endif /* ENABLE_PLUGINS */
+
   /* Even if we're producing relocatable output, some non-fatal errors should
      be reported in the exit status.  (What non-fatal errors, if any, do we
      want to ignore for relocatable output?)  */
@@ -780,9 +792,11 @@ add_keepsyms_file (const char *filename)
 static bfd_boolean
 add_archive_element (struct bfd_link_info *info,
                     bfd *abfd,
-                    const char *name)
+                    const char *name,
+                    bfd **subsbfd ATTRIBUTE_UNUSED)
 {
   lang_input_statement_type *input;
+  lang_input_statement_type orig_input;
 
   input = (lang_input_statement_type *)
       xcalloc (1, sizeof (lang_input_statement_type));
@@ -790,6 +804,52 @@ add_archive_element (struct bfd_link_info *info,
   input->local_sym_name = abfd->filename;
   input->the_bfd = abfd;
 
+  /* Save the original data for trace files/tries below, as plugins
+     (if enabled) may possibly alter it to point to a replacement
+     BFD, but we still want to output the original BFD filename.  */
+  orig_input = *input;
+#ifdef ENABLE_PLUGINS
+  if (bfd_my_archive (abfd) != NULL)
+    {
+      /* We must offer this archive member to the plugins to claim.  */
+      int fd = open (bfd_my_archive (abfd)->filename, O_RDONLY | O_BINARY);
+      if (fd >= 0)
+       {
+         struct ld_plugin_input_file file;
+         int claimed = 0;
+         /* Offset and filesize must refer to the individual archive
+            member, not the whole file, and must exclude the header.
+            Fortunately for us, that is how the data is stored in the
+            origin field of the bfd and in the arelt_data.  */
+         file.name = bfd_my_archive (abfd)->filename;
+         file.offset = abfd->origin;
+         file.filesize = arelt_size (abfd);
+         file.fd = fd;
+         /* We create a dummy BFD, initially empty, to house
+            whatever symbols the plugin may want to add.  */
+         file.handle = plugin_get_ir_dummy_bfd (abfd->filename, abfd);
+         if (plugin_call_claim_file (&file, &claimed))
+           einfo (_("%P%F: %s: plugin reported error claiming file\n"),
+             plugin_error_plugin ());
+         if (claimed)
+           {
+             /* Substitute the dummy BFD.  */
+             input->the_bfd = file.handle;
+             input->claimed = TRUE;
+             bfd_make_readable (input->the_bfd);
+             *subsbfd = input->the_bfd;
+           }
+         else
+           {
+             /* Abandon the dummy BFD.  */
+             bfd_close_all_done (file.handle);
+             close (fd);
+             input->claimed = FALSE;
+           }
+       }
+    }
+#endif /* ENABLE_PLUGINS */
+
   ldlang_add_file (input);
 
   if (config.map_file != NULL)
@@ -870,8 +930,7 @@ add_archive_element (struct bfd_link_info *info,
     }
 
   if (trace_files || trace_file_tries)
-    info_msg ("%I\n", input);
-
+    info_msg ("%I\n", &orig_input);
   return TRUE;
 }
 
@@ -888,6 +947,17 @@ 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.
@@ -906,10 +976,10 @@ multiple_definition (struct bfd_link_info *info ATTRIBUTE_UNUSED,
   if (obfd != NULL)
     einfo (_("%D: first defined here\n"), obfd, osec, oval);
 
-  if (command_line.relax)
+  if (RELAXATION_ENABLED)
     {
       einfo (_("%P: Disabling relaxation: it will not work with multiple definitions\n"));
-      command_line.relax = 0;
+      command_line.disable_target_specific_optimizations = -1;
     }
 
   return TRUE;
@@ -1103,7 +1173,7 @@ warning_callback (struct bfd_link_info *info ATTRIBUTE_UNUSED,
     einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
   else
     {
-      struct warning_callback_info info;
+      struct warning_callback_info cinfo;
 
       /* Look through the relocs to see if we can find a plausible
         address.  */
@@ -1111,13 +1181,13 @@ warning_callback (struct bfd_link_info *info ATTRIBUTE_UNUSED,
       if (!bfd_generic_link_read_symbols (abfd))
        einfo (_("%B%F: could not read symbols: %E\n"), abfd);
 
-      info.found = FALSE;
-      info.warning = warning;
-      info.symbol = symbol;
-      info.asymbols = bfd_get_outsymbols (abfd);
-      bfd_map_over_sections (abfd, warning_find_reloc, &info);
+      cinfo.found = FALSE;
+      cinfo.warning = warning;
+      cinfo.symbol = symbol;
+      cinfo.asymbols = bfd_get_outsymbols (abfd);
+      bfd_map_over_sections (abfd, warning_find_reloc, &cinfo);
 
-      if (! info.found)
+      if (! cinfo.found)
        einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
     }
 
@@ -1370,7 +1440,10 @@ unattached_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED,
 
 /* This is called if link_info.notice_all is set, or when a symbol in
    link_info.notice_hash is found.  Symbols are put in notice_hash
-   using the -y option.  */
+   using the -y option, while notice_all is set if the --cref option
+   has been supplied, or if there are any NOCROSSREFS sections in the
+   linker script; and if plugins are active, since they need to monitor
+   all references from non-IR files.  */
 
 static bfd_boolean
 notice (struct bfd_link_info *info,
@@ -1386,9 +1459,17 @@ notice (struct bfd_link_info *info,
       return TRUE;
     }
 
-  if (! info->notice_all
-      || (info->notice_hash != NULL
-         && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
+#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)
     {
       if (bfd_is_und_section (section))
        einfo ("%B: reference to %s\n", abfd, name);
This page took 0.030994 seconds and 4 git commands to generate.