PR24806, Linking with -T inside --start-group/--end-group

This patch processes INSERT AFTER and INSERT BEFORE in a user -T
script when such a script is invoked on the command line inside
--start-group/--end-group.  Also, ld now warns when the user simply
forgot --end-group.

	PR 24806
	* ldlang.c (process_insert_statements): Add start of list
	parameter.  Use rather than lang_os_list.head.  Process insert
	statements inside group statements with a recursive call.
	(lang_process): Adjust process_insert_statements call.
	* lexsup.c (parse_args): Warn when adding missing --end-group.
This commit is contained in:
Alan Modra 2019-07-31 23:10:40 +09:30
parent 5c1e6d53a5
commit 776ab89fe3
3 changed files with 45 additions and 15 deletions

View File

@ -1,3 +1,12 @@
2019-08-01 Alan Modra <amodra@gmail.com>
PR 24806
* ldlang.c (process_insert_statements): Add start of list
parameter. Use rather than lang_os_list.head. Process insert
statements inside group statements with a recursive call.
(lang_process): Adjust process_insert_statements call.
* lexsup.c (parse_args): Warn when adding missing --end-group.
2019-08-01 Alan Modra <amodra@gmail.com> 2019-08-01 Alan Modra <amodra@gmail.com>
* ldlang.h (lang_os_list): Rename from lang_output_section_statement. * ldlang.h (lang_os_list): Rename from lang_output_section_statement.

View File

@ -3916,21 +3916,26 @@ map_input_to_output_sections
start of the list and places them after the output section start of the list and places them after the output section
statement specified by the insert. This operation is complicated statement specified by the insert. This operation is complicated
by the fact that we keep a doubly linked list of output section by the fact that we keep a doubly linked list of output section
statements as well as the singly linked list of all statements. */ statements as well as the singly linked list of all statements.
FIXME someday: Twiddling with the list not only moves statements
from the user's script but also input and group statements that are
built from command line object files and --start-group. We only
get away with this because the list pointers used by file_chain
and input_file_chain are not reordered, and processing via
statement_list after this point mostly ignores input statements.
One exception is the map file, where LOAD and START GROUP/END GROUP
can end up looking odd. */
static void static void
process_insert_statements (void) process_insert_statements (lang_statement_union_type **start)
{ {
lang_statement_union_type **s; lang_statement_union_type **s;
lang_output_section_statement_type *first_os = NULL; lang_output_section_statement_type *first_os = NULL;
lang_output_section_statement_type *last_os = NULL; lang_output_section_statement_type *last_os = NULL;
lang_output_section_statement_type *os; lang_output_section_statement_type *os;
/* "start of list" is actually the statement immediately after s = start;
the special abs_section output statement, so that it isn't while (*s != NULL)
reordered. */
s = &lang_os_list.head;
while (*(s = &(*s)->header.next) != NULL)
{ {
if ((*s)->header.type == lang_output_section_statement_enum) if ((*s)->header.type == lang_output_section_statement_enum)
{ {
@ -3949,6 +3954,18 @@ process_insert_statements (void)
if (first_os == NULL) if (first_os == NULL)
first_os = last_os; first_os = last_os;
} }
else if ((*s)->header.type == lang_group_statement_enum)
{
/* A user might put -T between --start-group and
--end-group. One way this odd construct might arise is
from a wrapper around ld to change library search
behaviour. For example:
#! /bin/sh
exec real_ld --start-group "$@" --end-group
This isn't completely unreasonable so go looking inside a
group statement for insert statements. */
process_insert_statements (&(*s)->group_statement.children.head);
}
else if ((*s)->header.type == lang_insert_statement_enum) else if ((*s)->header.type == lang_insert_statement_enum)
{ {
lang_insert_statement_type *i = &(*s)->insert_statement; lang_insert_statement_type *i = &(*s)->insert_statement;
@ -4049,18 +4066,19 @@ process_insert_statements (void)
} }
ptr = insert_os_after (where); ptr = insert_os_after (where);
/* Snip everything after the abs_section output statement we /* Snip everything from the start of the list, up to and
know is at the start of the list, up to and including including the insert statement we are currently processing. */
the insert statement we are currently processing. */ first = *start;
first = lang_os_list.head->header.next; *start = (*s)->header.next;
lang_os_list.head->header.next = (*s)->header.next; /* Add them back where they belong, minus the insert. */
/* Add them back where they belong. */
*s = *ptr; *s = *ptr;
if (*s == NULL) if (*s == NULL)
statement_list.tail = s; statement_list.tail = s;
*ptr = first; *ptr = first;
s = &lang_os_list.head; s = start;
continue;
} }
s = &(*s)->header.next;
} }
/* Undo constraint twiddling. */ /* Undo constraint twiddling. */
@ -7544,7 +7562,9 @@ lang_process (void)
lang_statement_iteration++; lang_statement_iteration++;
map_input_to_output_sections (statement_list.head, NULL, NULL); map_input_to_output_sections (statement_list.head, NULL, NULL);
process_insert_statements (); /* Start at the statement immediately after the special abs_section
output statement, so that it isn't reordered. */
process_insert_statements (&lang_os_list.head->header.next);
/* Find any sections not attached explicitly and handle them. */ /* Find any sections not attached explicitly and handle them. */
lang_place_orphans (); lang_place_orphans ();

View File

@ -1602,6 +1602,7 @@ parse_args (unsigned argc, char **argv)
while (ingroup) while (ingroup)
{ {
einfo (_("%P: missing --end-group; added as last command line option\n"));
lang_leave_group (); lang_leave_group ();
ingroup--; ingroup--;
} }