bfd_cleanup for object_p
[deliverable/binutils-gdb.git] / bfd / plugin.c
index d9416771545cd3f03f13a7b395495a895685705a..a0f172d363793753601db6afa892c97f79da0aab 100644 (file)
@@ -126,7 +126,6 @@ message (int level ATTRIBUTE_UNUSED,
 struct plugin_list_entry
 {
   /* These must be initialized for each IR object with LTO wrapper.  */
-  void *handle;
   ld_plugin_claim_file_handler claim_file;
   ld_plugin_all_symbols_read_handler all_symbols_read;
   ld_plugin_all_symbols_read_handler cleanup_handler;
@@ -148,6 +147,17 @@ struct plugin_list_entry
   bfd_boolean initialized;
 };
 
+static const char *plugin_program_name;
+static int need_lto_wrapper_p;
+
+void
+bfd_plugin_set_program_name (const char *program_name,
+                            int need_lto_wrapper)
+{
+  plugin_program_name = program_name;
+  need_lto_wrapper_p = need_lto_wrapper;
+}
+
 /* Use GCC LTO wrapper to covert LTO IR object to the real object.  */
 
 static bfd_boolean
@@ -166,6 +176,9 @@ get_lto_wrapper (struct plugin_list_entry *plugin)
   char dir_seperator = '\0';
   char *resolution_file;
 
+  if (!need_lto_wrapper_p)
+    return FALSE;
+
   if (plugin->initialized)
     {
       if (plugin->lto_wrapper)
@@ -490,14 +503,6 @@ add_symbols (void * handle,
   return LDPS_OK;
 }
 
-static const char *plugin_program_name;
-
-void
-bfd_plugin_set_program_name (const char *program_name)
-{
-  plugin_program_name = program_name;
-}
-
 int
 bfd_plugin_open_input (bfd *ibfd, struct ld_plugin_input_file *file)
 {
@@ -592,27 +597,25 @@ try_claim (bfd *abfd)
 }
 
 static int
-try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
+try_load_plugin (const char *pname,
+                struct plugin_list_entry *plugin_list_iter,
+                bfd *abfd, bfd_boolean build_list_p)
 {
-  void *plugin_handle = NULL;
+  void *plugin_handle;
   struct ld_plugin_tv tv[12];
   int i;
   ld_plugin_onload onload;
   enum ld_plugin_status status;
-  struct plugin_list_entry *plugin_list_iter;
-
-  *has_plugin_p = 0;
+  int result = 0;
 
   /* NB: Each object is independent.  Reuse the previous plugin from
      the last run will lead to wrong result.  */
   if (current_plugin)
-    {
-      if (current_plugin->handle)
-       dlclose (current_plugin->handle);
-      memset (current_plugin, 0,
-             offsetof (struct plugin_list_entry, next));
-      current_plugin = NULL;
-    }
+    memset (current_plugin, 0,
+           offsetof (struct plugin_list_entry, next));
+
+  if (plugin_list_iter)
+    pname = plugin_list_iter->plugin_name;
 
   plugin_handle = dlopen (pname, RTLD_NOW);
   if (!plugin_handle)
@@ -621,23 +624,17 @@ try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
       return 0;
     }
 
-  for (plugin_list_iter = plugin_list;
-       plugin_list_iter;
-       plugin_list_iter = plugin_list_iter->next)
-    if (strcmp (plugin_list_iter->plugin_name, pname) == 0)
-      break;
-
   if (plugin_list_iter == NULL)
     {
       size_t length_plugin_name = strlen (pname) + 1;
       char *plugin_name = bfd_malloc (length_plugin_name);
       if (plugin_name == NULL)
-       return 0;
+       goto short_circuit;
       plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter);
       if (plugin_list_iter == NULL)
        {
          free (plugin_name);
-         return 0;
+         goto short_circuit;
        }
       /* Make a copy of PNAME since PNAME from load_plugin () will be
         freed.  */
@@ -648,11 +645,13 @@ try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
       plugin_list = plugin_list_iter;
     }
 
-  plugin_list_iter->handle = plugin_handle;
+  current_plugin = plugin_list_iter;
+  if (build_list_p)
+    goto short_circuit;
 
   onload = dlsym (plugin_handle, "onload");
   if (!onload)
-    return 0;
+    goto short_circuit;
 
   i = 0;
   tv[i].tv_tag = LDPT_MESSAGE;
@@ -705,37 +704,36 @@ try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
   tv[i].tv_tag = LDPT_NULL;
   tv[i].tv_u.tv_val = 0;
 
-  current_plugin = plugin_list_iter;
-
   /* LTO plugin will call handler hooks to set up plugin handlers.  */
   status = (*onload)(tv);
 
   if (status != LDPS_OK)
-    return 0;
+    goto short_circuit;
 
   if (current_plugin->lto_wrapper
       && setup_lto_wrapper_env (current_plugin))
-    return 0;
-
-  *has_plugin_p = 1;
+    goto short_circuit;
 
   abfd->plugin_format = bfd_plugin_no;
 
   if (!current_plugin->claim_file)
-    return 0;
+    goto short_circuit;
 
   if (!try_claim (abfd))
-    return 0;
+    goto short_circuit;
 
   abfd->plugin_format = bfd_plugin_yes;
-  return 1;
+  result = 1;
+
+ short_circuit:
+  dlclose (plugin_handle);
+  return result;
 }
 
 /* There may be plugin libraries in lib/bfd-plugins.  */
