]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - ld/plugin.c
hppa: Implement PA 2.0 symbolic relocations for long displacements
[thirdparty/binutils-gdb.git] / ld / plugin.c
index adaba32edaa19d4e6ec0fa73385d8348f18efcfb..13d29d6b09ffa9a6fd6c736f69ef2a426e8247c6 100644 (file)
@@ -1,5 +1,5 @@
 /* Plugin control for the GNU linker.
-   Copyright (C) 2010-2021 Free Software Foundation, Inc.
+   Copyright (C) 2010-2024 Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils.
 
@@ -51,7 +51,9 @@
 #if !(defined(errno) || defined(_MSC_VER) && defined(_INC_ERRNO))
 extern int errno;
 #endif
-#if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
+#if defined (HAVE_DLFCN_H)
+#include <dlfcn.h>
+#elif defined (HAVE_WINDOWS_H)
 #include <windows.h>
 #endif
 
@@ -85,6 +87,7 @@ typedef struct plugin
   size_t n_args;
   /* The plugin's event handlers.  */
   ld_plugin_claim_file_handler claim_file_handler;
+  ld_plugin_claim_file_handler_v2 claim_file_handler_v2;
   ld_plugin_all_symbols_read_handler all_symbols_read_handler;
   ld_plugin_cleanup_handler cleanup_handler;
   /* TRUE if the cleanup handlers have been called.  */
@@ -102,7 +105,10 @@ typedef struct view_buffer
    pointer.  */
 typedef struct plugin_input_file
 {
+  /* The dummy BFD.  */
   bfd *abfd;
+  /* The original input BFD.  Non-NULL if it is an archive member.  */
+  bfd *ibfd;
   view_buffer_t view_buffer;
   char *name;
   int fd;
@@ -154,6 +160,7 @@ static const enum ld_plugin_tag tv_header_tags[] =
   LDPT_LINKER_OUTPUT,
   LDPT_OUTPUT_NAME,
   LDPT_REGISTER_CLAIM_FILE_HOOK,
+  LDPT_REGISTER_CLAIM_FILE_HOOK_V2,
   LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
   LDPT_REGISTER_CLEANUP_HOOK,
   LDPT_ADD_SYMBOLS,
@@ -176,7 +183,7 @@ static bool plugin_notice (struct bfd_link_info *,
                           struct bfd_link_hash_entry *,
                           bfd *, asection *, bfd_vma, flagword);
 
-static bfd_cleanup plugin_object_p (bfd *);
+static bfd_cleanup plugin_object_p (bfd *, bool);
 
 #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
 
@@ -462,6 +469,15 @@ register_claim_file (ld_plugin_claim_file_handler handler)
   return LDPS_OK;
 }
 
+/* Register a claim-file version 2 handler.  */
+static enum ld_plugin_status
+register_claim_file_v2 (ld_plugin_claim_file_handler_v2 handler)
+{
+  ASSERT (called_plugin);
+  called_plugin->claim_file_handler_v2 = handler;
+  return LDPS_OK;
+}
+
 /* Register an all-symbols-read handler.  */
 static enum ld_plugin_status
 register_all_symbols_read (ld_plugin_all_symbols_read_handler handler)
@@ -490,7 +506,9 @@ add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms)
   int n;
 
   ASSERT (called_plugin);
-  symptrs = xmalloc (nsyms * sizeof *symptrs);
+  symptrs = bfd_alloc (abfd, nsyms * sizeof *symptrs);
+  if (symptrs == NULL)
+    return LDPS_ERR;
   for (n = 0; n < nsyms; n++)
     {
       enum ld_plugin_status rv;
@@ -498,6 +516,8 @@ add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms)
 
       bfdsym = bfd_make_empty_symbol (abfd);
       symptrs[n] = bfdsym;
+      if (bfdsym == NULL)
+       return LDPS_ERR;
       rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n);
       if (rv != LDPS_OK)
        return rv;
@@ -605,17 +625,25 @@ get_view (const void *handle, const void **viewp)
   return LDPS_OK;
 }
 
+/* Release plugin file descriptor.  */
+
+static void
+release_plugin_file_descriptor (plugin_input_file_t *input)
+{
+  if (input->fd != -1)
+    {
+      bfd_plugin_close_file_descriptor (input->ibfd, input->fd);
+      input->fd = -1;
+    }
+}
+
 /* Release the input file.  */
 static enum ld_plugin_status
 release_input_file (const void *handle)
 {
   plugin_input_file_t *input = (plugin_input_file_t *) handle;
   ASSERT (called_plugin);
-  if (input->fd != -1)
-    {
-      close (input->fd);
-      input->fd = -1;
-    }
+  release_plugin_file_descriptor (input);
   return LDPS_OK;
 }
 
@@ -636,7 +664,7 @@ is_visible_from_outside (struct ld_plugin_symbol *lsym,
                                   blhe->root.string))
        return false;
       /* Only ELF symbols really have visibility.  */
