PR24262, plugin search dir doesn't respect --libdir
authorAlan Modra <amodra@gmail.com>
Thu, 26 Sep 2019 06:50:35 +0000 (16:20 +0930)
committerAlan Modra <amodra@gmail.com>
Tue, 8 Oct 2019 14:00:11 +0000 (00:30 +1030)
bfd/
PR 24262
* Makefile.am (AM_CPPFLAGS): Add -DLIBDIR.
* plugin.c (load_plugin): Search both ${libdir}/bfd-plugins and
${bindir}/../lib/bfd-plugins if different.
* Makefile.in: Regenerate.
ld/
PR 24262
* ld.texi (-plugin): Revert 2019-03-15 change.

(cherry picked from commit 41f37a6fb71f2a3de388108f5cdfca9cbe6e9d51)

bfd/ChangeLog
bfd/Makefile.am
bfd/Makefile.in
bfd/plugin.c
ld/ChangeLog
ld/ld.texi

index f60b5f8..2ceab8d 100644 (file)
@@ -1,3 +1,13 @@
+2019-10-09  Alan Modra  <amodra@gmail.com>
+
+       Apply from master
+       2019-09-26  Alan Modra  <amodra@gmail.com>
+       PR 24262
+       * Makefile.am (AM_CPPFLAGS): Add -DLIBDIR.
+       * plugin.c (load_plugin): Search both ${libdir}/bfd-plugins and
+       ${bindir}/../lib/bfd-plugins if different.
+       * Makefile.in: Regenerate.
+
 2019-09-30  Phil Blundell  <pb@pbcl.net>
 
        Release 2.33
index 4703955..6a39ef5 100644 (file)
@@ -53,7 +53,7 @@ ZLIBINC = @zlibinc@
 WARN_CFLAGS = @WARN_CFLAGS@
 NO_WERROR = @NO_WERROR@
 AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC)
-AM_CPPFLAGS = -DBINDIR='"$(bindir)"'
+AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DLIBDIR='"$(libdir)"'
 if PLUGINS
 bfdinclude_HEADERS += $(INCDIR)/plugin-api.h
 LIBDL = @lt_cv_dlopen_libs@
index 9c14721..80499d6 100644 (file)
@@ -479,8 +479,9 @@ libbfd_la_LDFLAGS = $(am__append_1) -release `cat libtool-soversion` \
 ZLIB = @zlibdir@ -lz
 ZLIBINC = @zlibinc@
 AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC)
-AM_CPPFLAGS = -DBINDIR='"$(bindir)"' @HDEFINES@ @COREFLAG@ @TDEFINES@ \
-       $(CSEARCH) $(CSWITCHES) $(HAVEVECS) @INCINTL@
+AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DLIBDIR='"$(libdir)"' @HDEFINES@ \
+       @COREFLAG@ @TDEFINES@ $(CSEARCH) $(CSWITCHES) $(HAVEVECS) \
+       @INCINTL@ $(am__empty)
 @PLUGINS_TRUE@LIBDL = @lt_cv_dlopen_libs@
 
 # bfd.h goes here, for now
index 5f760e9..139f772 100644 (file)
@@ -366,11 +366,15 @@ register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *))
 static int
 load_plugin (bfd *abfd)
 {
-  char *plugin_dir;
-  char *p;
-  DIR *d;
-  struct dirent *ent;
+  /* The intent was to search ${libdir}/bfd-plugins for plugins, but
+     unfortunately the original implementation wasn't precisely that
+     when configuring binutils using --libdir.  Search in the proper
+     path first, then the old one for backwards compatibility.  */
+  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;
@@ -381,38 +385,58 @@ load_plugin (bfd *abfd)
   if (plugin_program_name == NULL)
     return found;
 
-  plugin_dir = concat (BINDIR, "/../lib/bfd-plugins", NULL);
-  p = make_relative_prefix (plugin_program_name,
-                           BINDIR,
-                           plugin_dir);
-  free (plugin_dir);
-  plugin_dir = NULL;
-
-  d = opendir (p);
-  if (!d)
-    goto out;
-
-  while ((ent = readdir (d)))
+  /* 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 to zero or the actual st_ino is zero we might waste some
+     time, but that doesn't matter too much.  */
+  last_st.st_dev = 0;
+  last_st.st_ino = 0;
+  for (i = 0; i < sizeof (path) / sizeof (path[0]); i++)
     {
-      char *full_name;
-      struct stat s;
-      int valid_plugin;
-
-      full_name = concat (p, "/", ent->d_name, NULL);
-      if (stat (full_name, &s) == 0 && S_ISREG (s.st_mode))
-       found = try_load_plugin (full_name, abfd, &valid_plugin);
-      if (has_plugin <= 0)
-       has_plugin = valid_plugin;
-      free (full_name);
+      char *plugin_dir = make_relative_prefix (plugin_program_name,
+                                              BINDIR,
+                                              path[i]);
+      if (plugin_dir)
+       {
+         struct stat st;
+         DIR *d;
+
+         if (stat (plugin_dir, &st) == 0
+             && S_ISDIR (st.st_mode)
+             && !(last_st.st_dev == st.st_dev
+                  && last_st.st_ino == st.st_ino
+                  && st.st_ino != 0)
+             && (d = opendir (plugin_dir)) != NULL)
+           {
+             struct dirent *ent;
+
+             last_st.st_dev = st.st_dev;
+             last_st.st_ino = st.st_ino;
+             while ((ent = readdir (d)) != NULL)
+               {
+                 char *full_name;
+
+                 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;
+                   }
+                 free (full_name);
+                 if (found)
+                   break;
+               }
+             closedir (d);
+           }
+         free (plugin_dir);
+       }
       if (found)
        break;
     }
 
- out:
-  free (p);
-  if (d)
-    closedir (d);
-
   return found;
 }
 
index 8c2455d..1c986dc 100644 (file)
@@ -1,3 +1,10 @@
+2019-10-09  Alan Modra  <amodra@gmail.com>
+
+       Apply from master
+       2019-09-26  Alan Modra  <amodra@gmail.com>
+       PR 24262
+       * ld.texi (-plugin): Revert 2019-03-15 change.
+
 2019-09-30  Phil Blundell  <pb@pbcl.net>
 
        Release 2.33
index 8d5c7bc..b344705 100644 (file)
@@ -855,7 +855,7 @@ Note that the location of the compiler originated plugins is different
 from the place where the @command{ar}, @command{nm} and
 @command{ranlib} programs search for their plugins.  In order for
 those commands to make use of a compiler based plugin it must first be
-copied into the @file{$@{bindir@}/../lib/bfd-plugins} directory.  All gcc
+copied into the @file{$@{libdir@}/bfd-plugins} directory.  All gcc
 based linker plugins are backward compatible, so it is sufficient to
 just copy in the newest one.