Fix compile time warnings about comparisons always being false.
[deliverable/binutils-gdb.git] / bfd / plugin.c
index 376e92cdb3e7117b464e2a5a941486d9a67ddc2d..537ab603110b88550032cf49d8a7c6a354c3f09a 100644 (file)
@@ -1,5 +1,5 @@
 /* Plugin support for BFD.
-   Copyright (C) 2009-2019 Free Software Foundation, Inc.
+   Copyright (C) 2009-2020 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -102,6 +102,7 @@ dlerror (void)
 #define bfd_plugin_bfd_lookup_section_flags          bfd_generic_lookup_section_flags
 #define bfd_plugin_bfd_merge_sections                bfd_generic_merge_sections
 #define bfd_plugin_bfd_is_group_section                      bfd_generic_is_group_section
+#define bfd_plugin_bfd_group_name                    bfd_generic_group_name
 #define bfd_plugin_bfd_discard_group                 bfd_generic_discard_group
 #define bfd_plugin_section_already_linked            _bfd_generic_section_already_linked
 #define bfd_plugin_bfd_define_common_symbol          bfd_generic_define_common_symbol
@@ -262,7 +263,9 @@ try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
        }
     }
 
-  plugin_list_iter = (struct plugin_list_entry *) xmalloc (sizeof *plugin_list_iter);
+  plugin_list_iter = bfd_malloc (sizeof *plugin_list_iter);
+  if (plugin_list_iter == NULL)
+    return 0;
   plugin_list_iter->handle = plugin_handle;
   plugin_list_iter->claim_file = NULL;
   plugin_list_iter->next = plugin_list;
@@ -364,11 +367,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;
@@ -379,38 +386,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;
 }
 
This page took 0.024666 seconds and 4 git commands to generate.