4b3b7c0
diff -rup binutils.orig/bfd/bfd-in2.h binutils-2.35.1/bfd/bfd-in2.h
4b3b7c0
--- binutils.orig/bfd/bfd-in2.h	2021-01-04 13:18:10.234368481 +0000
4b3b7c0
+++ binutils-2.35.1/bfd/bfd-in2.h	2021-01-04 13:18:20.596301287 +0000
4b3b7c0
@@ -1177,6 +1177,9 @@ typedef struct bfd_section
4b3b7c0
   struct bfd_symbol *symbol;
4b3b7c0
   struct bfd_symbol **symbol_ptr_ptr;
4b3b7c0
 
4b3b7c0
+  /* The matching section name pattern in linker script.  */
4b3b7c0
+  const char *pattern;
4b3b7c0
+
4b3b7c0
   /* Early in the link process, map_head and map_tail are used to build
4b3b7c0
      a list of input sections attached to an output section.  Later,
4b3b7c0
      output sections use these fields for a list of bfd_link_order
4b3b7c0
@@ -1370,8 +1373,8 @@ discarded_section (const asection *sec)
4b3b7c0
   /* target_index, used_by_bfd, constructor_chain, owner,           */ \
4b3b7c0
      0,            NULL,        NULL,              NULL,               \
4b3b7c0
                                                                        \
4b3b7c0
-  /* symbol,                    symbol_ptr_ptr,                     */ \
4b3b7c0
-     (struct bfd_symbol *) SYM, &SEC.symbol,                           \
4b3b7c0
+  /* symbol,                    symbol_ptr_ptr, pattern,            */ \
4b3b7c0
+     (struct bfd_symbol *) SYM, &SEC.symbol,    NULL,                  \
4b3b7c0
                                                                        \
4b3b7c0
   /* map_head, map_tail, already_assigned                           */ \
4b3b7c0
      { NULL }, { NULL }, NULL                                          \
