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
This commit is contained in:
H.J. Lu 2015-02-11 05:01:03 -08:00
parent 18ad82c163
commit 5ae0078cd2
5 changed files with 160 additions and 39 deletions

View file

@ -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. */

View file

@ -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. *}

View file

@ -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

View file

@ -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
{

View file

@ -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;
}
}