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:
parent
18ad82c163
commit
5ae0078cd2
5 changed files with 160 additions and 39 deletions
|
@ -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. */
|
||||
|
|
14
bfd/bfd.c
14
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. *}
|
||||
|
|
63
bfd/plugin.c
63
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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
105
ld/plugin.c
105
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue