This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Merge linker plugin handling into BFD plugin support


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=5ae0078cd2b6b69e6119864e20987c8724916b29

commit 5ae0078cd2b6b69e6119864e20987c8724916b29
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Feb 11 05:01:03 2015 -0800

    Merge linker plugin handling into BFD plugin support
    
    Linker plugin_maybe_claim is the interface of linker plugin support.
    This patch extracts linker plugin_maybe_claim into plugin_object_p and
    makes it available to BFD via a new function:
    
    void register_ld_plugin_object_p (const bfd_target *(*) (bfd *));
    
    bfd_plugin_object_p calls plugin_object_p registered by linker first.  It
    adds an enum bfd_plugin_format field and a pointer to plugin dummy BFD so
    that plugin_object_p stores plugin dummy BFD to allow plugin_maybe_claim
    to retrieve it later.
    
    bfd/
    
    	PR ld/17878
    	* bfd.c (bfd_plugin_format): New.
    	(bfd): Add plugin_format and plugin_dummy_bfd.
    	* plugin.c (try_load_plugin): Take a pointer to bfd_boolean
    	argument to return TRUE if any plugin is found.  Set plugin_format.
    	(has_plugin): New.
    	(bfd_plugin_target_p): New.
    	(bfd_plugin_specified_p): Likewise.
    	(bfd_plugin_target_p): Likewise.
    	(register_ld_plugin_object_p): Likewise.
    	(bfd_plugin_set_plugin): Set has_plugin.
    	(load_plugin): Cache try_load_plugin result.
    	(bfd_plugin_object_p): Try ld_plugin_object_p first.  Check
    	plugin_format.
    	* plugin.h (bfd_plugin_target_p): New.
    	(bfd_plugin_specified_p): Likewise.
    	(register_ld_plugin_object_p): Likewise.
    	* bfd-in2.h: Regenerated.
    
    ld/
    
    	PR ld/17878
    	* plugin.c: Include ../bfd/plugin.h.
    	(plugin_get_ir_dummy_bfd): Call bfd_create with
    	link_info.output_bfd instead of srctemplate.  Copy BFD info
    	from srctemplate only if it doesn't use BFD plugin target
    	vector.
    	(plugin_load_plugins): Call register_ld_plugin_object_p with
    	(plugin_object_p)
    	(plugin_maybe_claim): Renamed to ...
    	(plugin_object_p): This.  Return dummy BFD target vector if
    	input is calimed by plugin library, otherwise return NULL.
    	Update plugin_format and plugin_dummy_bfd.
    	(plugin_maybe_claim): New.  Use plugin_object_p.
    
    xx

Diff:
---
 bfd/bfd-in2.h |  14 ++++++++
 bfd/bfd.c     |  14 ++++++++
 bfd/plugin.c  |  63 +++++++++++++++++++++++++++++++----
 bfd/plugin.h  |   3 ++
 ld/plugin.c   | 105 ++++++++++++++++++++++++++++++++++++++++------------------
 5 files changed, 160 insertions(+), 39 deletions(-)

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 91dbf80..678eaed 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6272,6 +6272,13 @@ enum bfd_direction
     both_direction = 3
   };
 
+enum bfd_plugin_format
+  {
+    bfd_plugin_uknown = 0,
+    bfd_plugin_yes = 1,
+    bfd_plugin_no = 2
+  };
+
 struct bfd
 {
   /* The filename the application opened the BFD with.  */
@@ -6428,6 +6435,13 @@ struct bfd
   /* Set if this is the linker output BFD.  */
   unsigned int is_linker_output : 1;
 
+  /* If this is an input for a compiler plug-in library.  */
+  ENUM_BITFIELD (bfd_plugin_format) plugin_format : 2;
+
+  /* Set to dummy BFD created when claimed by a compiler plug-in
+     library.  */
+  bfd *plugin_dummy_bfd;
+
   /* Currently my_archive is tested before adding origin to
      anything. I believe that this can become always an add of
      origin, with origin set to 0 for non archive files.  */
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 29a7c5d..69c6bde 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -44,6 +44,13 @@ CODE_FRAGMENT
 .    both_direction = 3
 .  };
 .
