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;
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
char dir_seperator = '\0';
char *resolution_file;
+ if (!need_lto_wrapper_p)
+ return FALSE;
+
if (plugin->initialized)
{
if (plugin->lto_wrapper)
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)
{
struct ld_plugin_input_file file;
file.handle = abfd;
- if (!bfd_plugin_open_input (abfd, &file))
- return 0;
- if (current_plugin->claim_file)
+ if (bfd_plugin_open_input (abfd, &file)
+ && current_plugin->claim_file)
{
current_plugin->claim_file (&file, &claimed);
if (claimed)
}
}
- if (current_plugin->lto_wrapper)
- {
- /* Clean up for LTO wrapper. */
- unlink (current_plugin->resolution_file);
- free (current_plugin->resolution_option);
- }
+ close (file.fd);
}
- close (file.fd);
+
+ if (current_plugin->lto_wrapper)
+ {
+ /* Clean up for LTO wrapper. NB: Resolution file and option
+ have been created regardless if an IR object is claimed or
+ not. */
+ unlink (current_plugin->resolution_file);
+ free (current_plugin->resolution_option);
+ }
+
return claimed;
}
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;
+ int result = 0;
- *has_plugin_p = 0;
+ /* NB: Each object is independent. Reuse the previous plugin from
+ the last run will lead to wrong result. */
+ if (current_plugin)
+ memset (current_plugin, 0,
+ offsetof (struct plugin_list_entry, next));
- /* NB: Each object is inddependent. Reuse the previous plugin from
- the last LTO wrapper run will lead to wrong LTO data. */
- if (current_plugin
- && current_plugin->handle
- && current_plugin->lto_wrapper
- && strcmp (current_plugin->plugin_name, pname) == 0)
- {
- dlclose (current_plugin->handle);
- 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)
return 0;
}
- for (plugin_list_iter = plugin_list;
- plugin_list_iter;
- plugin_list_iter = plugin_list_iter->next)
+ if (plugin_list_iter == NULL)
{
- if (plugin_handle == plugin_list_iter->handle)
+ size_t length_plugin_name = strlen (pname) + 1;
+ char *plugin_name = bfd_malloc (length_plugin_name);
+ if (plugin_name == NULL)
+ goto short_circuit;
+ plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter);
+ if (plugin_list_iter == NULL)
{
- dlclose (plugin_handle);
- if (!plugin_list_iter->claim_file)
- return 0;
-
- register_claim_file (plugin_list_iter->claim_file);
- current_plugin = plugin_list_iter;
- goto have_claim_file;
+ free (plugin_name);
+ goto short_circuit;
}
- else if (plugin_list_iter->lto_wrapper
- && strcmp (plugin_list_iter->plugin_name, pname) == 0)
- goto have_lto_wrapper;
+ /* Make a copy of PNAME since PNAME from load_plugin () will be
+ freed. */
+ memcpy (plugin_name, pname, length_plugin_name);
+ memset (plugin_list_iter, 0, sizeof (*plugin_list_iter));
+ plugin_list_iter->plugin_name = plugin_name;
+ plugin_list_iter->next = plugin_list;
+ plugin_list = plugin_list_iter;
}
- plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter);
- if (plugin_list_iter == NULL)
- return 0;
- memset (plugin_list_iter, 0, sizeof (*plugin_list_iter));
- plugin_list_iter->plugin_name = pname;
- plugin_list_iter->next = plugin_list;
- plugin_list = plugin_list_iter;
-
-have_lto_wrapper:
- 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;
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;
-
-have_claim_file:
- *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;
bfd_plugin_set_plugin (const char *p)
{
plugin_name = p;
- has_plugin = p != NULL;
}
/* Return TRUE if a plugin library is used. */
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. */
/* 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
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
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)
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