plugin: Search bfd-plugins directories only once

try_load_plugin is updated to take either plugin name or plugin entry.
load_plugin is updated to search bfd-plugins directories first to build
a list of plugins and call try_load_plugin with each plugin on the list.
When --plugin is used, the plugin list only has one entry.

	* plugin.c (try_load_plugin): Make plugin_list_iter an argument
	and use it if it isn't NULL.  Remove has_plugin_p argument.  Add
	a build_list_p argument.  Don't search plugin_list.  Short circuit
	when building the plugin list.
	(has_plugin): Renamed to has_plugin_list.
	(bfd_plugin_set_plugin): Don't set has_plugin.
	(bfd_plugin_specified_p): Check plugin_list instead.
	(build_plugin_list): New function.
	(load_plugin): Call build_plugin_list and use plugin_list.
This commit is contained in:
H.J. Lu
2020-02-13 03:17:51 -08:00
parent f98a845896
commit 99845b3b77
2 changed files with 50 additions and 39 deletions

View File

@ -1,3 +1,15 @@
2020-02-13 H.J. Lu <hongjiu.lu@intel.com>
* plugin.c (try_load_plugin): Make plugin_list_iter an argument
and use it if it isn't NULL. Remove has_plugin_p argument. Add
a build_list_p argument. Don't search plugin_list. Short circuit
when building the plugin list.
(has_plugin): Renamed to has_plugin_list.
(bfd_plugin_set_plugin): Don't set has_plugin.
(bfd_plugin_specified_p): Check plugin_list instead.
(build_plugin_list): New function.
(load_plugin): Call build_plugin_list and use plugin_list.
2020-02-11 H.J. Lu <hongjiu.lu@intel.com> 2020-02-11 H.J. Lu <hongjiu.lu@intel.com>
PR binutils/25355 PR binutils/25355

View File

@ -592,16 +592,15 @@ try_claim (bfd *abfd)
} }
static int 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 = NULL;
struct ld_plugin_tv tv[12]; struct ld_plugin_tv tv[12];
int i; int i;
ld_plugin_onload onload; ld_plugin_onload onload;
enum ld_plugin_status status; enum ld_plugin_status status;
struct plugin_list_entry *plugin_list_iter;
*has_plugin_p = 0;
/* NB: Each object is independent. Reuse the previous plugin from /* NB: Each object is independent. Reuse the previous plugin from
the last run will lead to wrong result. */ the last run will lead to wrong result. */
@ -614,6 +613,9 @@ try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
current_plugin = NULL; current_plugin = NULL;
} }
if (plugin_list_iter)
pname = plugin_list_iter->plugin_name;
plugin_handle = dlopen (pname, RTLD_NOW); plugin_handle = dlopen (pname, RTLD_NOW);
if (!plugin_handle) if (!plugin_handle)
{ {
@ -621,12 +623,6 @@ try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
return 0; 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) if (plugin_list_iter == NULL)
{ {
size_t length_plugin_name = strlen (pname) + 1; size_t length_plugin_name = strlen (pname) + 1;
@ -649,6 +645,8 @@ try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
} }
plugin_list_iter->handle = plugin_handle; plugin_list_iter->handle = plugin_handle;
if (build_list_p)
return 0;
onload = dlsym (plugin_handle, "onload"); onload = dlsym (plugin_handle, "onload");
if (!onload) if (!onload)
@ -717,8 +715,6 @@ try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
&& setup_lto_wrapper_env (current_plugin)) && setup_lto_wrapper_env (current_plugin))
return 0; return 0;
*has_plugin_p = 1;
abfd->plugin_format = bfd_plugin_no; abfd->plugin_format = bfd_plugin_no;
if (!current_plugin->claim_file) if (!current_plugin->claim_file)
@ -732,8 +728,7 @@ try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
} }
/* There may be plugin libraries in lib/bfd-plugins. */ /* 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 const bfd_target *(*ld_plugin_object_p) (bfd *);
@ -743,7 +738,6 @@ void
bfd_plugin_set_plugin (const char *p) bfd_plugin_set_plugin (const char *p)
{ {
plugin_name = p; plugin_name = p;
has_plugin = p != NULL;
} }
/* Return TRUE if a plugin library is used. */ /* Return TRUE if a plugin library is used. */
@ -751,7 +745,7 @@ bfd_plugin_set_plugin (const char *p)
bfd_boolean bfd_boolean
bfd_plugin_specified_p (void) bfd_plugin_specified_p (void)
{ {
return has_plugin > 0; return plugin_list != NULL;
} }
/* Return TRUE if ABFD can be claimed by linker LTO plugin. */ /* Return TRUE if ABFD can be claimed by linker LTO plugin. */
@ -782,8 +776,8 @@ register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *))
ld_plugin_object_p = object_p; ld_plugin_object_p = object_p;
} }
static int static void
load_plugin (bfd *abfd) build_plugin_list (bfd *abfd)
{ {
/* The intent was to search ${libdir}/bfd-plugins for plugins, but /* The intent was to search ${libdir}/bfd-plugins for plugins, but
unfortunately the original implementation wasn't precisely that unfortunately the original implementation wasn't precisely that
@ -792,17 +786,10 @@ load_plugin (bfd *abfd)
static const char *path[] static const char *path[]
= { LIBDIR "/bfd-plugins", BINDIR "/../lib/bfd-plugins" }; = { LIBDIR "/bfd-plugins", BINDIR "/../lib/bfd-plugins" };
struct stat last_st; struct stat last_st;
int found = 0;
unsigned int i; unsigned int i;
if (!has_plugin) if (has_plugin_list >= 0)
return found; return;
if (plugin_name)
return try_load_plugin (plugin_name, abfd, &has_plugin);
if (plugin_program_name == NULL)
return found;
/* Try not to search the same dir twice, by looking at st_dev and /* 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 st_ino for the dir. If we are on a file system that always sets
@ -837,26 +824,38 @@ load_plugin (bfd *abfd)
full_name = concat (plugin_dir, "/", ent->d_name, NULL); full_name = concat (plugin_dir, "/", ent->d_name, NULL);
if (stat (full_name, &st) == 0 && S_ISREG (st.st_mode)) if (stat (full_name, &st) == 0 && S_ISREG (st.st_mode))
{ try_load_plugin (full_name, NULL, abfd, TRUE);
int valid_plugin;
found = try_load_plugin (full_name, abfd, &valid_plugin);
if (has_plugin <= 0)
has_plugin = valid_plugin;
}
free (full_name); free (full_name);
if (found)
break;
} }
closedir (d); closedir (d);
} }
free (plugin_dir); 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;
} }