From 776ab89fe3cdce91cd644058c9fcda0c506f995b Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 31 Jul 2019 23:10:40 +0930 Subject: [PATCH] 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. --- ld/ChangeLog | 9 +++++++++ ld/ldlang.c | 50 +++++++++++++++++++++++++++++++++++--------------- ld/lexsup.c | 1 + 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index 45bea2573d8..a93d367a544 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,12 @@ +2019-08-01 Alan Modra + + 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 * ldlang.h (lang_os_list): Rename from lang_output_section_statement. diff --git a/ld/ldlang.c b/ld/ldlang.c index 617f76919c4..96daf0ef11d 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -3916,21 +3916,26 @@ map_input_to_output_sections start of the list and places them after the output section statement specified by the insert. This operation is complicated 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 -process_insert_statements (void) +process_insert_statements (lang_statement_union_type **start) { lang_statement_union_type **s; lang_output_section_statement_type *first_os = NULL; lang_output_section_statement_type *last_os = NULL; lang_output_section_statement_type *os; - /* "start of list" is actually the statement immediately after - the special abs_section output statement, so that it isn't - reordered. */ - s = &lang_os_list.head; - while (*(s = &(*s)->header.next) != NULL) + s = start; + while (*s != NULL) { if ((*s)->header.type == lang_output_section_statement_enum) { @@ -3949,6 +3954,18 @@ process_insert_statements (void) if (first_os == NULL) 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) { lang_insert_statement_type *i = &(*s)->insert_statement; @@ -4049,18 +4066,19 @@ process_insert_statements (void) } ptr = insert_os_after (where); - /* Snip everything after the abs_section output statement we - know is at the start of the list, up to and including - the insert statement we are currently processing. */ - first = lang_os_list.head->header.next; - lang_os_list.head->header.next = (*s)->header.next; - /* Add them back where they belong. */ + /* Snip everything from the start of the list, up to and + including the insert statement we are currently processing. */ + first = *start; + *start = (*s)->header.next; + /* Add them back where they belong, minus the insert. */ *s = *ptr; if (*s == NULL) statement_list.tail = s; *ptr = first; - s = &lang_os_list.head; + s = start; + continue; } + s = &(*s)->header.next; } /* Undo constraint twiddling. */ @@ -7544,7 +7562,9 @@ lang_process (void) lang_statement_iteration++; 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. */ lang_place_orphans (); diff --git a/ld/lexsup.c b/ld/lexsup.c index 2539356baa7..d4f198125c1 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -1602,6 +1602,7 @@ parse_args (unsigned argc, char **argv) while (ingroup) { + einfo (_("%P: missing --end-group; added as last command line option\n")); lang_leave_group (); ingroup--; } -- 2.30.2