+.enum bfd_plugin_format
+.  {
+.    bfd_plugin_uknown = 0,
+.    bfd_plugin_yes = 1,
+.    bfd_plugin_no = 2
+.  };
+.
 .struct bfd
 .{
 .  {* The filename the application opened the BFD with.  *}
@@ -200,6 +207,13 @@ CODE_FRAGMENT
 .  {* Set if this is the linker output BFD.  *}
 .  unsigned int is_linker_output : 1;
 .
+.  {* If this is an input for a compiler plug-in library.  *}
+.  ENUM_BITFIELD (bfd_plugin_format) plugin_format : 2;
+.
+.  {* Set to dummy BFD created when claimed by a compiler plug-in
+.     library.  *}
+.  bfd *plugin_dummy_bfd;
+.
 .  {* Currently my_archive is tested before adding origin to
 .     anything. I believe that this can become always an add of
 .     origin, with origin set to 0 for non archive files.  *}
diff --git a/bfd/plugin.c b/bfd/plugin.c
index 94ed95b..b41e092 100644
--- a/bfd/plugin.c
+++ b/bfd/plugin.c
@@ -203,7 +203,7 @@ try_claim (bfd *abfd)
 }
 
 static int
-try_load_plugin (const char *pname, bfd *abfd)
+try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
 {
   void *plugin_handle;
   int tv_size = 4;
@@ -212,6 +212,8 @@ try_load_plugin (const char *pname, bfd *abfd)
   ld_plugin_onload onload;
   enum ld_plugin_status status;
 
+  *has_plugin_p = 0;
+
   plugin_handle = dlopen (pname, RTLD_NOW);
   if (!plugin_handle)
     {
@@ -244,25 +246,63 @@ try_load_plugin (const char *pname, bfd *abfd)
   if (status != LDPS_OK)
     goto err;
 
+  *has_plugin_p = 1;
+
+  abfd->plugin_format = bfd_plugin_no;
+
   if (!claim_file)
     goto err;
 
   if (!try_claim (abfd))
     goto err;
 
+  abfd->plugin_format = bfd_plugin_yes;
+
   return 1;
 
  err:
-  plugin_handle = NULL;
   return 0;
 }
 
+/* There may be plugin libraries in lib/bfd-plugins.  */
+
+static int has_plugin = -1;
+
+static const bfd_target *(*ld_plugin_object_p) (bfd *);
+
 static const char *plugin_name;
 
 void
 bfd_plugin_set_plugin (const char *p)
 {
   plugin_name = p;
+  has_plugin = p != NULL;
+}
+
+/* Return TRUE if a plugin library is used.  */
+
+bfd_boolean
+bfd_plugin_specified_p (void)
+{
+  return has_plugin > 0;
+}
+
+extern const bfd_target plugin_vec;
+
+/* Return TRUE if TARGET is a pointer to plugin_vec.  */
+
+bfd_boolean
+bfd_plugin_target_p (const bfd_target *target)
+{
+  return target == &plugin_vec;
+}
+
+/* Register OBJECT_P to be used by bfd_plugin_object_p.  */
+
+void
+register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *))
+{
+  ld_plugin_object_p = object_p;
 }
 
 static int
@@ -274,11 +314,14 @@ load_plugin (bfd *abfd)
   struct dirent *ent;
   int found = 0;
 
+  if (!has_plugin)
+    return found;
+
   if (plugin_name)
-    return try_load_plugin (plugin_name, abfd);
+    return try_load_plugin (plugin_name, abfd, &has_plugin);
 
   if (plugin_program_name == NULL)
