[PATCH] Revise linker plugin API to better preserve link order.

ld/ChangeLog:

2011-03-10  Dave Korn  <dave.korn.cygwin@gmail.com>

	* ldlang.h (lang_input_statement_type): Add new 'claim_archive' flag,
	wrapping both it and 'claim' flag in #ifdef ENABLE_PLUGINS.
	* ldmain.c (add_archive_element): Set it if the member is claimed.
	* ldlang.c (new_afile): Initialise claim_archive and claimed members.
	(find_replacements_insert_point): New helper function.
	(lang_process): After adding and opening replacement files passed
	from plugin, splice them into correct place in statement list and
	file chains to preserve critical link order.
	(lang_list_insert_after): New helper function.
	(lang_list_remove_tail): Likewise.
This commit is contained in:
Dave Korn 2011-03-10 10:25:02 +00:00
parent 8f7e76d024
commit 8543fde54a
4 changed files with 140 additions and 9 deletions

View File

@ -1,3 +1,16 @@
2011-03-10 Dave Korn <dave.korn.cygwin@gmail.com>
* ldlang.h (lang_input_statement_type): Add new 'claim_archive' flag,
wrapping both it and 'claim' flag in #ifdef ENABLE_PLUGINS.
* ldmain.c (add_archive_element): Set it if the member is claimed.
* ldlang.c (new_afile): Initialise claim_archive and claimed members.
(find_replacements_insert_point): New helper function.
(lang_process): After adding and opening replacement files passed
from plugin, splice them into correct place in statement list and
file chains to preserve critical link order.
(lang_list_insert_after): New helper function.
(lang_list_remove_tail): Likewise.
2011-03-10 Dave Korn <dave.korn.cygwin@gmail.com>
* plugin.c (IRONLY_SUFFIX): Revise to nicely human-readable form.

View File

@ -86,6 +86,13 @@ 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
@ -1127,6 +1134,10 @@ new_afile (const char *name,
p->whole_archive = whole_archive;
p->loaded = FALSE;
p->missing_file = FALSE;
#ifdef ENABLE_PLUGINS
p->claimed = FALSE;
p->claim_archive = FALSE;
#endif /* ENABLE_PLUGINS */
lang_statement_append (&input_file_chain,
(lang_statement_union_type *) p,
@ -6395,6 +6406,40 @@ lang_relax_sections (bfd_boolean need_layout)
}
}
#ifdef ENABLE_PLUGINS
/* Find the insert point for the plugin's replacement files. We
place them after the first claimed real object file, or if the
first claimed object is an archive member, after the last real
object file immediately preceding the archive. In the event
no objects have been claimed at all, we return the first dummy
object file on the list as the insert point; that works, but
the callee must be careful when relinking the file_chain as it
is not actually on that chain, only the statement_list and the
input_file list; in that case, the replacement files must be
inserted at the head of the file_chain. */
static lang_input_statement_type *
find_replacements_insert_point (void)
{
lang_input_statement_type *claim1, *lastobject;
lastobject = &input_file_chain.head->input_statement;
for (claim1 = &file_chain.head->input_statement;
claim1 != NULL;
claim1 = &claim1->next->input_statement)
{
if (claim1->claimed)
return claim1->claim_archive ? lastobject : claim1;
/* Update lastobject if this is a real object file. */
if (claim1->the_bfd && (claim1->the_bfd->my_archive == NULL))
lastobject = claim1;
}
/* No files were claimed by the plugin. Choose the last object
file found on the list (maybe the first, dummy entry) as the
insert point. */
return lastobject;
}
#endif /* ENABLE_PLUGINS */
void
lang_process (void)
{
@ -6421,21 +6466,54 @@ lang_process (void)
open_input_bfds (statement_list.head, FALSE);
#ifdef ENABLE_PLUGINS
if (plugin_active_plugins_p ())
{
union lang_statement_union **listend;
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. */
listend = statement_list.tail;
ASSERT (!*listend);
emulation's after_open hook. We create a private list of
input statements for this purpose, which we will eventually
insert into the global statment list after the first claimed
file. */
added = *stat_ptr;
/* We need to manipulate all three chains in synchrony. */
files = file_chain;
inputfiles = input_file_chain;
if (plugin_call_all_symbols_read ())
einfo (_("%P%F: %s: plugin reported error after all symbols read\n"),
plugin_error_plugin ());
/* If any new files were added, they will be on the end of the
statement list, and we can open them now by getting open_input_bfds
to carry on from where it ended last time. */
if (*listend)
open_input_bfds (*listend, FALSE);
/* Open any newly added files, updating the file chains. */
open_input_bfds (added.head, FALSE);
/* Restore the global list pointer now they have all been added. */
lang_list_remove_tail (stat_ptr, &added);
/* And detach the fresh ends of the file lists. */
lang_list_remove_tail (&file_chain, &files);
lang_list_remove_tail (&input_file_chain, &inputfiles);
/* Were any new files added? */
if (added.head != NULL)
{
/* 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 ();
/* 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);
/* Likewise for the file chains. */
lang_list_insert_after (&input_file_chain, &inputfiles,
&claim1->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);
else
lang_list_insert_after (&file_chain, &files, &file_chain.head);
}
}
#endif /* ENABLE_PLUGINS */
@ -6858,6 +6936,40 @@ 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

@ -287,9 +287,14 @@ typedef struct lang_input_statement_struct
/* Set if the file does not exist. */
unsigned int missing_file : 1;
#ifdef ENABLE_PLUGINS
/* Set if the file was claimed by a plugin. */
unsigned int claimed : 1;
/* Set if the file was claimed from an archive. */
unsigned int claim_archive : 1;
#endif /* ENABLE_PLUGINS */
} lang_input_statement_type;
typedef struct

View File

@ -833,6 +833,7 @@ add_archive_element (struct bfd_link_info *info,
/* Substitute the dummy BFD. */
input->the_bfd = file.handle;
input->claimed = TRUE;
input->claim_archive = TRUE;
bfd_make_readable (input->the_bfd);
*subsbfd = input->the_bfd;
}