-      if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour)
+      if (is_elf_hash_table (link_info.hash))
        {
          struct elf_link_hash_entry *el = (struct elf_link_hash_entry *)blhe;
          int vis = ELF_ST_VISIBILITY (el->other);
@@ -852,8 +880,11 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms,
          /* We need to know if the sym is referenced from non-IR files.  Or
             even potentially-referenced, perhaps in a future final link if
             this is a partial one, perhaps dynamically at load-time if the
-            symbol is externally visible.  Also check for wrapper symbol.  */
-         if (blhe->non_ir_ref_regular || wrap_status == wrapper)
+            symbol is externally visible.  Also check for __real_SYM
+            reference and wrapper symbol.  */
+         if (blhe->non_ir_ref_regular
+             || blhe->ref_real
+             || wrap_status == wrapper)
            res = LDPR_PREVAILING_DEF;
          else if (wrap_status == wrapped)
            res = LDPR_RESOLVED_IR;
@@ -1003,6 +1034,9 @@ set_tv_header (struct ld_plugin_tv *tv)
        case LDPT_REGISTER_CLAIM_FILE_HOOK:
          TVU(register_claim_file) = register_claim_file;
          break;
+       case LDPT_REGISTER_CLAIM_FILE_HOOK_V2:
+         TVU(register_claim_file_v2) = register_claim_file_v2;
+         break;
        case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
          TVU(register_all_symbols_read) = register_all_symbols_read;
          break;
@@ -1128,7 +1162,8 @@ plugin_load_plugins (void)
 
 /* Call 'claim file' hook for all plugins.  */
 static int
-plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
+plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed,
+                       bool known_used)
 {
   plugin_t *curplug = plugins_list;
   *claimed = false;
@@ -1139,7 +1174,10 @@ plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
          enum ld_plugin_status rv;
 
          called_plugin = curplug;
-         rv = (*curplug->claim_file_handler) (file, claimed);
+         if (curplug->claim_file_handler_v2)
+           rv = (*curplug->claim_file_handler_v2) (file, claimed, known_used);
+         else
+           rv = (*curplug->claim_file_handler) (file, claimed);
          called_plugin = NULL;
          if (rv != LDPS_OK)
            set_plugin_error (curplug->name);
@@ -1171,7 +1209,7 @@ plugin_cleanup (bfd *abfd ATTRIBUTE_UNUSED)
 }
 
 static bfd_cleanup
-plugin_object_p (bfd *ibfd)
+plugin_object_p (bfd *ibfd, bool known_used)
 {
   int claimed;
   plugin_input_file_t *input;
@@ -1211,6 +1249,7 @@ plugin_object_p (bfd *ibfd)
 
   file.handle = input;
   input->abfd = abfd;
+  input->ibfd = ibfd->my_archive != NULL ? ibfd : NULL;
   input->view_buffer.addr = NULL;
   input->view_buffer.filesize = 0;
   input->view_buffer.offset = 0;
@@ -1222,11 +1261,12 @@ plugin_object_p (bfd *ibfd)
 
   claimed = 0;
 
-  if (plugin_call_claim_file (&file, &claimed))
+  if (plugin_call_claim_file (&file, &claimed, known_used))
     einfo (_("%F%P: %s: plugin reported error claiming file\n"),
           plugin_error_plugin ());
 
-  if (input->fd != -1 && !bfd_plugin_target_p (ibfd->xvec))
+  if (input->fd != -1
+      && (!claimed || !bfd_plugin_target_p (ibfd->xvec)))
     {
       /* FIXME: fd belongs to us, not the plugin.  GCC plugin, which
         doesn't need fd after plugin_call_claim_file, doesn't use
@@ -1236,8 +1276,7 @@ plugin_object_p (bfd *ibfd)
         release_input_file after it is done, uses BFD plugin target
         vector.  This scheme doesn't work when a plugin needs fd and
         doesn't use BFD plugin target vector neither.  */
-      close (input->fd);
-      input->fd = -1;
+      release_plugin_file_descriptor (input);
     }
 
   if (claimed)
@@ -1277,7 +1316,7 @@ void
 plugin_maybe_claim (lang_input_statement_type *entry)
 {
   ASSERT (entry->header.type == lang_input_statement_enum);
-  if (plugin_object_p (entry->the_bfd))
+  if (plugin_object_p (entry->the_bfd, true))
     {
       bfd *abfd = entry->the_bfd->plugin_dummy_bfd;
 
@@ -1328,14 +1367,17 @@ plugin_call_cleanup (void)
     {
       if (curplug->cleanup_handler && !curplug->cleanup_done)
        {
-         enum ld_plugin_status rv;
-         curplug->cleanup_done = true;
-         called_plugin = curplug;
-         rv = (*curplug->cleanup_handler) ();
-         called_plugin = NULL;
-         if (rv != LDPS_OK)
-           info_msg (_("%P: %s: error in plugin cleanup: %d (ignored)\n"),
-                     curplug->name, rv);
+         if (!config.plugin_save_temps)
+           {
+             enum ld_plugin_status rv;
+             curplug->cleanup_done = true;
+             called_plugin = curplug;
+             rv = (*curplug->cleanup_handler) ();
+             called_plugin = NULL;
+             if (rv != LDPS_OK)
+               info_msg (_("%P: %s: error in plugin cleanup: %d (ignored)\n"),
+                         curplug->name, rv);
+           }
          dlclose (curplug->dlhandle);
        }
       curplug = curplug->next;