-    return 0;
+    return found;
 
   plugin_dir = concat (BINDIR, "/../lib/bfd-plugins", NULL);
   p = make_relative_prefix (plugin_program_name,
@@ -295,10 +338,13 @@ load_plugin (bfd *abfd)
     {
       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);
+	found = try_load_plugin (full_name, abfd, &valid_plugin);
+      if (has_plugin <= 0)
+	has_plugin = valid_plugin;
       free (full_name);
       if (found)
 	break;
@@ -316,10 +362,13 @@ load_plugin (bfd *abfd)
 static const bfd_target *
 bfd_plugin_object_p (bfd *abfd)
 {
-  if (!load_plugin (abfd))
+  if (ld_plugin_object_p)
+    return ld_plugin_object_p (abfd);
+
+  if (abfd->plugin_format == bfd_plugin_uknown && !load_plugin (abfd))
     return NULL;
 
-  return abfd->xvec;
+  return abfd->plugin_format == bfd_plugin_yes ? abfd->xvec : NULL;
 }
 
 /* Copy any private info we understand from the input bfd
diff --git a/bfd/plugin.h b/bfd/plugin.h
index af98c59..1a66e6e 100644
--- a/bfd/plugin.h
+++ b/bfd/plugin.h
@@ -25,6 +25,9 @@
 
 void bfd_plugin_set_program_name (const char *);
 void bfd_plugin_set_plugin (const char *);
+bfd_boolean bfd_plugin_target_p (const bfd_target *);
+bfd_boolean bfd_plugin_specified_p (void);
+void register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *));
 
 typedef struct plugin_data_struct
 {
diff --git a/ld/plugin.c b/ld/plugin.c
index e5bdb01..b48ce86 100644
--- a/ld/plugin.c
+++ b/ld/plugin.c
@@ -30,6 +30,7 @@
 #include "ldexp.h"
 #include "ldlang.h"
 #include "ldfile.h"
+#include "../bfd/plugin.h"
 #include "plugin.h"
 #include "plugin-api.h"
 #include "elf-bfd.h"
@@ -174,6 +175,8 @@ static bfd_boolean plugin_notice (struct bfd_link_info *,
 				  struct bfd_link_hash_entry *,
 				  bfd *, asection *, bfd_vma, flagword);
 
+static const bfd_target * plugin_object_p (bfd *);
+
 #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
 
 #define RTLD_NOW 0	/* Dummy value.  */
@@ -295,14 +298,19 @@ plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
 
   bfd_use_reserved_id = 1;
   abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *) NULL),
-		     srctemplate);
+		     link_info.output_bfd);
   if (abfd != NULL)
     {
       abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN;
-      bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
-      bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate));
-      if (bfd_make_writable (abfd)
-	  && bfd_copy_private_bfd_data (srctemplate, abfd))
+      if (!bfd_make_writable (abfd))
+	goto report_error;
+      if (! bfd_plugin_target_p (srctemplate->xvec))
+	{
+	  bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
+	  bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate));
+	  if (!bfd_copy_private_bfd_data (srctemplate, abfd))
+	    goto report_error;
+	}
 	{
 	  flagword flags;
 
@@ -313,6 +321,7 @@ plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
 	    return abfd;
 	}
     }
+report_error:
   einfo (_("could not create dummy IR bfd: %F%E\n"));
   return NULL;
 }
@@ -979,6 +988,8 @@ plugin_load_plugins (void)
   link_info.lto_plugin_active = TRUE;
   link_info.callbacks = &plugin_callbacks;
 
+  register_ld_plugin_object_p (plugin_object_p);
+
 #if HAVE_MMAP && HAVE_GETPAGESIZE
   plugin_pagesize = getpagesize ();;
 #endif
@@ -1024,22 +1035,36 @@ plugin_strdup (bfd *abfd, const char *str)
   return copy;
 }
 
