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