PR24806, Linking with -T inside --start-group/--end-group
authorAlan Modra <amodra@gmail.com>
Wed, 31 Jul 2019 13:40:40 +0000 (23:10 +0930)
committerAlan Modra <amodra@gmail.com>
Thu, 1 Aug 2019 05:08:57 +0000 (14:38 +0930)
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
ld/ldlang.c
ld/lexsup.c

index 45bea25..a93d367 100644 (file)
@@ -1,5 +1,14 @@
 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>
+
        * ldlang.h (lang_os_list): Rename from lang_output_section_statement.
        * ldlang.c: Likewise throughout file.
        * emultempl/alphaelf.em: Likewise.
index 617f769..96daf0e 100644 (file)
@@ -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 ();
index 2539356..d4f1981 100644 (file)
@@ -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--;
     }