]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - ld/ldlang.c
Fix PR30358, performance with --sort-section
[thirdparty/binutils-gdb.git] / ld / ldlang.c
index 9ad405aa06c917035f4d90bb76e60e5a5307e20a..aa01c81e661e4ccf8693ea0c21fd394a5ba12610 100644 (file)
@@ -80,6 +80,8 @@ static unsigned int opb_shift = 0;
 /* Forward declarations.  */
 static void exp_init_os (etree_type *);
 static lang_input_statement_type *lookup_name (const char *);
+static bool wont_add_section_p (asection *,
+                               lang_output_section_statement_type *);
 static void insert_undefined (const char *);
 static bool sort_def_symbol (struct bfd_link_hash_entry *, void *);
 static lang_statement_union_type *new_statement (enum statement_enum type,
@@ -687,6 +689,11 @@ output_section_callback_sort (lang_wild_statement_type *ptr,
   if (unique_section_p (section, os))
     return;
 
+  /* Don't add sections to the tree when we already know that
+     lang_add_section won't do anything with it.  */
+  if (wont_add_section_p (section, os))
+    return;
+
   node = (lang_section_bst_type *) xmalloc (sizeof (lang_section_bst_type));
   node->left = 0;
   node->right = 0;
@@ -2514,27 +2521,20 @@ lang_discard_section_p (asection *section)
   return discard;
 }
 
-/* The wild routines.
-
-   These expand statements like *(.text) and foo.o to a list of
-   explicit actions, like foo.o(.text), bar.o(.text) and
-   foo.o(.text, .data).  */
+/* Return TRUE if SECTION is never going to be added to output statement
+   OUTPUT.  lang_add_section() definitely won't do anything with SECTION
+   if this returns TRUE.  It may do something (or not) if this returns FALSE.
 
-/* Add SECTION to the output section OUTPUT.  Do this by creating a
-   lang_input_section statement which is placed at PTR.  */
+   Can be used as early-out to filter matches.  This may set
+   output_section of SECTION, if it was unset, to the abs section in case
+   we discover SECTION to be always discarded.  This may also give
+   warning messages.  */
 
-void
-lang_add_section (lang_statement_list_type *ptr,
-                 asection *section,
-                 struct wildcard_list *pattern,
-                 struct flag_info *sflag_info,
-                 lang_output_section_statement_type *output)
+static bool
+wont_add_section_p (asection *section,
+                   lang_output_section_statement_type *output)
 {
-  flagword flags = section->flags;
-
   bool discard;
-  lang_input_section_type *new_section;
-  bfd *abfd = link_info.output_bfd;
 
   /* Is this section one we know should be discarded?  */
   discard = lang_discard_section_p (section);
@@ -2548,41 +2548,35 @@ lang_add_section (lang_statement_list_type *ptr,
     {
       if (section->output_section == NULL)
        {
-         /* This prevents future calls from assigning this section.  */
+         /* This prevents future calls from assigning this section or
+            warning about it again.  */
          section->output_section = bfd_abs_section_ptr;
        }
+      else if (bfd_is_abs_section (section->output_section))
+       ;
       else if (link_info.non_contiguous_regions_warnings)
        einfo (_("%P:%pS: warning: --enable-non-contiguous-regions makes "
                 "section `%pA' from `%pB' match /DISCARD/ clause.\n"),
               NULL, section, section->owner);
 
-      return;
-    }
-
-  if (sflag_info)
-    {
-      bool keep;
-
-      keep = bfd_lookup_section_flags (&link_info, sflag_info, section);
-      if (!keep)
-       return;
+      return true;
     }
 
   if (section->output_section != NULL)
     {
       if (!link_info.non_contiguous_regions)
-       return;
+       return true;
 
       /* SECTION has already been handled in a special way
         (eg. LINK_ONCE): skip it.  */
       if (bfd_is_abs_section (section->output_section))
-       return;
+       return true;
 
       /* Already assigned to the same output section, do not process
         it again, to avoid creating loops between duplicate sections
         later.  */
       if (section->output_section == output->bfd_section)
-       return;
+       return true;
 
       if (link_info.non_contiguous_regions_warnings && output->bfd_section)
        einfo (_("%P:%pS: warning: --enable-non-contiguous-regions may "
@@ -2597,6 +2591,42 @@ lang_add_section (lang_statement_list_type *ptr,
         size_input_section as appropriate.  */
     }
 
+  return false;
+}
+
+/* The wild routines.
+
+   These expand statements like *(.text) and foo.o to a list of
+   explicit actions, like foo.o(.text), bar.o(.text) and
+   foo.o(.text, .data).  */
+
+/* Add SECTION to the output section OUTPUT.  Do this by creating a
+   lang_input_section statement which is placed at PTR.  */
+
+void
+lang_add_section (lang_statement_list_type *ptr,
+                 asection *section,
+                 struct wildcard_list *pattern,
+                 struct flag_info *sflag_info,
+                 lang_output_section_statement_type *output)
+{
+  flagword flags = section->flags;
+
+  lang_input_section_type *new_section;
+  bfd *abfd = link_info.output_bfd;
+
+  if (wont_add_section_p (section, output))
+    return;
+
+  if (sflag_info)
+    {
+      bool keep;
+
+      keep = bfd_lookup_section_flags (&link_info, sflag_info, section);
+      if (!keep)
+       return;
+    }
+
   /* We don't copy the SEC_NEVER_LOAD flag from an input section
      to an output section, because we want to be able to include a
      SEC_NEVER_LOAD section in the middle of an otherwise loaded