PR ld/12365

PR ld/12672
bfd/
	* bfd.c (BFD_PLUGIN): Define.
	(BFD_FLAGS_SAVED, BFD_FLAGS_FOR_BFD_USE_MASK): Add BFD_PLUGIN.
	* bfd-in2.h: Regenerate.
	* elflink.c (elf_link_output_extsym): Strip undefined plugin syms.
	* opncls.c (bfd_make_readable): Don't lose original bfd flags.
ld/
	* ldfile.c (ldfile_try_open_bfd): Don't attempt any plugin action
	when no_more_claiming.
	* ldmain.c (add_archive_element): Likewise.
	(multiple_definition): Remove plugin_multiple_definition call.
	(notice): Remove plugin_notice call.
	* ldlang.c (lang_list_insert_after, void lang_list_remove_tail): Move.
	Delete prototype.
	(plugin_insert): New static var.
	(open_input_bfds): Only rescan libs after plugin insert point.
	(lang_gc_sections): Omit plugin claimed files.
	(lang_process): Set plugin_insert.  Only rescan when plugin adds
	objects.
	* plugin.h (no_more_claiming): Declare.
	(plugin_notice, plugin_multiple_definition): Don't declare.
	* plugin.c: Formatting.
	(orig_notice_all, orig_allow_multiple_defs, orig_callbacks,
	plugin_callbacks): New static vars.
	(no_more_claiming): Make global.
	(plugin_cached_allow_multiple_defs): Delete.
	(plugin_get_ir_dummy_bfd): Set SEC_EXCLUDE on dummy .text section,
	use newer bfd_make_section variant.  Make COMMON section too.
	Error handling.  Correct setting of gp size.
	(asymbol_from_plugin_symbol): Properly cast last arg of concat.
	(message): Likewise for ACONCAT.
	(asymbol_from_plugin_symbol): Use our COMMON section.
	(get_symbols): When report_plugin_symbols, show visibility too.
	(init_non_ironly_hash): Move.  Don't test non_ironly_hash.
	(plugin_load_plugins): Save state of linker callbacks, set up to
	call plugin_notice instead.  Call init_non_ironly_hash here.
	(plugin_call_all_symbols_read): Set plugin_multiple_definition in
	plugin callbacks.
	(plugin_notice): Rewrite.
	(plugin_multiple_definition): Make static, call original callback.
ld/testsuite/
	* ld-plugin/plugin-7.d: Adjust for plugin changes.
	* ld-plugin/plugin-8.d: Likewise.
	* ld-plugin/plugin.exp: Pass --verbose=2 for visibility test, and
	compare ld output to..
	* ld-plugin/plugin-12.d: New.
This commit is contained in:
Alan Modra 2011-04-17 23:15:13 +00:00
parent 0283589814
commit 9e2278f567
13 changed files with 223 additions and 184 deletions

View File