4b3b7c0
diff -rup binutils.orig/bfd/elflink.c binutils-2.35.1/bfd/elflink.c
4b3b7c0
--- binutils.orig/bfd/elflink.c	2021-01-04 13:18:10.223368552 +0000
4b3b7c0
+++ binutils-2.35.1/bfd/elflink.c	2021-01-04 13:18:20.599301268 +0000
4b3b7c0
@@ -11662,8 +11662,21 @@ compare_link_order (const void *a, const
4b3b7c0
   const struct bfd_link_order *blo = *(const struct bfd_link_order **) b;
4b3b7c0
   asection *asec = elf_linked_to_section (alo->u.indirect.section);
4b3b7c0
   asection *bsec = elf_linked_to_section (blo->u.indirect.section);
4b3b7c0
-  bfd_vma apos = asec->output_section->lma + asec->output_offset;
4b3b7c0
-  bfd_vma bpos = bsec->output_section->lma + bsec->output_offset;
4b3b7c0
+  bfd_vma apos, bpos;
4b3b7c0
+
4b3b7c0
+  /* Check if any sections are unordered.  */
4b3b7c0
+  if (asec == NULL || bsec == NULL)
4b3b7c0
+    {
4b3b7c0
+      /* Place ordered sections before unordered sections.  */
4b3b7c0
+      if (bsec != NULL)
4b3b7c0
+	return 1;
4b3b7c0
+      else if (asec != NULL)
4b3b7c0
+	return -1;
4b3b7c0
+      return 0;
4b3b7c0
+    }
4b3b7c0
+
4b3b7c0
+  apos = asec->output_section->lma + asec->output_offset;
4b3b7c0
+  bpos = bsec->output_section->lma + bsec->output_offset;
4b3b7c0
 
4b3b7c0
   if (apos < bpos)
4b3b7c0
     return -1;
4b3b7c0
@@ -11698,14 +11711,14 @@ compare_link_order (const void *a, const
4b3b7c0
    sections.  Ideally we'd do this in the linker proper.  */
4b3b7c0
 
4b3b7c0
 static bfd_boolean
4b3b7c0
-elf_fixup_link_order (bfd *abfd, asection *o)
4b3b7c0
+elf_fixup_link_order (struct bfd_link_info *info, bfd *abfd, asection *o)
4b3b7c0
 {
4b3b7c0
   size_t seen_linkorder;
4b3b7c0
   size_t seen_other;
4b3b7c0
   size_t n;
4b3b7c0
   struct bfd_link_order *p;
4b3b7c0
   bfd *sub;
4b3b7c0
-  struct bfd_link_order **sections;
4b3b7c0
+  struct bfd_link_order **sections, **indirect_sections;
4b3b7c0
   asection *other_sec, *linkorder_sec;
4b3b7c0
   bfd_vma offset;  /* Octets.  */
4b3b7c0
 
4b3b7c0
@@ -11736,7 +11749,9 @@ elf_fixup_link_order (bfd *abfd, asectio
4b3b7c0
       else
4b3b7c0
 	seen_other++;
4b3b7c0
 
4b3b7c0
-      if (seen_other && seen_linkorder)
4b3b7c0
+      /* Allow mixed ordered and unordered input sections for
4b3b7c0
+         non-relocatable link.  */
4b3b7c0
+      if (bfd_link_relocatable (info) && seen_other && seen_linkorder)
4b3b7c0
 	{
4b3b7c0
 	  if (other_sec && linkorder_sec)
4b3b7c0
 	    _bfd_error_handler
4b3b7c0
@@ -11756,6 +11771,10 @@ elf_fixup_link_order (bfd *abfd, asectio
4b3b7c0
   if (!seen_linkorder)
4b3b7c0
     return TRUE;
4b3b7c0
 
4b3b7c0
+  /* Non-relocatable output can have both ordered and unordered input
4b3b7c0
+     sections.  */
4b3b7c0
+  seen_linkorder += seen_other;
4b3b7c0
+
4b3b7c0
   sections = bfd_malloc (seen_linkorder * sizeof (*sections));
4b3b7c0
   if (sections == NULL)
4b3b7c0
     return FALSE;
4b3b7c0
@@ -11764,22 +11783,51 @@ elf_fixup_link_order (bfd *abfd, asectio
4b3b7c0
   for (p = o->map_head.link_order; p != NULL; p = p->next)
4b3b7c0
     sections[seen_linkorder++] = p;
4b3b7c0
 
4b3b7c0
-  /* Sort the input sections in the order of their linked section.  */
4b3b7c0
-  qsort (sections, seen_linkorder, sizeof (*sections), compare_link_order);
4b3b7c0
+  for (indirect_sections = sections, n = 0; n < seen_linkorder;)
4b3b7c0
+    {
4b3b7c0
+      /* Find the first bfd_indirect_link_order section.  */
4b3b7c0
+      if (indirect_sections[0]->type == bfd_indirect_link_order)
4b3b7c0
+	{
4b3b7c0
+	  /* Count the consecutive bfd_indirect_link_order sections
4b3b7c0
+	     with the same pattern.  */
4b3b7c0
+	  size_t i, n_indirect;
4b3b7c0
+	  const char *pattern
4b3b7c0
+	    = indirect_sections[0]->u.indirect.section->pattern;
4b3b7c0
+	  for (i = n + 1; i < seen_linkorder; i++)
4b3b7c0
+	    if (sections[i]->type != bfd_indirect_link_order
4b3b7c0
+		|| sections[i]->u.indirect.section->pattern != pattern)
4b3b7c0
+	      break;
4b3b7c0
+	  n_indirect = i - n;
4b3b7c0
+	  /* Sort the bfd_indirect_link_order sections in the order of
4b3b7c0
+	     their linked section.  */
4b3b7c0
+	  qsort (indirect_sections, n_indirect, sizeof (*sections),
4b3b7c0
+		 compare_link_order);
4b3b7c0
+	  indirect_sections += n_indirect;
4b3b7c0
+	  n += n_indirect;
4b3b7c0
+	}
4b3b7c0
+      else
4b3b7c0
+	{
4b3b7c0
+	  indirect_sections++;
4b3b7c0
+	  n++;
4b3b7c0
+	}
4b3b7c0
+    }
4b3b7c0
 
4b3b7c0
-  /* Change the offsets of the sections.  */
4b3b7c0
+  /* Change the offsets of the bfd_indirect_link_order sections.  */
4b3b7c0
   offset = 0;
4b3b7c0
   for (n = 0; n < seen_linkorder; n++)
4b3b7c0
-    {
4b3b7c0
-      bfd_vma mask;
4b3b7c0
-      asection *s = sections[n]->u.indirect.section;
4b3b7c0
-      unsigned int opb = bfd_octets_per_byte (abfd, s);
4b3b7c0
-
4b3b7c0
-      mask = ~(bfd_vma) 0 << s->alignment_power * opb;
4b3b7c0
-      offset = (offset + ~mask) & mask;
4b3b7c0
-      sections[n]->offset = s->output_offset = offset / opb;
4b3b7c0
-      offset += sections[n]->size;
4b3b7c0
-    }
4b3b7c0
+    if (sections[n]->type == bfd_indirect_link_order)
4b3b7c0
+      {
4b3b7c0
+	bfd_vma mask;
4b3b7c0
+	asection *s = sections[n]->u.indirect.section;
4b3b7c0
+	unsigned int opb = bfd_octets_per_byte (abfd, s);
4b3b7c0
+
4b3b7c0
+	mask = ~(bfd_vma) 0 << s->alignment_power * opb;
4b3b7c0
+	offset = (offset + ~mask) & mask;
4b3b7c0
+	sections[n]->offset = s->output_offset = offset / opb;
4b3b7c0
+	offset += sections[n]->size;
4b3b7c0
+      }
4b3b7c0
+    else
4b3b7c0
+      offset = sections[n]->offset + sections[n]->size;
4b3b7c0
 
4b3b7c0
   free (sections);
4b3b7c0
   return TRUE;
4b3b7c0
@@ -12408,7 +12456,7 @@ bfd_elf_final_link (bfd *abfd, struct bf
4b3b7c0
   /* Reorder SHF_LINK_ORDER sections.  */
4b3b7c0
   for (o = abfd->sections; o != NULL; o = o->next)
4b3b7c0
     {
4b3b7c0
-      if (!elf_fixup_link_order (abfd, o))
4b3b7c0
+      if (!elf_fixup_link_order (info, abfd, o))
4b3b7c0
 	return FALSE;
4b3b7c0
     }
4b3b7c0
 
4b3b7c0
diff -rup binutils.orig/bfd/section.c binutils-2.35.1/bfd/section.c
4b3b7c0
--- binutils.orig/bfd/section.c	2021-01-04 13:18:10.233368487 +0000
4b3b7c0
+++ binutils-2.35.1/bfd/section.c	2021-01-04 13:18:20.599301268 +0000
4b3b7c0
@@ -541,6 +541,9 @@ CODE_FRAGMENT
4b3b7c0
 .  struct bfd_symbol *symbol;
4b3b7c0
 .  struct bfd_symbol **symbol_ptr_ptr;
4b3b7c0
 .
4b3b7c0
+.  {* The matching section name pattern in linker script.  *}
4b3b7c0
+.  const char *pattern;
4b3b7c0
+.
4b3b7c0
 .  {* Early in the link process, map_head and map_tail are used to build
4b3b7c0
 .     a list of input sections attached to an output section.  Later,
4b3b7c0
 .     output sections use these fields for a list of bfd_link_order
4b3b7c0
@@ -734,8 +737,8 @@ CODE_FRAGMENT
4b3b7c0
 .  {* target_index, used_by_bfd, constructor_chain, owner,           *}	\
4b3b7c0
 .     0,            NULL,        NULL,              NULL,		\
4b3b7c0
 .									\
4b3b7c0
-.  {* symbol,                    symbol_ptr_ptr,                     *}	\
4b3b7c0
-.     (struct bfd_symbol *) SYM, &SEC.symbol,				\
4b3b7c0
+.  {* symbol,                    symbol_ptr_ptr, pattern,            *}	\
4b3b7c0
+.     (struct bfd_symbol *) SYM, &SEC.symbol,    NULL,			\
4b3b7c0
 .									\
4b3b7c0
 .  {* map_head, map_tail, already_assigned                           *}	\
4b3b7c0
 .     { NULL }, { NULL }, NULL						\
4b3b7c0
diff -rup binutils.orig/gas/config/obj-elf.c binutils-2.35.1/gas/config/obj-elf.c
4b3b7c0
--- binutils.orig/gas/config/obj-elf.c	2021-01-04 13:18:09.942370375 +0000
4b3b7c0
+++ binutils-2.35.1/gas/config/obj-elf.c	2021-01-04 13:18:20.599301268 +0000
4b3b7c0
@@ -659,7 +659,9 @@ obj_elf_change_section (const char *name
4b3b7c0
 	    }
4b3b7c0
 	}
4b3b7c0
 
4b3b7c0
-      if (old_sec == NULL && ((attr & ~(SHF_MASKOS | SHF_MASKPROC))
4b3b7c0
+      if (old_sec == NULL && ((attr & ~(SHF_LINK_ORDER
4b3b7c0
+					| SHF_MASKOS
4b3b7c0
+					| SHF_MASKPROC))
4b3b7c0
 			      & ~ssect->attr) != 0)
4b3b7c0
 	{
4b3b7c0
 	  /* As a GNU extension, we permit a .note section to be
4b3b7c0
diff -rup binutils.orig/ld/ldlang.c binutils-2.35.1/ld/ldlang.c
4b3b7c0
--- binutils.orig/ld/ldlang.c	2021-01-04 13:18:09.691372002 +0000
4b3b7c0
+++ binutils-2.35.1/ld/ldlang.c	2021-01-04 13:18:20.600301261 +0000
4b3b7c0
@@ -7421,7 +7421,7 @@ lang_reset_memory_regions (void)
4b3b7c0
 
4b3b7c0
 static void
4b3b7c0
 gc_section_callback (lang_wild_statement_type *ptr,
4b3b7c0
-		     struct wildcard_list *sec ATTRIBUTE_UNUSED,
4b3b7c0
+		     struct wildcard_list *sec,
4b3b7c0
 		     asection *section,
4b3b7c0
 		     struct flag_info *sflag_info ATTRIBUTE_UNUSED,
4b3b7c0
 		     lang_input_statement_type *file ATTRIBUTE_UNUSED,
4b3b7c0
@@ -7431,6 +7431,8 @@ gc_section_callback (lang_wild_statement
4b3b7c0
      should be as well.  */
4b3b7c0
   if (ptr->keep_sections)
4b3b7c0
     section->flags |= SEC_KEEP;
4b3b7c0
+  if (sec)
4b3b7c0
+    section->pattern = sec->spec.name;
4b3b7c0
 }
4b3b7c0
 
4b3b7c0
 /* Iterate over sections marking them against GC.  */