+static int has_plugin_list = -1;
 
-static int has_plugin = -1;
-
-static const bfd_target *(*ld_plugin_object_p) (bfd *);
+static bfd_cleanup (*ld_plugin_object_p) (bfd *);
 
 static const char *plugin_name;
 
@@ -743,7 +741,6 @@ void
 bfd_plugin_set_plugin (const char *p)
 {
   plugin_name = p;
-  has_plugin = p != NULL;
 }
 
 /* Return TRUE if a plugin library is used.  */
@@ -751,7 +748,7 @@ bfd_plugin_set_plugin (const char *p)
 bfd_boolean
 bfd_plugin_specified_p (void)
 {
-  return has_plugin > 0;
+  return plugin_list != NULL;
 }
 
 /* Return TRUE if ABFD can be claimed by linker LTO plugin.  */
@@ -777,13 +774,13 @@ bfd_plugin_target_p (const bfd_target *target)
 /* Register OBJECT_P to be used by bfd_plugin_object_p.  */
 
 void
-register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *))
+register_ld_plugin_object_p (bfd_cleanup (*object_p) (bfd *))
 {
   ld_plugin_object_p = object_p;
 }
 
-static int
-load_plugin (bfd *abfd)
+static void
+build_plugin_list (bfd *abfd)
 {
   /* The intent was to search ${libdir}/bfd-plugins for plugins, but
      unfortunately the original implementation wasn't precisely that
@@ -792,17 +789,10 @@ load_plugin (bfd *abfd)
   static const char *path[]
     = { LIBDIR "/bfd-plugins", BINDIR "/../lib/bfd-plugins" };
   struct stat last_st;
-  int found = 0;
   unsigned int i;
 
-  if (!has_plugin)
-    return found;
-
-  if (plugin_name)
-    return try_load_plugin (plugin_name, abfd, &has_plugin);
-
-  if (plugin_program_name == NULL)
-    return found;
+  if (has_plugin_list >= 0)
+    return;
 
   /* Try not to search the same dir twice, by looking at st_dev and
      st_ino for the dir.  If we are on a file system that always sets
@@ -837,30 +827,42 @@ load_plugin (bfd *abfd)
 
                  full_name = concat (plugin_dir, "/", ent->d_name, NULL);
                  if (stat (full_name, &st) == 0 && S_ISREG (st.st_mode))
-                   {
-                     int valid_plugin;
-
-                     found = try_load_plugin (full_name, abfd, &valid_plugin);
-                     if (has_plugin <= 0)
-                       has_plugin = valid_plugin;
-                   }
+                   try_load_plugin (full_name, NULL, abfd, TRUE);
                  free (full_name);
-                 if (found)
-                   break;
                }
              closedir (d);
            }
          free (plugin_dir);
        }
-      if (found)
-       break;
     }
 
-  return found;
+  has_plugin_list = plugin_list != NULL;
+}
+
+static int
+load_plugin (bfd *abfd)
+{
+  struct plugin_list_entry *plugin_list_iter;
+
+  if (plugin_name)
+    return try_load_plugin (plugin_name, plugin_list, abfd, FALSE);
+
+  if (plugin_program_name == NULL)
+    return 0;
+
+  build_plugin_list (abfd);
+
+  for (plugin_list_iter = plugin_list;
+       plugin_list_iter;
+       plugin_list_iter = plugin_list_iter->next)
+    if (try_load_plugin (NULL, plugin_list_iter, abfd, FALSE))
+      return 1;
+
+  return 0;
 }
 
 
-static const bfd_target *
+static bfd_cleanup
 bfd_plugin_object_p (bfd *abfd)
 {
   if (ld_plugin_object_p)
@@ -869,7 +871,7 @@ bfd_plugin_object_p (bfd *abfd)
   if (abfd->plugin_format == bfd_plugin_unknown && !load_plugin (abfd))
     return NULL;
 
-  return abfd->plugin_format == bfd_plugin_yes ? abfd->xvec : NULL;
+  return abfd->plugin_format == bfd_plugin_yes ? _bfd_no_cleanup : NULL;
 }
 
 /* Copy any private info we understand from the input bfd
This page took 0.030309 seconds and 4 git commands to generate.