-void
-plugin_maybe_claim (lang_input_statement_type *entry)
+static const bfd_target *
+plugin_object_p (bfd *ibfd)
 {
-  int claimed = 0;
+  int claimed;
   plugin_input_file_t *input;
   off_t offset, filesize;
   struct ld_plugin_input_file file;
   bfd *abfd;
-  bfd *ibfd = entry->the_bfd;
-  bfd_boolean inarchive = bfd_my_archive (ibfd) != NULL;
-  const char *name
-    = inarchive ? bfd_my_archive (ibfd)->filename : ibfd->filename;
-  int fd = open (name, O_RDONLY | O_BINARY);
+  bfd_boolean inarchive;
+  const char *name;
+  int fd;
+
+  /* Don't try the dummy object file.  */
+  if ((ibfd->flags & BFD_PLUGIN) != 0)
+    return NULL;
+
+  if (ibfd->plugin_format != bfd_plugin_uknown)
+    {
+      if (ibfd->plugin_format == bfd_plugin_yes)
+	return ibfd->plugin_dummy_bfd->xvec;
+      else
+	return NULL;
+    }
+
+  inarchive = bfd_my_archive (ibfd) != NULL;
+  name = inarchive ? bfd_my_archive (ibfd)->filename : ibfd->filename;
+  fd = open (name, O_RDONLY | O_BINARY);
 
   if (fd < 0)
-    return;
+    return NULL;
 
   /* We create a dummy BFD, initially empty, to house whatever symbols
      the plugin may want to add.  */
@@ -1085,35 +1110,32 @@ plugin_maybe_claim (lang_input_statement_type *entry)
   input->filesize = filesize;
   input->name = plugin_strdup (abfd, ibfd->filename);
 
+  claimed = 0;
+
   if (plugin_call_claim_file (&file, &claimed))
     einfo (_("%P%F: %s: plugin reported error claiming file\n"),
 	   plugin_error_plugin ());
 
-  if (input->fd != -1 && ibfd->format == bfd_object)
+  if (input->fd != -1 && ! bfd_plugin_target_p (ibfd->xvec))
     {
-      /* FIXME: fd belongs to us, not the plugin.  IR for GCC plugin,
-	 which doesn't need fd after plugin_call_claim_file, is
-	 stored in bfd_object file.  Since GCC plugin before GCC 5
-	 doesn't call release_input_file, we close it here.  IR for
-	 LLVM plugin, which needs fd after plugin_call_claim_file and
-	 calls release_input_file after it is done, is stored in
-	 non-bfd_object file.  This scheme doesn't work when a plugin
-	 needs fd and its IR is stored in bfd_object file.  */
+      /* FIXME: fd belongs to us, not the plugin.  GCC plugin, which
+	 doesn't need fd after plugin_call_claim_file, doesn't use
+	 BFD plugin target vector.  Since GCC plugin doesn't call
+	 release_input_file, we close it here.  LLVM plugin, which
+	 needs fd after plugin_call_claim_file and calls
+	 release_input_file after it is done, uses BFD plugin target
+	 vector.  This scheme doesn't work when a plugin needs fd and
+	 doesn't use BFD plugin target vector neither.  */
       close (fd);
       input->fd = -1;
     }
 
   if (claimed)
     {
-      /* Discard the real file's BFD and substitute the dummy one.  */
-
-      /* BFD archive handling caches elements so we can't call
-	 bfd_close for archives.  */
-      if (!inarchive)
-	bfd_close (ibfd);
+      ibfd->plugin_format = bfd_plugin_yes;
+      ibfd->plugin_dummy_bfd = abfd;
       bfd_make_readable (abfd);
-      entry->the_bfd = abfd;
-      entry->flags.claimed = TRUE;
+      return abfd->xvec;
     }
   else
     {
@@ -1134,8 +1156,27 @@ plugin_maybe_claim (lang_input_statement_type *entry)
 
       /* If plugin didn't claim the file, we don't need the dummy bfd.
 	 Can't avoid speculatively creating it, alas.  */
+      ibfd->plugin_format = bfd_plugin_no;
       bfd_close_all_done (abfd);
-      entry->flags.claimed = FALSE;
+      return NULL;
+    }
+}
+
+void
+plugin_maybe_claim (lang_input_statement_type *entry)
+{
+  if (plugin_object_p (entry->the_bfd))
+    {
+      bfd *abfd = entry->the_bfd->plugin_dummy_bfd;
+
+      /* Discard the real file's BFD and substitute the dummy one.  */
+
+      /* BFD archive handling caches elements so we can't call
+	 bfd_close for archives.  */
+      if (entry->the_bfd->my_archive == NULL)
+	bfd_close (entry->the_bfd);
+      entry->the_bfd = abfd;
+      entry->flags.claimed = 1;
     }
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]