Add a compile-time test for PR ld/22263
[binutils-gdb.git] / ld / ldlang.c
index 96de2e265909c1d536a9e583db4e665650d6037c..0018188205a2f71d90114395197b379970ab1ab2 100644 (file)
@@ -227,7 +227,7 @@ unique_section_p (const asection *sec,
 
 static bfd_boolean
 walk_wild_file_in_exclude_list (struct name_list *exclude_list,
-                                lang_input_statement_type *file)
+                               lang_input_statement_type *file)
 {
   struct name_list *list_tmp;
 
@@ -2367,9 +2367,9 @@ lang_add_section (lang_statement_list_type *ptr,
   if ((flags & (SEC_LINK_ONCE | SEC_GROUP)) == (SEC_LINK_ONCE | SEC_GROUP))
     {
       if (link_info.resolve_section_groups)
-        flags &= ~(SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_RELOC);
+       flags &= ~(SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_RELOC);
       else
-        flags &= ~(SEC_LINK_DUPLICATES | SEC_RELOC);
+       flags &= ~(SEC_LINK_DUPLICATES | SEC_RELOC);
     }
   else if (!bfd_link_relocatable (&link_info))
     flags &= ~(SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_RELOC);
@@ -2834,6 +2834,7 @@ load_symbols (lang_input_statement_type *entry,
     case bfd_archive:
       check_excluded_libs (entry->the_bfd);
 
+      entry->the_bfd->usrdata = entry;
       if (entry->flags.whole_archive)
        {
          bfd *member = NULL;
@@ -4424,7 +4425,7 @@ print_wild_statement (lang_wild_statement_type *w,
       name_list *tmp;
       minfo ("EXCLUDE_FILE(%s", w->exclude_name_list->name);
       for (tmp = w->exclude_name_list->next; tmp; tmp = tmp->next)
-        minfo (" %s", tmp->name);
+       minfo (" %s", tmp->name);
       minfo (") ");
     }
 
@@ -4443,40 +4444,40 @@ print_wild_statement (lang_wild_statement_type *w,
       int closing_paren = 0;
 
       switch (sec->spec.sorted)
-        {
-        case none:
-          break;
-
-        case by_name:
-          minfo ("SORT_BY_NAME(");
-          closing_paren = 1;
-          break;
-
-        case by_alignment:
-          minfo ("SORT_BY_ALIGNMENT(");
-          closing_paren = 1;
-          break;
-
-        case by_name_alignment:
-          minfo ("SORT_BY_NAME(SORT_BY_ALIGNMENT(");
-          closing_paren = 2;
-          break;
-
-        case by_alignment_name:
-          minfo ("SORT_BY_ALIGNMENT(SORT_BY_NAME(");
-          closing_paren = 2;
-          break;
-
-        case by_none:
-          minfo ("SORT_NONE(");
-          closing_paren = 1;
-          break;
-
-        case by_init_priority:
-          minfo ("SORT_BY_INIT_PRIORITY(");
-          closing_paren = 1;
-          break;
-        }
+       {
+       case none:
+         break;
+
+       case by_name:
+         minfo ("SORT_BY_NAME(");
+         closing_paren = 1;
+         break;
+
+       case by_alignment:
+         minfo ("SORT_BY_ALIGNMENT(");
+         closing_paren = 1;
+         break;
+
+       case by_name_alignment:
+         minfo ("SORT_BY_NAME(SORT_BY_ALIGNMENT(");
+         closing_paren = 2;
+         break;
+
+       case by_alignment_name:
+         minfo ("SORT_BY_ALIGNMENT(SORT_BY_NAME(");
+         closing_paren = 2;
+         break;
+
+       case by_none:
+         minfo ("SORT_NONE(");
+         closing_paren = 1;
+         break;
+
+       case by_init_priority:
+         minfo ("SORT_BY_INIT_PRIORITY(");
+         closing_paren = 1;
+         break;
+       }
 
       if (sec->spec.exclude_name_list != NULL)
        {
@@ -4491,7 +4492,7 @@ print_wild_statement (lang_wild_statement_type *w,
       else
        minfo ("*");
       for (;closing_paren > 0; closing_paren--)
-        minfo (")");
+       minfo (")");
       if (sec->next)
        minfo (" ");
     }
@@ -6418,7 +6419,7 @@ ldlang_place_orphan (asection *s)
       int constraint = 0;
 
       if (config.orphan_handling == orphan_handling_error)
-       einfo ("%X%P: error: unplaced orphan section `%A' from `%B'.\n",
+       einfo (_("%X%P: error: unplaced orphan section `%A' from `%B'.\n"),
               s, s->owner);
 
       if (config.unique_orphan_sections || unique_section_p (s, NULL))
@@ -6436,8 +6437,8 @@ ldlang_place_orphan (asection *s)
        }
 
       if (config.orphan_handling == orphan_handling_warn)
-       einfo ("%P: warning: orphan section `%A' from `%B' being "
-              "placed in section `%s'.\n",
+       einfo (_("%P: warning: orphan section `%A' from `%B' being "
+                "placed in section `%s'.\n"),
               s, s->owner, os->name);
     }
 }
@@ -6543,9 +6544,9 @@ lang_for_each_input_file (void (*func) (lang_input_statement_type *))
 {
   lang_input_statement_type *f;
 
-  for (f = (lang_input_statement_type *) input_file_chain.head;
+  for (f = &input_file_chain.head->input_statement;
        f != NULL;
-       f = (lang_input_statement_type *) f->next_real_file)
+       f = &f->next_real_file->input_statement)
     func (f);
 }
 
@@ -6942,6 +6943,51 @@ find_replacements_insert_point (void)
   return lastobject;
 }
 
+/* Find where to insert ADD, an archive element or shared library
+   added during a rescan.  */
+
+static lang_statement_union_type **
+find_rescan_insertion (lang_input_statement_type *add)
+{
+  bfd *add_bfd = add->the_bfd;
+  lang_input_statement_type *f;
+  lang_input_statement_type *last_loaded = NULL;
+  lang_input_statement_type *before = NULL;
+  lang_statement_union_type **iter = NULL;
+
+  if (add_bfd->my_archive != NULL)
+    add_bfd = add_bfd->my_archive;
+
+  /* First look through the input file chain, to find an object file
+     before the one we've rescanned.  Normal object files always
+     appear on both the input file chain and the file chain, so this
+     lets us get quickly to somewhere near the correct place on the
+     file chain if it is full of archive elements.  Archives don't
+     appear on the file chain, but if an element has been extracted
+     then their input_statement->next points at it.  */
+  for (f = &input_file_chain.head->input_statement;
+       f != NULL;
+       f = &f->next_real_file->input_statement)
+    {
+      if (f->the_bfd == add_bfd)
+       {
+         before = last_loaded;
+         if (f->next != NULL)
+           return &f->next->input_statement.next;
+       }
+      if (f->the_bfd != NULL && f->next != NULL)
+       last_loaded = f;
+    }
+
+  for (iter = before ? &before->next : &file_chain.head->input_statement.next;
+       *iter != NULL;
+       iter = &(*iter)->input_statement.next)
+    if ((*iter)->input_statement.the_bfd->my_archive == NULL)
+      break;
+
+  return iter;
+}
+
 /* 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.)  */
@@ -7112,7 +7158,36 @@ lang_process (void)
            lang_list_insert_after (&file_chain, &files, &file_chain.head);
 
          /* Rescan archives in case new undefined symbols have appeared.  */
+         files = file_chain;
          open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
+         lang_list_remove_tail (&file_chain, &files);
+         while (files.head != NULL)
+           {
+             lang_statement_union_type **insert;
+             lang_statement_union_type **iter, *temp;
+             bfd *my_arch;
+
+             insert = find_rescan_insertion (&files.head->input_statement);
+             /* All elements from an archive can be added at once.  */
+             iter = &files.head->input_statement.next;
+             my_arch = files.head->input_statement.the_bfd->my_archive;
+             if (my_arch != NULL)
+               for (; *iter != NULL; iter = &(*iter)->input_statement.next)
+                 if ((*iter)->input_statement.the_bfd->my_archive != my_arch)
+                   break;
+             temp = *insert;
+             *insert = files.head;
+             files.head = *iter;
+             *iter = temp;
+             if (my_arch != NULL)
+               {
+                 lang_input_statement_type *parent = my_arch->usrdata;
+                 if (parent != NULL)
+                   parent->next = (lang_statement_union_type *)
+                     ((char *) iter
+                      - offsetof (lang_input_statement_type, next));
+               }
+           }
        }
     }
 #endif /* ENABLE_PLUGINS */
@@ -7960,6 +8035,7 @@ lang_leave_overlay (etree_type *lma_expr,
   overlay_vma = NULL;
   overlay_list = NULL;
   overlay_max = NULL;
+  overlay_subalign = NULL;
 }
 \f
 /* Version handling.  This is only useful for ELF.  */