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>
 
 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.
        * 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
    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
 
 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;
 
 {
   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)
        {
     {
       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;
        }
          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;
       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);
            }
 
          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 = *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.  */
     }
 
   /* Undo constraint twiddling.  */
@@ -7544,7 +7562,9 @@ lang_process (void)
   lang_statement_iteration++;
   map_input_to_output_sections (statement_list.head, NULL, NULL);
 
   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 ();
 
   /* 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)
     {
 
   while (ingroup)
     {
+      einfo (_("%P: missing --end-group; added as last command line option\n"));
       lang_leave_group ();
       ingroup--;
     }
       lang_leave_group ();
       ingroup--;
     }