From 5ae0078cd2b6b69e6119864e20987c8724916b29 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 11 Feb 2015 05:01:03 -0800 Subject: 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 --- ld/plugin.c | 105 ++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 32 deletions(-) (limited to 'ld') 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; } } -- cgit v1.1