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