@ -5110,14 +5110,17 @@ struct bfd
/* Decompress sections in this BFD. */
#define BFD_DECOMPRESS 0x10000
/* BFD is a dummy, for plugins. */
#define BFD_PLUGIN 0x20000
/* Flags bits to be saved in bfd_preserve_save. */
#define BFD_FLAGS_SAVED \
(BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS)
(BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN)
/* Flags bits which are for BFD use only. */
#define BFD_FLAGS_FOR_BFD_USE_MASK \
(BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
| BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT)
| BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT)
/* Currently my_archive is tested before adding origin to
anything. I believe that this can become always an add of

View File

@ -157,14 +157,17 @@ CODE_FRAGMENT
. {* Decompress sections in this BFD. *}
.#define BFD_DECOMPRESS 0x10000
.
. {* BFD is a dummy, for plugins. *}
.#define BFD_PLUGIN 0x20000
.
. {* Flags bits to be saved in bfd_preserve_save. *}
.#define BFD_FLAGS_SAVED \
. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS)
. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN)
.
. {* Flags bits which are for BFD use only. *}
.#define BFD_FLAGS_FOR_BFD_USE_MASK \
. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
. | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT)
. | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT)
.
. {* Currently my_archive is tested before adding origin to
. anything. I believe that this can become always an add of

View File

@ -8704,6 +8704,11 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
|| h->root.type == bfd_link_hash_defweak)
&& elf_discarded_section (h->root.u.def.section))
strip = TRUE;
else if ((h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_undefweak)
&& h->root.u.undef.abfd != NULL
&& (h->root.u.undef.abfd->flags & BFD_PLUGIN) != 0)
strip = TRUE;
else
strip = FALSE;

View File

@ -875,7 +875,7 @@ bfd_make_readable (bfd *abfd)
abfd->section_count = 0;
abfd->usrdata = NULL;
abfd->cacheable = FALSE;
abfd->flags = BFD_IN_MEMORY;
abfd->flags |= BFD_IN_MEMORY;
abfd->mtime_set = FALSE;
abfd->target_defaulted = TRUE;

View File

@ -313,7 +313,8 @@ success:
will be needed when and if we want to bfd_create a new
one using this one as a template. */
if (bfd_check_format (entry->the_bfd, bfd_object)
&& plugin_active_plugins_p ())
&& plugin_active_plugins_p ()
&& !no_more_claiming)
{
int fd = open (attempt, O_RDONLY | O_BINARY);
if (fd >= 0)

View File

@ -86,13 +86,6 @@ static void print_statement_list (lang_statement_union_type *,
static void print_statements (void);
static void print_input_section (asection *, bfd_boolean);
static bfd_boolean lang_one_common (struct bfd_link_hash_entry *, void *);
#ifdef ENABLE_PLUGINS
static void lang_list_insert_after (lang_statement_list_type *destlist,
lang_statement_list_type *srclist,
lang_statement_union_type **field);
static void lang_list_remove_tail (lang_statement_list_type *destlist,
lang_statement_list_type *origlist);
#endif /* ENABLE_PLUGINS */
static void lang_record_phdrs (void);
static void lang_do_version_exports_section (void);
static void lang_finalize_version_expr_head
@ -3180,6 +3173,9 @@ enum open_bfd_mode
OPEN_BFD_FORCE = 1,
OPEN_BFD_RESCAN = 2
};
#ifdef ENABLE_PLUGINS
static lang_input_statement_type *plugin_insert = NULL;
#endif
static void
open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
@ -3236,6 +3232,10 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
force it to be researched unless the whole archive
has been loaded already. Do the same for a rescan. */
if (mode != OPEN_BFD_NORMAL
#ifdef ENABLE_PLUGINS
&& ((mode & OPEN_BFD_RESCAN) == 0
|| plugin_insert == NULL)
#endif
&& !s->input_statement.whole_archive
&& s->input_statement.loaded
&& bfd_check_format (s->input_statement.the_bfd,
@ -3271,6 +3271,12 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
}
}
}
#ifdef ENABLE_PLUGINS
/* If we have found the point at which a plugin added new
files, clear plugin_insert to enable archive rescan. */
if (&s->input_statement == plugin_insert)
plugin_insert = NULL;
#endif
break;
case lang_assignment_statement_enum:
if (s->assignment_statement.exp->assign.hidden)
@ -6279,6 +6285,10 @@ lang_gc_sections (void)
LANG_FOR_EACH_INPUT_STATEMENT (f)
{
asection *sec;
#ifdef ENABLE_PLUGINS
if (f->claimed)
continue;
#endif
for (sec = f->the_bfd->sections; sec != NULL; sec = sec->next)
if ((sec->flags & SEC_DEBUGGING) == 0)
sec->flags &= ~SEC_EXCLUDE;
@ -6452,6 +6462,38 @@ find_replacements_insert_point (void)
insert point. */
return lastobject;
}
/* Insert SRCLIST into DESTLIST after given element by chaining
on FIELD as the next-pointer. (Counterintuitively does not need
a pointer to the actual after-node itself, just its chain field.) */
static void
lang_list_insert_after (lang_statement_list_type *destlist,
lang_statement_list_type *srclist,
lang_statement_union_type **field)
{
*(srclist->tail) = *field;
*field = srclist->head;
if (destlist->tail == field)
destlist->tail = srclist->tail;
}
/* Detach new nodes added to DESTLIST since the time ORIGLIST
was taken as a copy of it and leave them in ORIGLIST. */
static void
lang_list_remove_tail (lang_statement_list_type *destlist,
lang_statement_list_type *origlist)
{
union lang_statement_union **savetail;
/* Check that ORIGLIST really is an earlier state of DESTLIST. */
ASSERT (origlist->head == destlist->head);
savetail = origlist->tail;
origlist->head = *(savetail);
origlist->tail = destlist->tail;
destlist->tail = savetail;
*savetail = NULL;
}
#endif /* ENABLE_PLUGINS */
void
@ -6484,6 +6526,7 @@ lang_process (void)
{
lang_statement_list_type added;
lang_statement_list_type files, inputfiles;
/* Now all files are read, let the plugin(s) decide if there
are any more to be added to the link before we call the
emulation's after_open hook. We create a private list of
@ -6509,27 +6552,29 @@ lang_process (void)
{
/* If so, we will insert them into the statement list immediately
after the first input file that was claimed by the plugin. */
lang_input_statement_type *claim1 = find_replacements_insert_point ();
plugin_insert = find_replacements_insert_point ();
/* If a plugin adds input files without having claimed any, we
don't really have a good idea where to place them. Just putting
them at the start or end of the list is liable to leave them
outside the crtbegin...crtend range. */
ASSERT (claim1 != NULL);
/* Splice the new statement list into the old one after claim1. */
lang_list_insert_after (stat_ptr, &added, &claim1->header.next);
ASSERT (plugin_insert != NULL);
/* Splice the new statement list into the old one. */
lang_list_insert_after (stat_ptr, &added,
&plugin_insert->header.next);
/* Likewise for the file chains. */
lang_list_insert_after (&input_file_chain, &inputfiles,
&claim1->next_real_file);
&plugin_insert->next_real_file);
/* We must be careful when relinking file_chain; we may need to
insert the new files at the head of the list if the insert
point chosen is the dummy first input file. */
if (claim1->filename)
lang_list_insert_after (&file_chain, &files, &claim1->next);
if (plugin_insert->filename)
lang_list_insert_after (&file_chain, &files, &plugin_insert->next);
else
lang_list_insert_after (&file_chain, &files, &file_chain.head);
/* Rescan archives in case new undefined symbols have appeared. */
open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
}
/* Rescan any archives in case new undefined symbols have appeared. */
open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
}
#endif /* ENABLE_PLUGINS */
@ -6952,40 +6997,6 @@ lang_statement_append (lang_statement_list_type *list,
list->tail = field;
}
#ifdef ENABLE_PLUGINS
/* Insert SRCLIST into DESTLIST after given element by chaining
on FIELD as the next-pointer. (Counterintuitively does not need
a pointer to the actual after-node itself, just its chain field.) */
static void
lang_list_insert_after (lang_statement_list_type *destlist,
lang_statement_list_type *srclist,
lang_statement_union_type **field)
{
*(srclist->tail) = *field;
*field = srclist->head;
if (destlist->tail == field)
destlist->tail = srclist->tail;
}
/* Detach new nodes added to DESTLIST since the time ORIGLIST
was taken as a copy of it and leave them in ORIGLIST. */
static void
lang_list_remove_tail (lang_statement_list_type *destlist,
lang_statement_list_type *origlist)
{
union lang_statement_union **savetail;
/* Check that ORIGLIST really is an earlier state of DESTLIST. */
ASSERT (origlist->head == destlist->head);
savetail = origlist->tail;
origlist->head = *(savetail);
origlist->tail = destlist->tail;
destlist->tail = savetail;
*savetail = NULL;
}
#endif /* ENABLE_PLUGINS */
/* Set the output format type. -oformat overrides scripts. */
void

