|
|
db51e6 |
diff -rup binutils.orig/bfd/Makefile.am binutils-2.30/bfd/Makefile.am
|
|
|
db51e6 |
--- binutils.orig/bfd/Makefile.am 2022-08-19 12:00:54.247630878 +0100
|
|
|
db51e6 |
+++ binutils-2.30/bfd/Makefile.am 2022-08-19 12:20:51.714655518 +0100
|
|
|
db51e6 |
@@ -52,7 +52,7 @@ ZLIBINC = @zlibinc@
|
|
|
db51e6 |
WARN_CFLAGS = @WARN_CFLAGS@
|
|
|
db51e6 |
NO_WERROR = @NO_WERROR@
|
|
|
db51e6 |
AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC)
|
|
|
db51e6 |
-AM_CPPFLAGS = -DBINDIR='"$(bindir)"'
|
|
|
db51e6 |
+AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DLIBDIR='"$(libdir)"'
|
|
|
db51e6 |
if PLUGINS
|
|
|
db51e6 |
bfdinclude_HEADERS += $(INCDIR)/plugin-api.h
|
|
|
db51e6 |
LIBDL = @lt_cv_dlopen_libs@
|
|
|
db51e6 |
diff -rup binutils.orig/bfd/Makefile.in binutils-2.30/bfd/Makefile.in
|
|
|
db51e6 |
--- binutils.orig/bfd/Makefile.in 2022-08-19 12:00:54.248630872 +0100
|
|
|
db51e6 |
+++ binutils-2.30/bfd/Makefile.in 2022-08-19 12:21:24.788462670 +0100
|
|
|
db51e6 |
@@ -390,7 +390,7 @@ libbfd_la_LDFLAGS = -Wl,-Bsymbolic-funct
|
|
|
db51e6 |
ZLIB = @zlibdir@ -lz
|
|
|
db51e6 |
ZLIBINC = @zlibinc@
|
|
|
db51e6 |
AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC)
|
|
|
db51e6 |
-AM_CPPFLAGS = -DBINDIR='"$(bindir)"'
|
|
|
db51e6 |
+AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DLIBDIR='"$(libdir)"'
|
|
|
db51e6 |
@PLUGINS_TRUE@LIBDL = @lt_cv_dlopen_libs@
|
|
|
db51e6 |
|
|
|
db51e6 |
# bfd.h goes here, for now
|
|
|
db51e6 |
diff -rup binutils.orig/bfd/plugin.c binutils-2.30/bfd/plugin.c
|
|
|
db51e6 |
--- binutils.orig/bfd/plugin.c 2022-08-19 12:00:54.248630872 +0100
|
|
|
db51e6 |
+++ binutils-2.30/bfd/plugin.c 2022-08-19 12:24:10.466496616 +0100
|
|
|
db51e6 |
@@ -348,16 +348,44 @@ try_claim (bfd *abfd)
|
|
|
db51e6 |
return claimed;
|
|
|
db51e6 |
}
|
|
|
db51e6 |
|
|
|
db51e6 |
+struct plugin_list_entry
|
|
|
db51e6 |
+{
|
|
|
db51e6 |
+ /* These must be initialized for each IR object with LTO wrapper. */
|
|
|
db51e6 |
+ ld_plugin_claim_file_handler claim_file;
|
|
|
db51e6 |
+ ld_plugin_all_symbols_read_handler all_symbols_read;
|
|
|
db51e6 |
+ ld_plugin_all_symbols_read_handler cleanup_handler;
|
|
|
db51e6 |
+ bfd_boolean has_symbol_type;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+ struct plugin_list_entry *next;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+ /* These can be reused for all IR objects. */
|
|
|
db51e6 |
+ const char *plugin_name;
|
|
|
db51e6 |
+};
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+static struct plugin_list_entry *plugin_list = NULL;
|
|
|
db51e6 |
+static struct plugin_list_entry *current_plugin = NULL;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
static int
|
|
|
db51e6 |
-try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p, bfd_boolean build_list_p)
|
|
|
db51e6 |
+try_load_plugin (const char *pname,
|
|
|
db51e6 |
+ struct plugin_list_entry *plugin_list_iter,
|
|
|
db51e6 |
+ bfd *abfd,
|
|
|
db51e6 |
+ bfd_boolean build_list_p)
|
|
|
db51e6 |
{
|
|
|
db51e6 |
void *plugin_handle;
|
|
|
db51e6 |
struct ld_plugin_tv tv[4];
|
|
|
db51e6 |
int i;
|
|
|
db51e6 |
ld_plugin_onload onload;
|
|
|
db51e6 |
enum ld_plugin_status status;
|
|
|
db51e6 |
+ int result = 0;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+ /* NB: Each object is independent. Reuse the previous plugin from
|
|
|
db51e6 |
+ the last run will lead to wrong result. */
|
|
|
db51e6 |
+ if (current_plugin)
|
|
|
db51e6 |
+ memset (current_plugin, 0,
|
|
|
db51e6 |
+ offsetof (struct plugin_list_entry, next));
|
|
|
db51e6 |
|
|
|
db51e6 |
- *has_plugin_p = 0;
|
|
|
db51e6 |
+ if (plugin_list_iter)
|
|
|
db51e6 |
+ pname = plugin_list_iter->plugin_name;
|
|
|
db51e6 |
|
|
|
db51e6 |
plugin_handle = dlopen (pname, RTLD_NOW);
|
|
|
db51e6 |
if (!plugin_handle)
|
|
|
db51e6 |
@@ -366,13 +394,40 @@ try_load_plugin (const char *pname, bfd
|
|
|
db51e6 |
we do not bother the user with the details of any
|
|
|
db51e6 |
plugins that cannot be loaded. */
|
|
|
db51e6 |
if (! build_list_p)
|
|
|
db51e6 |
- _bfd_error_handler ("%s\n", dlerror ());
|
|
|
db51e6 |
+ _bfd_error_handler ("Failed to load plugin '%s', reason: %s\n",
|
|
|
db51e6 |
+ pname, dlerror ());
|
|
|
db51e6 |
return 0;
|
|
|
db51e6 |
}
|
|
|
db51e6 |
|
|
|
db51e6 |
+ if (plugin_list_iter == NULL)
|
|
|
db51e6 |
+ {
|
|
|
db51e6 |
+ size_t length_plugin_name = strlen (pname) + 1;
|
|
|
db51e6 |
+ char *plugin_name = bfd_malloc (length_plugin_name);
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+ if (plugin_name == NULL)
|
|
|
db51e6 |
+ goto short_circuit;
|
|
|
db51e6 |
+ plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter);
|
|
|
db51e6 |
+ if (plugin_list_iter == NULL)
|
|
|
db51e6 |
+ {
|
|
|
db51e6 |
+ free (plugin_name);
|
|
|
db51e6 |
+ goto short_circuit;
|
|
|
db51e6 |
+ }
|
|
|
db51e6 |
+ /* Make a copy of PNAME since PNAME from load_plugin () will be
|
|
|
db51e6 |
+ freed. */
|
|
|
db51e6 |
+ memcpy (plugin_name, pname, length_plugin_name);
|
|
|
db51e6 |
+ memset (plugin_list_iter, 0, sizeof (*plugin_list_iter));
|
|
|
db51e6 |
+ plugin_list_iter->plugin_name = plugin_name;
|
|
|
db51e6 |
+ plugin_list_iter->next = plugin_list;
|
|
|
db51e6 |
+ plugin_list = plugin_list_iter;
|
|
|
db51e6 |
+ }
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+ current_plugin = plugin_list_iter;
|
|
|
db51e6 |
+ if (build_list_p)
|
|
|
db51e6 |
+ goto short_circuit;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
onload = dlsym (plugin_handle, "onload");
|
|
|
db51e6 |
if (!onload)
|
|
|
db51e6 |
- goto err;
|
|
|
db51e6 |
+ goto short_circuit;
|
|
|
db51e6 |
|
|
|
db51e6 |
i = 0;
|
|
|
db51e6 |
tv[i].tv_tag = LDPT_MESSAGE;
|
|
|
db51e6 |
@@ -393,34 +448,26 @@ try_load_plugin (const char *pname, bfd
|
|
|
db51e6 |
status = (*onload)(tv);
|
|
|
db51e6 |
|
|
|
db51e6 |
if (status != LDPS_OK)
|
|
|
db51e6 |
- goto err;
|
|
|
db51e6 |
-
|
|
|
db51e6 |
- *has_plugin_p = 1;
|
|
|
db51e6 |
+ goto short_circuit;
|
|
|
db51e6 |
|
|
|
db51e6 |
abfd->plugin_format = bfd_plugin_no;
|
|
|
db51e6 |
|
|
|
db51e6 |
- if (!claim_file)
|
|
|
db51e6 |
- goto err;
|
|
|
db51e6 |
+ if (!current_plugin->claim_file)
|
|
|
db51e6 |
+ goto short_circuit;
|
|
|
db51e6 |
|
|
|
db51e6 |
if (!try_claim (abfd))
|
|
|
db51e6 |
- goto err;
|
|
|
db51e6 |
+ goto short_circuit;
|
|
|
db51e6 |
|
|
|
db51e6 |
abfd->plugin_format = bfd_plugin_yes;
|
|
|
db51e6 |
+ result = 1;
|
|
|
db51e6 |
|
|
|
db51e6 |
- /* There is a potential resource leak here, but it is not important. */
|
|
|
db51e6 |
- /* coverity[leaked_storage: FALSE] */
|
|
|
db51e6 |
- return 1;
|
|
|
db51e6 |
-
|
|
|
db51e6 |
- err:
|
|
|
db51e6 |
- /* There is a potential resource leak here, but it is not important. */
|
|
|
db51e6 |
- /* coverity[leaked_storage: FALSE] */
|
|
|
db51e6 |
- return 0;
|
|
|
db51e6 |
+ short_circuit:
|
|
|
db51e6 |
+ dlclose (plugin_handle);
|
|
|
db51e6 |
+ return result;
|
|
|
db51e6 |
}
|
|
|
db51e6 |
|
|
|
db51e6 |
/* There may be plugin libraries in lib/bfd-plugins. */
|
|
|
db51e6 |
|
|
|
db51e6 |
-static int has_plugin = -1;
|
|
|
db51e6 |
-
|
|
|
db51e6 |
static const bfd_target *(*ld_plugin_object_p) (bfd *);
|
|
|
db51e6 |
|
|
|
db51e6 |
static const char *plugin_name;
|
|
|
db51e6 |
@@ -429,7 +476,6 @@ void
|
|
|
db51e6 |
bfd_plugin_set_plugin (const char *p)
|
|
|
db51e6 |
{
|
|
|
db51e6 |
plugin_name = p;
|
|
|
db51e6 |
- has_plugin = p != NULL;
|
|
|
db51e6 |
}
|
|
|
db51e6 |
|
|
|
db51e6 |
/* Return TRUE if a plugin library is used. */
|
|
|
db51e6 |
@@ -437,7 +483,7 @@ bfd_plugin_set_plugin (const char *p)
|
|
|
db51e6 |
bfd_boolean
|
|
|
db51e6 |
bfd_plugin_specified_p (void)
|
|
|
db51e6 |
{
|
|
|
db51e6 |
- return has_plugin > 0;
|
|
|
db51e6 |
+ return plugin_list != NULL;
|
|
|
db51e6 |
}
|
|
|
db51e6 |
|
|
|
db51e6 |
/* Return TRUE if ABFD can be claimed by linker LTO plugin. */
|
|
|
db51e6 |
@@ -468,60 +514,92 @@ register_ld_plugin_object_p (const bfd_t
|
|
|
db51e6 |
ld_plugin_object_p = object_p;
|
|
|
db51e6 |
}
|
|
|
db51e6 |
|
|
|
db51e6 |
+/* There may be plugin libraries in lib/bfd-plugins. */
|
|
|
db51e6 |
+static int has_plugin_list = -1;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+static void
|
|
|
db51e6 |
+build_plugin_list (bfd *abfd)
|
|
|
db51e6 |
+{
|
|
|
db51e6 |
+ /* The intent was to search ${libdir}/bfd-plugins for plugins, but
|
|
|
db51e6 |
+ unfortunately the original implementation wasn't precisely that
|
|
|
db51e6 |
+ when configuring binutils using --libdir. Search in the proper
|
|
|
db51e6 |
+ path first, then the old one for backwards compatibility. */
|
|
|
db51e6 |
+ static const char *path[]
|
|
|
db51e6 |
+ = { LIBDIR "/bfd-plugins",
|
|
|
db51e6 |
+ BINDIR "/../lib/bfd-plugins" };
|
|
|
db51e6 |
+ struct stat last_st;
|
|
|
db51e6 |
+ unsigned int i;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+ if (has_plugin_list >= 0)
|
|
|
db51e6 |
+ return;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+ /* Try not to search the same dir twice, by looking at st_dev and
|
|
|
db51e6 |
+ st_ino for the dir. If we are on a file system that always sets
|
|
|
db51e6 |
+ st_ino to zero or the actual st_ino is zero we might waste some
|
|
|
db51e6 |
+ time, but that doesn't matter too much. */
|
|
|
db51e6 |
+ last_st.st_dev = 0;
|
|
|
db51e6 |
+ last_st.st_ino = 0;
|
|
|
db51e6 |
+ for (i = 0; i < sizeof (path) / sizeof (path[0]); i++)
|
|
|
db51e6 |
+ {
|
|
|
db51e6 |
+ char *plugin_dir = make_relative_prefix (plugin_program_name,
|
|
|
db51e6 |
+ BINDIR,
|
|
|
db51e6 |
+ path[i]);
|
|
|
db51e6 |
+ if (plugin_dir)
|
|
|
db51e6 |
+ {
|
|
|
db51e6 |
+ struct stat st;
|
|
|
db51e6 |
+ DIR *d;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+ if (stat (plugin_dir, &st) == 0
|
|
|
db51e6 |
+ && S_ISDIR (st.st_mode)
|
|
|
db51e6 |
+ && !(last_st.st_dev == st.st_dev
|
|
|
db51e6 |
+ && last_st.st_ino == st.st_ino
|
|
|
db51e6 |
+ && st.st_ino != 0)
|
|
|
db51e6 |
+ && (d = opendir (plugin_dir)) != NULL)
|
|
|
db51e6 |
+ {
|
|
|
db51e6 |
+ struct dirent *ent;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+ last_st.st_dev = st.st_dev;
|
|
|
db51e6 |
+ last_st.st_ino = st.st_ino;
|
|
|
db51e6 |
+ while ((ent = readdir (d)) != NULL)
|
|
|
db51e6 |
+ {
|
|
|
db51e6 |
+ char *full_name;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+ full_name = concat (plugin_dir, "/", ent->d_name, NULL);
|
|
|
db51e6 |
+ if (stat (full_name, &st) == 0 && S_ISREG (st.st_mode))
|
|
|
db51e6 |
+ (void) try_load_plugin (full_name, NULL, abfd, TRUE);
|
|
|
db51e6 |
+ free (full_name);
|
|
|
db51e6 |
+ }
|
|
|
db51e6 |
+ closedir (d);
|
|
|
db51e6 |
+ }
|
|
|
db51e6 |
+ free (plugin_dir);
|
|
|
db51e6 |
+ }
|
|
|
db51e6 |
+ }
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+ has_plugin_list = plugin_list != NULL;
|
|
|
db51e6 |
+}
|
|
|
db51e6 |
+
|
|
|
db51e6 |
static int
|
|
|
db51e6 |
load_plugin (bfd *abfd)
|
|
|
db51e6 |
{
|
|
|
db51e6 |
- char *plugin_dir;
|
|
|
db51e6 |
- char *p;
|
|
|
db51e6 |
- DIR *d;
|
|
|
db51e6 |
- struct dirent *ent;
|
|
|
db51e6 |
- int found = 0;
|
|
|
db51e6 |
+ struct plugin_list_entry *plugin_list_iter;
|
|
|
db51e6 |
|
|
|
db51e6 |
- if (!has_plugin)
|
|
|
db51e6 |
- return found;
|
|
|
db51e6 |
-
|
|
|
db51e6 |
- if (plugin_name)
|
|
|
db51e6 |
- return try_load_plugin (plugin_name, abfd, &has_plugin, FALSE);
|
|
|
db51e6 |
+ if (plugin_name != NULL)
|
|
|
db51e6 |
+ return try_load_plugin (plugin_name, plugin_list, abfd, FALSE);
|
|
|
db51e6 |
|
|
|
db51e6 |
if (plugin_program_name == NULL)
|
|
|
db51e6 |
- return found;
|
|
|
db51e6 |
-
|
|
|
db51e6 |
- plugin_dir = concat (BINDIR, "/../lib/bfd-plugins", NULL);
|
|
|
db51e6 |
- p = make_relative_prefix (plugin_program_name,
|
|
|
db51e6 |
- BINDIR,
|
|
|
db51e6 |
- plugin_dir);
|
|
|
db51e6 |
- free (plugin_dir);
|
|
|
db51e6 |
- plugin_dir = NULL;
|
|
|
db51e6 |
-
|
|
|
db51e6 |
- d = opendir (p);
|
|
|
db51e6 |
- if (!d)
|
|
|
db51e6 |
- goto out;
|
|
|
db51e6 |
+ return 0;
|
|
|
db51e6 |
|
|
|
db51e6 |
- while ((ent = readdir (d)))
|
|
|
db51e6 |
- {
|
|
|
db51e6 |
- char *full_name;
|
|
|
db51e6 |
- struct stat s;
|
|
|
db51e6 |
- int valid_plugin;
|
|
|
db51e6 |
-
|
|
|
db51e6 |
- full_name = concat (p, "/", ent->d_name, NULL);
|
|
|
db51e6 |
- if (stat(full_name, &s) == 0 && S_ISREG (s.st_mode))
|
|
|
db51e6 |
- found = try_load_plugin (full_name, abfd, &valid_plugin, TRUE);
|
|
|
db51e6 |
- if (has_plugin <= 0)
|
|
|
db51e6 |
- has_plugin = valid_plugin;
|
|
|
db51e6 |
- free (full_name);
|
|
|
db51e6 |
- if (found)
|
|
|
db51e6 |
- break;
|
|
|
db51e6 |
- }
|
|
|
db51e6 |
+ build_plugin_list (abfd);
|
|
|
db51e6 |
|
|
|
db51e6 |
- out:
|
|
|
db51e6 |
- free (p);
|
|
|
db51e6 |
- if (d)
|
|
|
db51e6 |
- closedir (d);
|
|
|
db51e6 |
+ for (plugin_list_iter = plugin_list;
|
|
|
db51e6 |
+ plugin_list_iter;
|
|
|
db51e6 |
+ plugin_list_iter = plugin_list_iter->next)
|
|
|
db51e6 |
+ if (try_load_plugin (NULL, plugin_list_iter, abfd, FALSE))
|
|
|
db51e6 |
+ return 1;
|
|
|
db51e6 |
|
|
|
db51e6 |
- return found;
|
|
|
db51e6 |
+ return 0;
|
|
|
db51e6 |
}
|
|
|
db51e6 |
|
|
|
db51e6 |
-
|
|
|
db51e6 |
static const bfd_target *
|
|
|
db51e6 |
bfd_plugin_object_p (bfd *abfd)
|
|
|
db51e6 |
{
|
|
|
db51e6 |
--- binutils.orig/bfd/plugin.c 2022-08-19 13:54:29.289173969 +0100
|
|
|
db51e6 |
+++ binutils-2.30/bfd/plugin.c 2022-08-19 14:13:24.077310901 +0100
|
|
|
db51e6 |
@@ -122,13 +122,29 @@ message (int level ATTRIBUTE_UNUSED,
|
|
|
db51e6 |
return LDPS_OK;
|
|
|
db51e6 |
}
|
|
|
db51e6 |
|
|
|
db51e6 |
+struct plugin_list_entry
|
|
|
db51e6 |
+{
|
|
|
db51e6 |
+ /* These must be initialized for each IR object with LTO wrapper. */
|
|
|
db51e6 |
+ ld_plugin_claim_file_handler claim_file;
|
|
|
db51e6 |
+ ld_plugin_all_symbols_read_handler all_symbols_read;
|
|
|
db51e6 |
+ ld_plugin_all_symbols_read_handler cleanup_handler;
|
|
|
db51e6 |
+ bfd_boolean has_symbol_type;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+ struct plugin_list_entry *next;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+ /* These can be reused for all IR objects. */
|
|
|
db51e6 |
+ const char *plugin_name;
|
|
|
db51e6 |
+};
|
|
|
db51e6 |
+
|
|
|
db51e6 |
+static struct plugin_list_entry *plugin_list = NULL;
|
|
|
db51e6 |
+static struct plugin_list_entry *current_plugin = NULL;
|
|
|
db51e6 |
+
|
|
|
db51e6 |
/* Register a claim-file handler. */
|
|
|
db51e6 |
-static ld_plugin_claim_file_handler claim_file;
|
|
|
db51e6 |
|
|
|
db51e6 |
static enum ld_plugin_status
|
|
|
db51e6 |
register_claim_file (ld_plugin_claim_file_handler handler)
|
|
|
db51e6 |
{
|
|
|
db51e6 |
- claim_file = handler;
|
|
|
db51e6 |
+ current_plugin->claim_file = handler;
|
|
|
db51e6 |
return LDPS_OK;
|
|
|
db51e6 |
}
|
|
|
db51e6 |
|
|
|
db51e6 |
@@ -339,32 +355,17 @@ try_claim (bfd *abfd)
|
|
|
db51e6 |
int claimed = 0;
|
|
|
db51e6 |
struct ld_plugin_input_file file;
|
|
|
db51e6 |
|
|
|
db51e6 |
+ if (current_plugin->claim_file == NULL)
|
|
|
db51e6 |
+ return 0;
|
|
|
db51e6 |
if (!bfd_plugin_open_input (abfd, &file))
|
|
|
db51e6 |
return 0;
|
|
|
db51e6 |
file.handle = abfd;
|
|
|
db51e6 |
off_t cur_offset = lseek (file.fd, 0, SEEK_CUR);
|
|
|
db51e6 |
- claim_file (&file, &claimed);
|
|
|
db51e6 |
+ current_plugin->claim_file (&file, &claimed);
|
|
|
db51e6 |
lseek (file.fd, cur_offset, SEEK_SET);
|
|
|
db51e6 |
return claimed;
|
|
|
db51e6 |
}
|
|
|
db51e6 |
|
|
|
db51e6 |
-struct plugin_list_entry
|
|
|
db51e6 |
-{
|
|
|
db51e6 |
- /* These must be initialized for each IR object with LTO wrapper. */
|
|
|
db51e6 |
- ld_plugin_claim_file_handler claim_file;
|
|
|
db51e6 |
- ld_plugin_all_symbols_read_handler all_symbols_read;
|
|
|
db51e6 |
- ld_plugin_all_symbols_read_handler cleanup_handler;
|
|
|
db51e6 |
- bfd_boolean has_symbol_type;
|
|
|
db51e6 |
-
|
|
|
db51e6 |
- struct plugin_list_entry *next;
|
|
|
db51e6 |
-
|
|
|
db51e6 |
- /* These can be reused for all IR objects. */
|
|
|
db51e6 |
- const char *plugin_name;
|
|
|
db51e6 |
-};
|
|
|
db51e6 |
-
|
|
|
db51e6 |
-static struct plugin_list_entry *plugin_list = NULL;
|
|
|
db51e6 |
-static struct plugin_list_entry *current_plugin = NULL;
|
|
|
db51e6 |
-
|
|
|
db51e6 |
static int
|
|
|
db51e6 |
try_load_plugin (const char *pname,
|
|
|
db51e6 |
struct plugin_list_entry *plugin_list_iter,
|