View File

@ -804,7 +804,9 @@ add_archive_element (struct bfd_link_info *info,
BFD, but we still want to output the original BFD filename. */
orig_input = *input;
#ifdef ENABLE_PLUGINS
if (bfd_my_archive (abfd) != NULL && plugin_active_plugins_p ())
if (bfd_my_archive (abfd) != NULL
&& plugin_active_plugins_p ()
&& !no_more_claiming)
{
/* We must offer this archive member to the plugins to claim. */
int fd = open (bfd_my_archive (abfd)->filename, O_RDONLY | O_BINARY);
@ -944,22 +946,11 @@ multiple_definition (struct bfd_link_info *info ATTRIBUTE_UNUSED,
asection *nsec,
bfd_vma nval)
{
#ifdef ENABLE_PLUGINS
/* We may get called back even when --allow-multiple-definition is in
effect, as the plugin infrastructure needs to use this hook in
order to swap out IR-only symbols for real ones. In that case,
it will let us know not to continue by returning TRUE even if this
is not an IR-only vs. non-IR symbol conflict. */
if (plugin_multiple_definition (info, name, obfd, osec, oval, nbfd,
nsec, nval))
return TRUE;
#endif /* ENABLE_PLUGINS */
/* If either section has the output_section field set to
bfd_abs_section_ptr, it means that the section is being
discarded, and this is not really a multiple definition at all.
FIXME: It would be cleaner to somehow ignore symbols defined in
sections which are being discarded. */
FIXME: It would be cleaner to somehow ignore symbols defined in
sections which are being discarded. */
if ((osec->output_section != NULL
&& ! bfd_is_abs_section (osec)
&& bfd_is_abs_section (osec->output_section))
@ -1456,17 +1447,8 @@ notice (struct bfd_link_info *info,
return TRUE;
}
#ifdef ENABLE_PLUGINS
/* We should hide symbols in the dummy IR BFDs from the nocrossrefs list
and let the real object files that are generated and added later trip
the error instead. Similarly would be better to trace the real symbol
from the real file than the temporary dummy. */
if (!plugin_notice (info, name, abfd, section, value))
return TRUE;
#endif /* ENABLE_PLUGINS */
if (info->notice_hash != NULL
&& bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)
&& bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)
{
if (bfd_is_und_section (section))
einfo ("%B: reference to %s\n", abfd, name);

View File

@ -97,15 +97,18 @@ static const char *error_plugin = NULL;
cases when establishing symbol resolutions. */
static struct bfd_hash_table *non_ironly_hash = NULL;
/* State of linker "notice" and "multiple_definition" interfaces
before we poked at them. */
static bfd_boolean orig_notice_all;
static bfd_boolean orig_allow_multiple_defs;
/* Original linker callbacks, and the plugin version. */
static const struct bfd_link_callbacks *orig_callbacks;
static struct bfd_link_callbacks plugin_callbacks;
/* Set at all symbols read time, to avoid recursively offering the plugin
its own newly-added input files and libs to claim. */
static bfd_boolean no_more_claiming = FALSE;
/* If the --allow-multiple-definition command-line option is active, we
have to disable it so that BFD always calls our hook, and simulate the
effect (when not resolving IR vs. real symbols) ourselves by ensuring
TRUE is returned from the hook. */
static bfd_boolean plugin_cached_allow_multiple_defs = FALSE;
bfd_boolean no_more_claiming = FALSE;
/* List of tags to set in the constant leading part of the tv array. */
static const enum ld_plugin_tag tv_header_tags[] =
@ -130,6 +133,17 @@ static const enum ld_plugin_tag tv_header_tags[] =
/* How many entries in the constant leading part of the tv array. */
static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags);
/* Forward references. */
static bfd_boolean plugin_notice (struct bfd_link_info *info,
const char *name, bfd *abfd,
asection *section, bfd_vma value);
static bfd_boolean plugin_multiple_definition (struct bfd_link_info *info,
const char *name,
bfd *obfd, asection *osec,
bfd_vma oval, bfd *nbfd,
asection *nsec,
bfd_vma nval);
#if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
#define RTLD_NOW 0 /* Dummy value. */
@ -225,24 +239,30 @@ plugin_opt_plugin_arg (const char *arg)
bfd *
plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
{
asection *sec;
bfd *abfd;
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);
bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
bfd_make_writable (abfd);
bfd_copy_private_bfd_data (srctemplate, abfd);
bfd_set_gp_size (abfd, bfd_get_gp_size (abfd));
/* Create a minimal set of sections to own the symbols. */
sec = bfd_make_section_old_way (abfd, ".text");
bfd_set_section_flags (abfd, sec,
(SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
| SEC_ALLOC | SEC_LOAD | SEC_KEEP));
sec->output_section = sec;
sec->output_offset = 0;
return abfd;
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))
{
flagword flags;
/* Create sections to own the symbols. */
flags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
| SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE);
if (bfd_make_section_anyway_with_flags (abfd, ".text", flags))
return abfd;
}
}
einfo (_("could not create dummy IR bfd: %F%E\n"));
return NULL;
}
/* Check if the BFD passed in is an IR dummy object file. */
@ -254,9 +274,9 @@ is_ir_dummy_bfd (const bfd *abfd)
Likewise, the usrdata field may be NULL if ABFD was added by the
backend without a corresponding input statement, as happens e.g.
when processing DT_NEEDED dependencies. */
return abfd
&& abfd->usrdata
&& ((lang_input_statement_type *)(abfd->usrdata))->claimed;
return (abfd
&& abfd->usrdata
&& ((lang_input_statement_type *)(abfd->usrdata))->claimed);
}
/* Helpers to convert between BFD and GOLD symbol formats. */
@ -269,7 +289,7 @@ asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
asym->the_bfd = abfd;
asym->name = (ldsym->version
? concat (ldsym->name, "@", ldsym->version, NULL)
? concat (ldsym->name, "@", ldsym->version, (const char *) NULL)
: ldsym->name);
asym->value = 0;
switch (ldsym->def)
@ -487,9 +507,9 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
/* Find out which section owns the symbol. Since it's not undef,
it must have an owner; if it's not a common symbol, both defs
and weakdefs keep it in the same place. */
owner_sec = (blhe->type == bfd_link_hash_common)
? blhe->u.c.p->section
: blhe->u.def.section;
owner_sec = (blhe->type == bfd_link_hash_common
? blhe->u.c.p->section
: blhe->u.def.section);
/* We need to know if the sym is referenced from non-IR files. Or
even potentially-referenced, perhaps in a future final link if
@ -539,10 +559,12 @@ get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
? LDPR_PREEMPTED_IR
: LDPR_PREEMPTED_REG);
report_symbol:
report_symbol:
if (report_plugin_symbols)
einfo ("%P: %B: symbol `%s' definition: %d, resolution: %d\n",
abfd, syms[n].name, syms[n].def, syms[n].resolution);
einfo (_("%P: %B: symbol `%s' "
"definition: %d, visibility: %d, resolution: %d\n"),
abfd, syms[n].name,
syms[n].def, syms[n].visibility, syms[n].resolution);
}
return LDPS_OK;
}
@ -599,14 +621,13 @@ message (int level, const char *format, ...)
case LDPL_FATAL:
case LDPL_ERROR:
default:
{
char *newfmt = ACONCAT ((level == LDPL_FATAL
? "%P%F: " : "%P%X: ",
format, "\n", NULL));
fflush (stdout);
vfinfo (stderr, newfmt, args, TRUE);
fflush (stderr);
}
{
char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%P%F: " : "%P%X: ",
format, "\n", (const char *) NULL));
fflush (stdout);
vfinfo (stderr, newfmt, args, TRUE);
fflush (stderr);
}
break;
}
@ -714,6 +735,27 @@ plugin_active_plugins_p (void)
return plugins_list != NULL;
}
/* Init the non_ironly hash table. */
static void
init_non_ironly_hash (void)
{
struct bfd_sym_chain *sym;
non_ironly_hash
= (struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table));
if (!bfd_hash_table_init_n (non_ironly_hash,
bfd_hash_newfunc,
sizeof (struct bfd_hash_entry),
61))
einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
for (sym = &entry_symbol; sym != NULL; sym = sym->next)
if (sym->name
&& !bfd_hash_lookup (non_ironly_hash, sym->name, TRUE, TRUE))
einfo (_("%P%X: hash table failure adding symbol %s\n"),
sym->name);
}
/* Load up and initialise all plugins after argument parsing. */
int
plugin_load_plugins (void)
@ -761,7 +803,13 @@ plugin_load_plugins (void)
/* Since plugin(s) inited ok, assume they're going to want symbol
resolutions, which needs us to track which symbols are referenced
by non-IR files using the linker's notice callback. */
orig_notice_all = link_info.notice_all;
orig_callbacks = link_info.callbacks;
plugin_callbacks = *orig_callbacks;
plugin_callbacks.notice = &plugin_notice;
link_info.notice_all = TRUE;
link_info.callbacks = &plugin_callbacks;
init_non_ironly_hash ();
return 0;
}
@ -803,8 +851,9 @@ plugin_call_all_symbols_read (void)
as the plugin infrastructure relies on the multiple_definition
callback to swap out the dummy IR-only BFDs for new real ones
when it starts opening the files added during this callback. */
plugin_cached_allow_multiple_defs = link_info.allow_multiple_definition;
orig_allow_multiple_defs = link_info.allow_multiple_definition;
link_info.allow_multiple_definition = FALSE;
plugin_callbacks.multiple_definition = &plugin_multiple_definition;
while (curplug)
{
@ -847,30 +896,6 @@ plugin_call_cleanup (void)
plugin_error_plugin ());
}
/* Lazily init the non_ironly hash table. */
static void
init_non_ironly_hash (void)
{
struct bfd_sym_chain *sym;
if (non_ironly_hash == NULL)
{
non_ironly_hash =
(struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table));
if (!bfd_hash_table_init_n (non_ironly_hash,
bfd_hash_newfunc,
sizeof (struct bfd_hash_entry),
61))
einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
for (sym = &entry_symbol; sym != NULL; sym = sym->next)
if (sym->name
&& !bfd_hash_lookup (non_ironly_hash, sym->name, TRUE, TRUE))
einfo (_("%P%X: hash table failure adding symbol %s\n"),
sym->name);
}
}
/* To determine which symbols should be resolved LDPR_PREVAILING_DEF
and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
the linker adds them to the linker hash table. If we see a symbol
@ -879,32 +904,38 @@ init_non_ironly_hash (void)
it was referenced only by IR files. We have to notice_all symbols,
because we won't necessarily know until later which ones will be
contributed by IR files. */
bfd_boolean
plugin_notice (struct bfd_link_info *info ATTRIBUTE_UNUSED,
const char *name, bfd *abfd,
asection *section, bfd_vma value ATTRIBUTE_UNUSED)
static bfd_boolean
plugin_notice (struct bfd_link_info *info,
const char *name,
bfd *abfd,
asection *section,
bfd_vma value)
{
bfd_boolean is_ref = bfd_is_und_section (section);
bfd_boolean is_dummy = is_ir_dummy_bfd (abfd);
init_non_ironly_hash ();
/* We only care about refs, not defs, indicated by section pointing
to the undefined section (according to the bfd linker notice callback
interface definition). */
if (is_ref && !is_dummy)
if (name != NULL)
{
/* This is a ref from a non-IR file, so note the ref'd symbol
in the non-IR-only hash. */
if (!bfd_hash_lookup (non_ironly_hash, name, TRUE, TRUE))
einfo (_("%P%X: %s: hash table failure adding symbol %s\n"),
abfd->filename, name);
}
else if (!is_ref && is_dummy)
{
/* No further processing since this is a def from an IR dummy BFD. */
return FALSE;
/* No further processing if this def/ref is from an IR dummy BFD. */
if (is_ir_dummy_bfd (abfd))
return TRUE;
/* We only care about refs, not defs, indicated by section
pointing to the undefined section (according to the bfd
linker notice callback interface definition). */
if (bfd_is_und_section (section))
{
/* This is a ref from a non-IR file, so note the ref'd
symbol in the non-IR-only hash. */
if (!bfd_hash_lookup (non_ironly_hash, name, TRUE, TRUE))
einfo (_("%P%X: %s: hash table failure adding symbol %s\n"),
abfd->filename, name);
}
}
/* Continue with cref/nocrossref/trace-sym processing. */
if (name == NULL
|| orig_notice_all
|| (info->notice_hash != NULL
&& bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
return (*orig_callbacks->notice) (info, name, abfd, section, value);
return TRUE;
}
@ -917,10 +948,9 @@ plugin_notice (struct bfd_link_info *info ATTRIBUTE_UNUSED,
real BFD. We return true if this was not-really-a-clash because
we've fixed it up, or anyway if --allow-multiple-definition was in
effect (before we disabled it to ensure we got called back). */
bfd_boolean
static bfd_boolean
plugin_multiple_definition (struct bfd_link_info *info, const char *name,
bfd *obfd, asection *osec ATTRIBUTE_UNUSED,
bfd_vma oval ATTRIBUTE_UNUSED,
bfd *obfd, asection *osec, bfd_vma oval,
bfd *nbfd, asection *nsec, bfd_vma nval)
{
if (is_ir_dummy_bfd (obfd))
@ -937,5 +967,10 @@ plugin_multiple_definition (struct bfd_link_info *info, const char *name,
blhe->u.def.value = nval;
return TRUE;
}
return plugin_cached_allow_multiple_defs;
if (orig_allow_multiple_defs)
return TRUE;
return (*orig_callbacks->multiple_definition) (info, name, obfd, osec, oval,
nbfd, nsec, nval);
}

View File

@ -24,6 +24,10 @@
/* Report plugin symbols. */
extern bfd_boolean report_plugin_symbols;
/* Set at all symbols read time, to avoid recursively offering the plugin
its own newly-added input files and libs to claim. */
extern bfd_boolean no_more_claiming;
/* This is the only forward declaration we need to avoid having
to include the plugin-api.h header in order to use this file. */
struct ld_plugin_input_file;
@ -62,17 +66,4 @@ extern void plugin_call_cleanup (void);
add_symbols hook has been called so that it can be read when linking. */
extern bfd *plugin_get_ir_dummy_bfd (const char *name, bfd *template);
/* Notice-symbol bfd linker callback hook. */
extern bfd_boolean plugin_notice (struct bfd_link_info *info,
const char *name, bfd *abfd,
asection *section, bfd_vma value);
/* Multiple-definition bfd linker callback hook. */
extern bfd_boolean plugin_multiple_definition (struct bfd_link_info *info,
const char *name,
bfd *obfd, asection *osec,
bfd_vma oval, bfd *nbfd,
asection *nsec,
bfd_vma nval);
#endif /* !def GLD_PLUGIN_H */

View File

@ -0,0 +1,6 @@
#...
.*: symbol `func' definition: 0, visibility: 0, resolution: 2
.*: symbol `func1' definition: 0, visibility: 1, resolution: 3
.*: symbol `func2' definition: 0, visibility: 2, resolution: 3
.*: symbol `func3' definition: 0, visibility: 3, resolution: 3
#pass

View File

@ -26,5 +26,6 @@ hook called: claim_file tmpdir/func.o \[@0/.* CLAIMED
hook called: claim_file tmpdir/text.o \[@0/.* not claimed
#...
hook called: all symbols read.
`func' referenced in section `\.text' of tmpdir/main.o: defined in discarded section .*
hook called: cleanup.
#...

View File

@ -30,5 +30,6 @@ hook called: claim_file tmpdir/text.o \[@0/.* not claimed
hook called: all symbols read.
Sym: '_?func' Resolution: LDPR_PREVAILING_DEF
Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY
`func' referenced in section `\.text' of tmpdir/main.o: defined in discarded section .*
hook called: cleanup.
#...

View File

@ -152,8 +152,8 @@ set plugin_extra_elf_tests [list \
-plugin-opt sym:${_}func2::0:2:0 \
-plugin-opt sym:${_}func3::0:3:0 \
-plugin-opt dumpresolutions \
$testobjfiles $libs" "" "" {{ld plugin-ignore.d} \
{readelf -s plugin-vis-1.d}} "main.x" ] \
-plugin-opt add:tmpdir/func.o \
$testobjfiles $libs --verbose=2" "" "" {{ld plugin-12.d}} "main.x" ] \
]
if { !$can_compile || $failed_compile } {