public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* RFC: ld: Add --text-section-ordering-file (version 2)
@ 2024-04-25 13:01 Nick Clifton
  2024-04-25 15:32 ` H.J. Lu
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Nick Clifton @ 2024-04-25 13:01 UTC (permalink / raw)
  To: hjl.tools, binutils; +Cc: siddhesh

[-- Attachment #1: Type: text/plain, Size: 2922 bytes --]

Hi Guys,

  Attached is a patch to add a --section-ordering-file option to the BFD
  linker.  It is based upon H.J.'s original patch, but extended so that
  it will work with multiple output sections.

  There are a couple of points that I feel I should highlight:

  * The option only works in conjunction with a modified linker script.
  
    In particular the script must have: "INCLUDE section-ordering-file"
    statements in it, wherever it wants section ordering to be allowed.
    This statement can appear multiple times in a linker script,
    although it would not make sense to have it appear more than once in
    any given output section.  Here is an example:
    
      SECTIONS
      {
        .text : {
          INCLUDE section-ordering-file
          *(.text)
        }
        .data : {
          INCLUDE section-ordering-file
          *(.data)
        }
      }
    
  * H.J's original version allowed for linker script like
    "filename(section)" syntax to be used to name sections, eg:
    "*(.text.*)", as well as a simpler "section name regexp", eg
    ".text.*", to be used.  This version only supports the latter
    format.

    In addition H.J.'s syntax allowed for abbreviated section names to
    match.  So ".t*t" would match any section starting with ".t" and
    ending with "t" and would put it into the .text section.  In this
    version however the output section is selected based upon matching
    the fixed part at the start of the pattern with the output section.
    So ".t*t" would only work if the output section was called ".t".

    To help compensate for this, and to allow arbitrary input sections
    to be mapped to specific output sections, the output section name
    can be provided as if it were a filename.  So .foo(.bar) would map
    all sections called .bar to the output section .foo, but only if the
    linker script has an output section called .foo, and only if that
    output section declaration includes a INCLUDE section-ordering-file
    statement.
    
    Perhaps an example will make things clearer.  If the above linker
    script is used and the section ordering file contains:

      # A comment - this will be ignored.
      .text.hot .text.cold .text.warm
      .data.big
      .data(.bar)
      .text.foo*
      .ignore(.me)

    This is roughly equivalent to a linker script that looks like this:

      SECTIONS
      {
        .text : {
          *(.text.hot)
          *(.text.cold)
          *(.text.warm)
          *(.text.foo*)
          *(.text)
        }
        .data : {
          *(.data.big)
          *(.bar)
          *(.data)
        }
      }

    Note - the linker will not warn about entries in the section
    ordering file that do not match an output section name.  So in the
    above example the ".ignore(.me)" entry will not generate a warning
    about it not being used.

  Thoughts, comments, etc ?

Cheers
  Nick


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: section-ordering-file.patch --]
[-- Type: text/x-patch, Size: 47828 bytes --]

diff --git a/ld/NEWS b/ld/NEWS
index f70d2157339..458f6562ca0 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -2,6 +2,9 @@
 
 * Add -plugin-save-temps to store plugin intermediate files permanently.
 
+* Add the linker option, --section-ordering-file=FILE, for ELF and
+  PE COFF linker to specify the input section order.
+
 Changes in 2.42:
 
 * Add -z mark-plt/-z nomark-plt options to x86-64 ELF linker to mark PLT
diff --git a/ld/ld.h b/ld/ld.h
index fcdd9a2c083..81e9ee03387 100644
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -319,8 +319,20 @@ typedef struct
 
   /* Compress DWARF debug sections.  */
   enum compressed_debug_section_type compress_debug;
+
+  /* The optional section ordering file.  */
+  const char *section_ordering_file;
+
 } ld_config_type;
 
+/* Any "INPUT <filename>" directive inside a linekr script that uses
+   SECTION_ORDERING_FILE as its filename is actually a indicator that
+   the config.section_ordering_file parameter should be processed and
+   inserted.  */
+#define SECTION_ORDERING_FILE_1 "section-ordering-file"
+/* Also accept the name with underscores instead of dashes.  */
+#define SECTION_ORDERING_FILE_2 "section_ordering_file"
+
 extern ld_config_type config;
 
 extern FILE * saved_script_handle;
diff --git a/ld/ld.texi b/ld/ld.texi
index ca9574dfc71..a6f04c8a457 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -2552,6 +2552,105 @@ patterns in the linker script.
 This option will apply @code{SORT_BY_ALIGNMENT} to all wildcard section
 patterns in the linker script.
 
+@kindex --section-ordering-file=@file{file}
+@item --section-ordering-file=@file{file}
+This option gives the linker a file which tells it how to order
+specific input sections when placing them in an output section.
+
+The input file consists of one or more entries separated by white
+space and/or line separators.  Blank lines and line whose
+first non-whitespace character is a hash (@samp{#}), are ignored.
+
+Each entry in the section ordering file is either a section name, a
+section name regular expression, or an output section name followed by
+a list of section name patterns enclosed in parentheses.
+
+A section name attempts to map any input section matching that name to
+the output section that starts with the same prefix as the input
+section.  So for example @samp{.text.hot} maps all input sections
+called @samp{.text.hot} to the output section @samp{.text}.  Note -
+this mapping will only work if the linker script being used has
+specified that the particular output section allows section ordering
+input.  See below for more details.
+
+A section name regular expression entry matches multiple input
+sections to the output section whose name starts of the fixed part of
+the expression.
+
+A section name followed by a list of section name expressions enclosed
+inside parentheses maps the section name expressions to the output
+section named first.  So for example @samp{.data(.foo)} maps all
+incoming @samp{.foo} sections to the @samp{.data} output section.
+Note - if there are multiple section names or section name patterns
+inside the parenthesised list, the order of those sections relative to
+each other is not guaranteed.
+
+Most importantly however the order in which entries occur in the
+section ordering file will be preserved, within the output section to
+which they are mapped.
+
+Here is an example:
+
+@smallexample
+  # A comment
+  .text.hot .text.cold .text.warm
+  .data.big
+  .data(.bar)
+  .text.foo*
+@end smallexample
+
+This is roughly equivalent to a linker script that looks like this:
+
+@smallexample
+  SECTIONS
+  @{
+    .text : @{
+      *(.text.hot)
+      *(.text.cold)
+      *(.text.warm)
+      *(.text.foo*)
+      *(.text)
+      @}
+    .data : @{
+      *(.data.big)
+      *(.bar)
+      *(.data)
+      @}
+  @}
+@end smallexample
+
+Note - the syntax used in the section ordering file is similar to, but
+different from the syntax used in linker scripts.
+
+Note - this option works in conjunction with the linker script being
+used by the linker.  In particular the linker script must use special
+directives to indicate where the section order file's mappings should
+be placed.  So the above example would only work if the linker script
+looked something like this:
+
+@smallexample
+  SECTIONS
+  @{
+    .text : @{
+       INCLUDE section-ordering-file
+       *(.text)
+       @}
+    .data : @{
+       INCLUDE section-ordering-file
+       *(.data)
+       @}
+   @}
+@end smallexample
+
+Note - the @samp{--section-ordering-file} option controls the order of
+input sections being mapped into an output section.  It does not
+control the order of output sections in relation to each other.
+
+If the @option{verbose} option is enabled, the contents of the section
+ordering file will be reported.
+
+This option is supported only in ELF and PE COFF linkers.
+
 @kindex --spare-dynamic-tags
 @item --spare-dynamic-tags=@var{count}
 This option specifies the number of empty slots to leave in the
@@ -4188,6 +4287,13 @@ with the @option{-L} option.  You can nest calls to @code{INCLUDE} up to
 You can place @code{INCLUDE} directives at the top level, in @code{MEMORY} or
 @code{SECTIONS} commands, or in output section descriptions.
 
+Note - there is a special case for @code{INCLUDE} directives found
+inside the @code{SECTION} command.  If the @var{filename} is
+@var{section_ordering_file} or @var{section-ordering-file} then this
+indicates that the contents of the file specified by the
+@option{--section-ordering-file} option should be used at that
+particular point in the script.
+
 @item INPUT(@var{file}, @var{file}, @dots{})
 @itemx INPUT(@var{file} @var{file} @dots{})
 @kindex INPUT(@var{files})
diff --git a/ld/ldfile.c b/ld/ldfile.c
index dc9875d8813..991affbc44d 100644
--- a/ld/ldfile.c
+++ b/ld/ldfile.c
@@ -736,7 +736,7 @@ ldfile_open_file (lang_input_statement_type *entry)
 /* Try to open NAME.  */
 
 static FILE *
-try_open (const char *name, bool *sysrooted)
+try_open (const char *name, const char *orig_name, bool *sysrooted)
 {
   FILE *result;
 
@@ -750,10 +750,44 @@ try_open (const char *name, bool *sysrooted)
 
   if (verbose)
     {
-      if (result == NULL)
-	info_msg (_("cannot find script file %s\n"), name);
+      if (config.section_ordering_file != NULL
+	  && strcmp (orig_name, config.section_ordering_file) == 0)
+	{
+	  static bool displayed_ordering_file = false;
+
+	  if (displayed_ordering_file)
+	    ;
+	  else if (result == NULL)
+	    info_msg (_("cannot find section ordering file: %s\n"),
+		      name);
+	  else
+	    {
+	      static const int ld_bufsz = 8193;
+	      size_t n;
+	      char *buf = (char *) xmalloc (ld_bufsz);
+
+	      info_msg (_("opened section ordering file: %s\n"), name);
+	      info_msg ("==================================================\n");
+
+	      while ((n = fread (buf, 1, ld_bufsz - 1, result)) > 0)
+		{
+		  buf[n] = 0;
+		  info_msg ("%s", buf);
+		}
+	      rewind (result);
+	      free (buf);
+
+	      info_msg ("==================================================\n\n");
+	      displayed_ordering_file = true;
+	    }
+	}
       else
-	info_msg (_("opened script file %s\n"), name);
+	{
+	  if (result == NULL)
+	    info_msg (_("cannot find script file %s\n"), name);
+	  else
+	    info_msg (_("opened script file %s\n"), name);
+	}
     }
 
   return result;
@@ -832,7 +866,7 @@ ldfile_find_command_file (const char *name,
   if (!default_only)
     {
       /* First try raw name.  */
-      result = try_open (name, sysrooted);
+      result = try_open (name, name, sysrooted);
       if (result != NULL)
 	return result;
     }
@@ -859,7 +893,7 @@ ldfile_find_command_file (const char *name,
        search = search->next)
     {
       path = concat (search->name, slash, name, (const char *) NULL);
-      result = try_open (path, sysrooted);
+      result = try_open (path, name, sysrooted);
       free (path);
       if (result)
 	break;
@@ -871,7 +905,8 @@ ldfile_find_command_file (const char *name,
   return result;
 }
 
-enum script_open_style {
+enum script_open_style
+{
   script_nonT,
   script_T,
   script_defaultT
@@ -908,6 +943,40 @@ ldfile_open_command_file_1 (const char *name, enum script_open_style open_how)
 	}
     }
 
+  /* Don't allow nested INCLUDEs in the section ordering file.  */
+  if (in_section_ordering_file)
+    {
+      einfo (_("%F%P: error: 'INCLUDE %s' found in the section "
+	       "ordering file: '%s'\n"), name, config.section_ordering_file);
+      return;
+    }
+
+  if (strcmp (name, SECTION_ORDERING_FILE_1) == 0
+      || strcmp (name, SECTION_ORDERING_FILE_2) == 0)    
+    {
+      /* Support
+
+	 INCLUDE section_ordering_file;
+
+	 in input sections in linker script.  */
+      if (config.section_ordering_file == NULL)
+	{
+	  /* Skip if the section ordering file isn't specified.  */
+	  lex_push_file (NULL, name, false);
+	  return;
+	}
+
+      /* FIXME: Check that we are inside the SECTIONS part of the script.  */
+
+      /* Load the section ordering file.  */
+      name = config.section_ordering_file;
+
+      /* Set the in the section ordering file marker.  */
+      in_section_ordering_file = true;
+    }
+  else
+    in_section_ordering_file = false;
+
   /* FIXME: This memory is never freed, but that should not really matter.
      It will be released when the linker exits, and it is unlikely to ever
      be more than a few tens of bytes.  */
@@ -932,7 +1001,12 @@ ldfile_open_command_file_1 (const char *name, enum script_open_style open_how)
 
   lineno = 1;
 
-  saved_script_handle = ldlex_input_stack;
+  /* Clear the end of the include file marker.  */
+  seen_eof_include_file = false;
+
+  /* The section ordering file isn't a real linker script file.  */
+  if (!in_section_ordering_file)
+    saved_script_handle = ldlex_input_stack;
 }
 
 /* Open command file NAME in the current directory, -L directories,
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 54d1af62ebe..61d2f5153ab 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -689,7 +689,9 @@ wild_sort (lang_wild_statement_type *wild,
 	 looking at the sections for this file.  */
 
       /* Find the correct node to append this section.  */
-      if (sec && sec->spec.sorted != none && sec->spec.sorted != by_none
+      if (sec
+	  && sec->spec.sorted != none
+	  && sec->spec.sorted != by_none
 	  && compare_section (sec->spec.sorted, section, (*tree)->section, sec->spec.reversed) < 0)
 	tree = &((*tree)->left);
       else
@@ -957,7 +959,7 @@ resolve_wild_sections (lang_input_statement_type *file)
       const char *sname = bfd_section_name (s);
       char c = 1;
       struct prefixtree *t = ptroot;
-      //printf (" YYY consider %s of %s\n", sname, file->the_bfd->filename);
+
       do
 	{
 	  if (t->stmt)
@@ -966,7 +968,6 @@ resolve_wild_sections (lang_input_statement_type *file)
 	      for (sl = t->stmt; sl; sl = sl->next)
 		{
 		  walk_wild_section_match (sl->stmt, file, s);
-		  //printf ("   ZZZ maybe place into %p\n", sl->stmt);
 		}
 	    }
 	  if (!c)
@@ -985,7 +986,6 @@ resolve_wilds (void)
 {
   LANG_FOR_EACH_INPUT_STATEMENT (f)
     {
-      //printf("XXX   %s\n", f->filename);
       if (f->the_bfd == NULL
 	  || !bfd_check_format (f->the_bfd, bfd_archive))
 	resolve_wild_sections (f);
@@ -8515,12 +8515,101 @@ lang_add_wild (struct wildcard_spec *filespec,
 
   if (filespec != NULL && filespec->name != NULL)
     {
-      if (strcmp (filespec->name, "*") == 0)
-	filespec->name = NULL;
-      else if (!wildcardp (filespec->name))
-	lang_has_input_file = true;
+      if (in_section_ordering_file)
+	{
+	  if (filespec->sorted != none
+	      || filespec->exclude_name_list != NULL
+	      || filespec->section_flag_list != NULL
+	      || filespec->reversed)
+	    {
+	      einfo (_("%F%P: error: \
+sorting, excluding, reversing and flag selection is not supported in section ordering file entries\n"));
+	    }
+	  else if (current_section == NULL)
+	    {
+	      einfo (_("%F%P: error: \
+using a section ordering file outside of an output section definition is not supported\n"));
+	    }
+	  else if (section_list != NULL)
+	    {
+	      /* We need a way to include input sections whose names do not
+		 start with the output section's name.  We do this by accepting
+		 entries of the form "<output-section-name> ( <input-section-regexp> )"
+		 The <output-section-name> should not be a regexp.  */
+	      if (strcmp (filespec->name, current_section->name) == 0)
+		{
+		  /* Convert .text(.bar) into *(.bar).  */
+		  filespec->name = NULL;
+		  goto cont;
+		}
+
+	      /* FIXME: We have no way of detecting if an entry in the section
+		 ordering file does not match any output section.  */
+	    }
+	  else if (strncmp (filespec->name, current_section->name,
+			    strlen (current_section->name)))
+	    {
+	      /* Exclude this entry from this section.
+		 Since we have a single section ordering file, but we want it
+		 to be able to provide the ordering for multiple output
+		 sections, we match entries to output sections.  So for
+		 example if the ordering file contains:
+		   .text.foo
+		   .data.bar
+		   .text.b*
+		   .data.z*
+		 Then we add the .text.foo and .text.b* patterns to the .text
+		 output section (in that order) and the .data.bar and .data.z*
+		 patterns to the .data output section.
+
+		 This behaviour relies upon the linker script containing
+		 "INCLUDE section-ordering-file" directives in all of the
+		 output sections that it wants to be able to be affected by
+		 the --section-ordering-file option.  */
+	      ;
+
+	      /* FIXME: We have no way of detecting if an entry in the section
+		 ordering file does not match any output section.  */
+	    }
+	  else
+	    {
+	      /* A section ordering file entry looks like a filename
+		 without a section list.  Convert the filename into
+		 a section name and create a wild card as the file
+		 name.  */
+	      struct wildcard_list *single_section = XCNEW (struct wildcard_list);
+
+	      single_section->spec.name = filespec->name;
+	      single_section->spec.sorted = none;
+	      /* A NULL indicates the wild card file name, "*".  */
+	      filespec->name = NULL;
+	      section_list = single_section;
+
+	      /* Carry on processing the statement.  */
+	      goto cont;
+	    }
+	  
+	  if (seen_eof_include_file)
+	    in_section_ordering_file = false;
+
+	  return;
+	}
+      else
+	{
+	  if (strcmp (filespec->name, "*") == 0)
+	    filespec->name = NULL;
+	  else if (!wildcardp (filespec->name))
+	    lang_has_input_file = true;
+	}
     }
 
+ cont:
+  /* NB: Clear the in the section ordering file marker after
+     processing the last entry when the end of the section
+     ordering file is reached.  */
+  if (in_section_ordering_file && seen_eof_include_file)
+    in_section_ordering_file = false;
+
   new_stmt = new_stat (lang_wild_statement, stat_ptr);
   new_stmt->filename = NULL;
   new_stmt->filenames_sorted = false;
diff --git a/ld/ldlex.h b/ld/ldlex.h
index d575562a357..39454cc764c 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -68,6 +68,7 @@ enum option_values
   OPTION_TASK_LINK,
   OPTION_TBSS,
   OPTION_TDATA,
+  OPTION_SECTION_ORDERING_FILE,
   OPTION_TTEXT,
   OPTION_TTEXT_SEGMENT,
   OPTION_TRODATA_SEGMENT,
@@ -485,6 +486,8 @@ extern input_type parser_input;
 
 extern unsigned int lineno;
 extern const char *lex_string;
+extern bool in_section_ordering_file;
+extern bool seen_eof_include_file;
 
 /* In ldlex.l.  */
 extern int yylex (void);
diff --git a/ld/ldlex.l b/ld/ldlex.l
index e113c90812b..113e4126d0b 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -43,6 +43,12 @@ input_type parser_input;
 /* Line number in the current input file.  */
 unsigned int lineno;
 
+/* True if the current input file is the section ordering file.  */
+bool in_section_ordering_file = false;
+
+/* True if the end of the include file is reached.  */
+bool seen_eof_include_file = false;
+
 /* The string we are currently lexing, or NULL if we are reading a
    file.  */
 const char *lex_string = NULL;
@@ -487,6 +493,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 
   lineno = lineno_stack[include_stack_ptr];
   input_flags.sysrooted = sysrooted_stack[include_stack_ptr];
+  seen_eof_include_file = true;
 
   return END;
 }
diff --git a/ld/lexsup.c b/ld/lexsup.c
index dad3b6059ed..15a20fe86ac 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -487,6 +487,9 @@ static const struct ld_option ld_options[] =
   { {"sort-section", required_argument, NULL, OPTION_SORT_SECTION},
     '\0', N_("name|alignment"),
     N_("Sort sections by name or maximum alignment"), TWO_DASHES },
+  { {"section-ordering-file", required_argument, NULL, OPTION_SECTION_ORDERING_FILE},
+    '\0', N_("FILE"),
+    N_("Sort sections by statements in FILE"), TWO_DASHES },
   { {"spare-dynamic-tags", required_argument, NULL, OPTION_SPARE_DYNAMIC_TAGS},
     '\0', N_("COUNT"), N_("How many tags to reserve in .dynamic section"),
     TWO_DASHES },
@@ -673,6 +676,7 @@ parse_args (unsigned argc, char **argv)
     dynamic_list
   } opt_dynamic_list = dynamic_list_unset;
   struct bfd_elf_dynamic_list *export_list = NULL;
+  bool seen_linker_script = false;
 
   shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
   longopts = (struct option *)
@@ -1400,6 +1404,12 @@ parse_args (unsigned argc, char **argv)
 	    einfo (_("%F%P: invalid section sorting option: %s\n"),
 		   optarg);
 	  break;
+	case OPTION_SECTION_ORDERING_FILE:
+	  if (seen_linker_script)
+	    einfo (_("%F%P: --section-ordering-file must be placed"
+		     " before -T/--script\n"));
+	  config.section_ordering_file = optarg;
+	  break;
 	case OPTION_STATS:
 	  config.stats = true;
 	  break;
@@ -1416,6 +1426,7 @@ parse_args (unsigned argc, char **argv)
 	  ++trace_files;
 	  break;
 	case 'T':
+	  seen_linker_script = true;
 	  previous_script_handle = saved_script_handle;
 	  ldfile_open_script_file (optarg);
 	  parser_input = input_script;
diff --git a/ld/scripttempl/arclinux.sc b/ld/scripttempl/arclinux.sc
index 36ba5a664d3..eabbb90c3d5 100644
--- a/ld/scripttempl/arclinux.sc
+++ b/ld/scripttempl/arclinux.sc
@@ -487,11 +487,12 @@ cat <<EOF
   .text         ${RELOCATING-0} :
   {
     ${RELOCATING+${TEXT_START_SYMBOLS}}
-    ${RELOCATING+*(.text.unlikely .text.*_unlikely .text.unlikely.*)}
-    ${RELOCATING+*(.text.exit .text.exit.*)}
+    ${RELOCATING+INCLUDE section_ordering_file}
     ${RELOCATING+*(.text.startup .text.startup.*)}
     ${RELOCATING+*(.text.hot .text.hot.*)}
     ${RELOCATING+*(SORT(.text.sorted.*))}
+    ${RELOCATING+*(.text.unlikely .text.*_unlikely .text.unlikely.*)}
+    ${RELOCATING+*(.text.exit .text.exit.*)}
     *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*})
     /* .gnu.warning sections are handled specially by elf.em.  */
     *(.gnu.warning)
@@ -598,6 +599,7 @@ cat <<EOF
   .data         ${RELOCATING-0} :
   {
     ${RELOCATING+${DATA_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*})
     ${CONSTRUCTING+SORT(CONSTRUCTORS)}
   }
diff --git a/ld/scripttempl/avr.sc b/ld/scripttempl/avr.sc
index 329d57e2849..bbfee834fc3 100644
--- a/ld/scripttempl/avr.sc
+++ b/ld/scripttempl/avr.sc
@@ -244,6 +244,7 @@ SECTIONS
     KEEP (*(.init8))
     *(.init9)  /* Call main().  */
     KEEP (*(.init9))}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+. = ALIGN(2);
     *(.text.*)
@@ -305,6 +306,7 @@ cat <<EOF
   .data        ${RELOCATING-0} :
   {
     ${RELOCATING+ PROVIDE (__data_start = .) ; }
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+ *(.data*)
     *(.gnu.linkonce.d*)}
diff --git a/ld/scripttempl/dlx.sc b/ld/scripttempl/dlx.sc
index 8dcbf300c56..d606535224c 100644
--- a/ld/scripttempl/dlx.sc
+++ b/ld/scripttempl/dlx.sc
@@ -22,12 +22,14 @@ SECTIONS
   .text :
   {
     ${RELOCATING+CREATE_OBJECT_SYMBOLS}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+etext = ${DATA_ALIGNMENT};}
   }
   ${RELOCATING+. = ${DATA_ALIGNMENT};}
   .data :
   {
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${CONSTRUCTING+CONSTRUCTORS}
     ${RELOCATING+edata  =  .;}
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
index d5022fa502f..64b1d8b3305 100644
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -553,11 +553,12 @@ cat <<EOF
   .text         ${RELOCATING-0} :
   {
     ${RELOCATING+${TEXT_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section-ordering-file}
+    ${RELOCATING+*(.text.hot .text.hot.*)}
+    ${RELOCATING+*(SORT(.text.sorted.*))}
     ${RELOCATING+*(.text.unlikely .text.*_unlikely .text.unlikely.*)}
     ${RELOCATING+*(.text.exit .text.exit.*)}
     ${RELOCATING+*(.text.startup .text.startup.*)}
-    ${RELOCATING+*(.text.hot .text.hot.*)}
-    ${RELOCATING+*(SORT(.text.sorted.*))}
     *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*})
     /* .gnu.warning sections are handled specially by elf.em.  */
     *(.gnu.warning)
@@ -672,6 +673,7 @@ cat <<EOF
   .data         ${RELOCATING-0}${RELOCATING+${DATA_SECTION_ALIGNMENT}} :
   {
     ${RELOCATING+${DATA_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section-ordering-file}
     *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*})
     ${CONSTRUCTING+SORT(CONSTRUCTORS)}
   }
diff --git a/ld/scripttempl/elf32cr16.sc b/ld/scripttempl/elf32cr16.sc
index 3e7d92a4f34..19ebde72510 100644
--- a/ld/scripttempl/elf32cr16.sc
+++ b/ld/scripttempl/elf32cr16.sc
@@ -81,6 +81,7 @@ SECTIONS
   .text :
   {
     __TEXT_START = .;
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text) *(.text.*) *(.gnu.linkonce.t.*)
     __TEXT_END = .;
   }${RELOCATING+ > rom}
@@ -131,6 +132,7 @@ SECTIONS
   .data :
   {
     __DATA_START = .;
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data_4) *(.data_2) *(.data_1) *(.data) *(.data.*) *(.gnu.linkonce.d.*)
     __DATA_END = .;
   }${RELOCATING+ > ram AT > rom}
diff --git a/ld/scripttempl/elf32crx.sc b/ld/scripttempl/elf32crx.sc
index 1b1316676a7..a1a8186a371 100644
--- a/ld/scripttempl/elf32crx.sc
+++ b/ld/scripttempl/elf32crx.sc
@@ -77,6 +77,7 @@ SECTIONS
   .text :
   {
     __TEXT_START = .;
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text) *(.text.*) *(.gnu.linkonce.t.*)
     __TEXT_END = .;
   } > rom
@@ -129,6 +130,7 @@ SECTIONS
   .data :
   {
     __DATA_START = .;
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data_4) *(.data_2) *(.data_1) *(.data) *(.data.*) *(.gnu.linkonce.d.*)
     __DATA_END = .;
   } > ram AT > rom
diff --git a/ld/scripttempl/elf32msp430.sc b/ld/scripttempl/elf32msp430.sc
index bed0d673238..2c638f15b00 100644
--- a/ld/scripttempl/elf32msp430.sc
+++ b/ld/scripttempl/elf32msp430.sc
@@ -163,6 +163,7 @@ SECTIONS
     *(.lower.text.* .lower.text)
 
     . = ALIGN(2);}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+. = ALIGN(2);
     *(.text.*)
@@ -260,6 +261,7 @@ SECTIONS
     PROVIDE (__data_start = .) ;
     PROVIDE (__datastart = .) ;
 
+    ${RELOCATING+INCLUDE section_ordering_file}
     KEEP (*(.jcr))
     *(.data.rel.ro.local) *(.data.rel.ro*)
     *(.dynamic)
diff --git a/ld/scripttempl/elf64bpf.sc b/ld/scripttempl/elf64bpf.sc
index ca62d7c88e0..0ea9b4a9064 100644
--- a/ld/scripttempl/elf64bpf.sc
+++ b/ld/scripttempl/elf64bpf.sc
@@ -508,11 +508,12 @@ cat <<EOF
   .text         ${RELOCATING-0} :
   {
     ${RELOCATING+${TEXT_START_SYMBOLS}}
-    ${RELOCATING+*(.text.unlikely .text.*_unlikely .text.unlikely.*)}
-    ${RELOCATING+*(.text.exit .text.exit.*)}
+    ${RELOCATING+INCLUDE section_ordering_file}
     ${RELOCATING+*(.text.startup .text.startup.*)}
     ${RELOCATING+*(.text.hot .text.hot.*)}
     ${RELOCATING+*(SORT(.text.sorted.*))}
+    ${RELOCATING+*(.text.unlikely .text.*_unlikely .text.unlikely.*)}
+    ${RELOCATING+*(.text.exit .text.exit.*)}
     *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*})
     /* .gnu.warning sections are handled specially by elf.em.  */
     *(.gnu.warning)
@@ -621,6 +622,7 @@ cat <<EOF
   .data         ${RELOCATING-0} :
   {
     ${RELOCATING+${DATA_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*})
     ${CONSTRUCTING+SORT(CONSTRUCTORS)}
   }
diff --git a/ld/scripttempl/elf64hppa.sc b/ld/scripttempl/elf64hppa.sc
index 6bde304dd27..991219b8bd2 100644
--- a/ld/scripttempl/elf64hppa.sc
+++ b/ld/scripttempl/elf64hppa.sc
@@ -412,6 +412,7 @@ cat <<EOF
   .text         ${RELOCATING-0} :
   {
     ${RELOCATING+${TEXT_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*})
     /* .gnu.warning sections are handled specially by elf.em.  */
     *(.gnu.warning)
@@ -475,6 +476,7 @@ cat <<EOF
   .data         ${RELOCATING-0} :
   {
     ${RELOCATING+${DATA_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*})
     ${CONSTRUCTING+SORT(CONSTRUCTORS)}
   }
diff --git a/ld/scripttempl/elfarc.sc b/ld/scripttempl/elfarc.sc
index 1ae0248a900..bf98c4464a1 100644
--- a/ld/scripttempl/elfarc.sc
+++ b/ld/scripttempl/elfarc.sc
@@ -288,6 +288,7 @@ cat <<EOF
   .text         ${RELOCATING-0} :
   {
     ${RELOCATING+${TEXT_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*})
     /* .gnu.warning sections are handled specially by elf.em.  */
     *(.gnu.warning)
@@ -337,6 +338,7 @@ cat <<EOF
   .data         ${RELOCATING-0} :
   {
     ${RELOCATING+${DATA_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*})
     ${CONSTRUCTING+SORT(CONSTRUCTORS)}
   }
diff --git a/ld/scripttempl/elfarcv2.sc b/ld/scripttempl/elfarcv2.sc
index 3054e4c62f3..05c04662b32 100644
--- a/ld/scripttempl/elfarcv2.sc
+++ b/ld/scripttempl/elfarcv2.sc
@@ -192,6 +192,7 @@ SECTIONS
 
     /* Remaining code.  */
     ${RELOCATING+ . = ALIGN(4);}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*})
     /* .gnu.warning sections are handled specially by elf.em.  */
     *(.gnu.warning)
@@ -253,6 +254,7 @@ SECTIONS
   .data	${RELOCATING-0} :
   {
     ${RELOCATING+ PROVIDE (__data_start = .) ; }
+    ${RELOCATING+INCLUDE section_ordering_file}
     /* --gc-sections will delete empty .data. This leads to wrong start
        addresses for subsequent sections because -Tdata= from the command
        line will have no effect, see PR13697.  Thus, keep .data  */
diff --git a/ld/scripttempl/elfd10v.sc b/ld/scripttempl/elfd10v.sc
index 1ecf4a19092..2c4ed68bf63 100644
--- a/ld/scripttempl/elfd10v.sc
+++ b/ld/scripttempl/elfd10v.sc
@@ -109,6 +109,7 @@ SECTIONS
     KEEP (*(SORT_NONE(.init.*)))
     KEEP (*(SORT_NONE(.fini)))
     KEEP (*(SORT_NONE(.fini.*)))}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.text.*)}
     /* .gnu.warning sections are handled specially by elf.em.  */
@@ -132,6 +133,7 @@ SECTIONS
   .data  ${RELOCATING-0} :
   {
     ${RELOCATING+${DATA_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+*(.data.*)
     *(.gnu.linkonce.d*)}
diff --git a/ld/scripttempl/elfd30v.sc b/ld/scripttempl/elfd30v.sc
index ed0c412edc8..2cfb937515e 100644
--- a/ld/scripttempl/elfd30v.sc
+++ b/ld/scripttempl/elfd30v.sc
@@ -125,6 +125,7 @@ SECTIONS
   /* Internal text space or external memory */
   .text :
   {
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.gnu.linkonce.t*)
     KEEP (*(SORT_NONE(.fini)))
@@ -150,6 +151,7 @@ SECTIONS
 
   .data		${RELOCATING-0} :
   {
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+*(.gnu.linkonce.d*)}
     ${CONSTRUCTING+CONSTRUCTORS}
diff --git a/ld/scripttempl/elfm68hc11.sc b/ld/scripttempl/elfm68hc11.sc
index b122da0e32a..73634062e96 100644
--- a/ld/scripttempl/elfm68hc11.sc
+++ b/ld/scripttempl/elfm68hc11.sc
@@ -318,6 +318,7 @@ SECTIONS
     /* Put startup code at beginning so that _start keeps same address.  */
     ${RELOCATING+${STARTUP_CODE}}
 
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.text.*)}
     /* .gnu.warning sections are handled specially by elf.em.  */
@@ -378,6 +379,7 @@ SECTIONS
     ${RELOCATING+__data_section_start = .;}
     ${RELOCATING+PROVIDE (__data_section_start = .);}
 
+    ${RELOCATING+INCLUDE section_ordering_file}
     ${RELOCATING+${DATA_START_SYMBOLS}}
     ${RELOCATING+*(.sdata)}
     *(.data)
diff --git a/ld/scripttempl/elfm68hc12.sc b/ld/scripttempl/elfm68hc12.sc
index 47410a95f46..78c9db5ceb8 100644
--- a/ld/scripttempl/elfm68hc12.sc
+++ b/ld/scripttempl/elfm68hc12.sc
@@ -317,6 +317,7 @@ SECTIONS
     /* Put startup code at beginning so that _start keeps same address.  */
     ${RELOCATING+${STARTUP_CODE}}
 
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.text.*)}
     /* .gnu.warning sections are handled specially by elf.em.  */
@@ -379,6 +380,7 @@ SECTIONS
     ${RELOCATING+__data_section_start = .;}
     ${RELOCATING+PROVIDE (__data_section_start = .);}
 
+    ${RELOCATING+INCLUDE section_ordering_file}
     ${RELOCATING+${DATA_START_SYMBOLS}}
     ${RELOCATING+*(.sdata)}
     *(.data)
diff --git a/ld/scripttempl/elfm9s12z.sc b/ld/scripttempl/elfm9s12z.sc
index 271d218835b..861096cbba1 100644
--- a/ld/scripttempl/elfm9s12z.sc
+++ b/ld/scripttempl/elfm9s12z.sc
@@ -303,6 +303,7 @@ SECTIONS
     /* Put startup code at beginning so that _start keeps same address.  */
     ${RELOCATING+${STARTUP_CODE}}
 
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.text.*)}
     /* .gnu.warning sections are handled specially by elf.em.  */
@@ -368,6 +369,7 @@ SECTIONS
     ${RELOCATING+__data_section_start = .;}
     ${RELOCATING+PROVIDE (__data_section_start = .);}
 
+    ${RELOCATING+INCLUDE section_ordering_file}
     ${RELOCATING+${DATA_START_SYMBOLS}}
     ${RELOCATING+*(.sdata)}
     *(.data)
diff --git a/ld/scripttempl/elfmicroblaze.sc b/ld/scripttempl/elfmicroblaze.sc
index 88abe4f10ba..13649908e24 100644
--- a/ld/scripttempl/elfmicroblaze.sc
+++ b/ld/scripttempl/elfmicroblaze.sc
@@ -79,6 +79,7 @@ SECTIONS
 
   ${RELOCATING+ _ftext  =  .;}
   .text : {
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.text.*)}
     ${RELOCATING+*(.gnu.linkonce.t.*)}
@@ -135,6 +136,7 @@ SECTIONS
   ${RELOCATING+ . = ALIGN(4);}
   ${RELOCATING+ _fdata = .;}
   .data : {
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+*(.data.*)}
     ${RELOCATING+*(.gnu.linkonce.d.*)}
diff --git a/ld/scripttempl/elfxgate.sc b/ld/scripttempl/elfxgate.sc
index 4c25bc161f2..9f94220ad48 100644
--- a/ld/scripttempl/elfxgate.sc
+++ b/ld/scripttempl/elfxgate.sc
@@ -317,6 +317,7 @@ SECTIONS
     /* Put startup code at beginning so that _start keeps same address.  */
     ${RELOCATING+${STARTUP_CODE}}
 
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.text.*)}
     /* .gnu.warning sections are handled specially by elf.em.  */
@@ -379,6 +380,7 @@ SECTIONS
     ${RELOCATING+__data_section_start = .;}
     ${RELOCATING+PROVIDE (__data_section_start = .);}
 
+    ${RELOCATING+INCLUDE section_ordering_file}
     ${RELOCATING+${DATA_START_SYMBOLS}}
     ${RELOCATING+*(.sdata)}
     *(.data)
diff --git a/ld/scripttempl/elfxtensa.sc b/ld/scripttempl/elfxtensa.sc
index 231f53b5f5b..5b3d7793cdc 100644
--- a/ld/scripttempl/elfxtensa.sc
+++ b/ld/scripttempl/elfxtensa.sc
@@ -418,6 +418,7 @@ cat <<EOF
     ${RELOCATING+${INIT_END}}
 
     ${RELOCATING+${TEXT_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.literal .text .stub${RELOCATING+ .literal.* .text.* .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*})
     /* .gnu.warning sections are handled specially by elf.em.  */
     *(.gnu.warning)
@@ -485,6 +486,7 @@ cat <<EOF
   .data         ${RELOCATING-0} :
   {
     ${RELOCATING+${DATA_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*})
     ${CONSTRUCTING+SORT(CONSTRUCTORS)}
   }
diff --git a/ld/scripttempl/ft32.sc b/ld/scripttempl/ft32.sc
index e52e75cd924..666664ab190 100644
--- a/ld/scripttempl/ft32.sc
+++ b/ld/scripttempl/ft32.sc
@@ -32,6 +32,7 @@ SECTIONS
 {
   .text :
   {
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text${RELOCATING+*})
     ${RELOCATING+*(.strings)
     *(._pm*)
@@ -43,6 +44,7 @@ SECTIONS
   ${CONSTRUCTING+${TORS}}
   .data	: ${RELOCATING+ AT (ADDR (.text) + SIZEOF (.text))}
   {
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+*(.rodata)
     *(.rodata*)
diff --git a/ld/scripttempl/i386beos.sc b/ld/scripttempl/i386beos.sc
index 6c512e67760..276f0dedfe5 100644
--- a/ld/scripttempl/i386beos.sc
+++ b/ld/scripttempl/i386beos.sc
@@ -60,6 +60,7 @@ SECTIONS
   {
     ${RELOCATING+ __text_start__ = . ;}
     ${RELOCATING+ KEEP (*(SORT_NONE(.init)))}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${R_TEXT}
     *(.glue_7t)
@@ -85,6 +86,7 @@ SECTIONS
   .data ${RELOCATING+BLOCK(__section_alignment__)} :
   {
     ${RELOCATING+__data_start__ = . ;}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     *(.data2)
     ${R_DATA}
diff --git a/ld/scripttempl/i386go32.sc b/ld/scripttempl/i386go32.sc
index 9b992279e4e..f7c6109bdaa 100644
--- a/ld/scripttempl/i386go32.sc
+++ b/ld/scripttempl/i386go32.sc
@@ -34,6 +34,7 @@ ${RELOCATING+ENTRY (${ENTRY})}
 SECTIONS
 {
   .text ${RELOCATING+ ${TARGET_PAGE_SIZE}+SIZEOF_HEADERS} : {
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.text.*)}
     ${RELOCATING+*(.gnu.linkonce.t*)}
@@ -58,6 +59,7 @@ SECTIONS
     __environ = . ;
     PROVIDE(_environ = .) ;
     LONG(0) ;
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+*(.data.*)}
 
diff --git a/ld/scripttempl/iq2000.sc b/ld/scripttempl/iq2000.sc
index e85aa2303ed..2a55ef7f7a0 100644
--- a/ld/scripttempl/iq2000.sc
+++ b/ld/scripttempl/iq2000.sc
@@ -297,6 +297,7 @@ cat <<EOF
   .text    ${RELOCATING-0} :
   {
     ${RELOCATING+${TEXT_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.text.*)}
     *(.stub)
@@ -323,6 +324,7 @@ cat <<EOF
   .data  ${RELOCATING-0} :
   {
     ${RELOCATING+${DATA_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+*(.data.*)}
     ${RELOCATING+*(.gnu.linkonce.d.*)}
diff --git a/ld/scripttempl/mcorepe.sc b/ld/scripttempl/mcorepe.sc
index 3262102e85e..7a37a784d1c 100644
--- a/ld/scripttempl/mcorepe.sc
+++ b/ld/scripttempl/mcorepe.sc
@@ -66,6 +66,7 @@ SECTIONS
   .text ${RELOCATING+ __image_base__ + __section_alignment__ } :
   {
     ${RELOCATING+ KEEP (*(SORT_NONE(.init)))}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${R_TEXT}
     ${RELOCATING+ *(.text.*)}
@@ -91,6 +92,7 @@ SECTIONS
   .data ${RELOCATING+BLOCK(__section_alignment__)} :
   {
     ${RELOCATING+__data_start__ = . ;}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     *(.data2)
     ${R_DATA}
diff --git a/ld/scripttempl/mep.sc b/ld/scripttempl/mep.sc
index 39e4d64857c..3bf5e0354aa 100644
--- a/ld/scripttempl/mep.sc
+++ b/ld/scripttempl/mep.sc
@@ -310,6 +310,7 @@ cat <<EOF
   .text         ${RELOCATING-0} :
   {
     ${RELOCATING+${TEXT_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*})
     /* .gnu.warning sections are handled specially by elf.em.  */
     *(.gnu.warning)
@@ -369,6 +370,7 @@ cat <<EOF
   .data         ${RELOCATING-0} :
   {
     ${RELOCATING+${DATA_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*})
     ${CONSTRUCTING+SORT(CONSTRUCTORS)}
   }
diff --git a/ld/scripttempl/mmo.sc b/ld/scripttempl/mmo.sc
index e87a758eb90..ef946c8d2b7 100644
--- a/ld/scripttempl/mmo.sc
+++ b/ld/scripttempl/mmo.sc
@@ -30,6 +30,7 @@ SECTIONS
     ${RELOCATING+ KEEP (*(SORT_NONE(.init)))}
     ${RELOCATING+ PROVIDE (_init_end = .);}
 
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.text.*)}
     ${RELOCATING+*(.gnu.linkonce.t*)}
@@ -87,6 +88,7 @@ SECTIONS
   {
     ${RELOCATING+ PROVIDE(__Sdata = .);}
 
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data);
     ${RELOCATING+*(.data.*)}
     ${RELOCATING+*(.gnu.linkonce.d*)}
diff --git a/ld/scripttempl/nds32elf.sc b/ld/scripttempl/nds32elf.sc
index 0f8366d91ac..13abb9fc0a4 100644
--- a/ld/scripttempl/nds32elf.sc
+++ b/ld/scripttempl/nds32elf.sc
@@ -434,11 +434,12 @@ cat <<EOF
   .text         ${RELOCATING-0} :
   {
     ${RELOCATING+${TEXT_START_SYMBOLS}}
-    ${RELOCATING+*(.text.unlikely .text.*_unlikely .text.unlikely.*)}
-    ${RELOCATING+*(.text.exit .text.exit.*)}
+    ${RELOCATING+INCLUDE section_ordering_file}
     ${RELOCATING+*(.text.startup .text.startup.*)}
     ${RELOCATING+*(.text.hot .text.hot.*)}
     ${RELOCATING+*(SORT(.text.sorted.*))}
+    ${RELOCATING+*(.text.unlikely .text.*_unlikely .text.unlikely.*)}
+    ${RELOCATING+*(.text.exit .text.exit.*)}
     *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*})
     /* .gnu.warning sections are handled specially by elf.em.  */
     *(.gnu.warning)
@@ -540,6 +541,7 @@ cat <<EOF
   .data         ${RELOCATING-0} :
   {
     ${RELOCATING+${DATA_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*})
     ${CONSTRUCTING+SORT(CONSTRUCTORS)}
   }
diff --git a/ld/scripttempl/pe.sc b/ld/scripttempl/pe.sc
index 70f5194b02f..60690b07f68 100644
--- a/ld/scripttempl/pe.sc
+++ b/ld/scripttempl/pe.sc
@@ -91,6 +91,7 @@ SECTIONS
   .text ${RELOCATING+ __image_base__ + ( __section_alignment__ < ${TARGET_PAGE_SIZE} ? . : __section_alignment__ )} :
   {
     ${RELOCATING+KEEP (*(SORT_NONE(.init)))}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${R_TEXT}
     ${RELOCATING+ *(.text.*)}
@@ -153,6 +154,7 @@ SECTIONS
   .data ${RELOCATING+BLOCK(__section_alignment__)} :
   {
     ${RELOCATING+__data_start__ = . ;}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+*(.data2)}
     ${R_DATA}
diff --git a/ld/scripttempl/pep.sc b/ld/scripttempl/pep.sc
index 63039f11574..23557104f51 100644
--- a/ld/scripttempl/pep.sc
+++ b/ld/scripttempl/pep.sc
@@ -92,6 +92,7 @@ SECTIONS
   .text ${RELOCATING+ __image_base__ + ( __section_alignment__ < ${TARGET_PAGE_SIZE} ? . : __section_alignment__ )} :
   {
     ${RELOCATING+KEEP (*(SORT_NONE(.init)))}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${R_TEXT}
     ${RELOCATING+ *(.text.*)}
@@ -154,6 +155,7 @@ SECTIONS
   .data ${RELOCATING+BLOCK(__section_alignment__)} :
   {
     ${RELOCATING+__data_start__ = . ;}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+*(.data2)}
     ${R_DATA}
diff --git a/ld/scripttempl/pru.sc b/ld/scripttempl/pru.sc
index 3ff86bc61c7..bf2b7479d46 100644
--- a/ld/scripttempl/pru.sc
+++ b/ld/scripttempl/pru.sc
@@ -110,6 +110,7 @@ SECTIONS
     ${RELOCATING+KEEP (*(.init0))}
 
     ${RELOCATING+. = ALIGN(4);}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+. = ALIGN(4);}
     ${RELOCATING+*(.text.*)}
@@ -145,6 +146,7 @@ SECTIONS
     . += (. == 0 ? 4 : 0);}
 
     ${RELOCATING+ PROVIDE (_data_start = .) ; }
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+ *(.data*)}
     ${RELOCATING+ *(.data:*)}
diff --git a/ld/scripttempl/v850.sc b/ld/scripttempl/v850.sc
index 10d1da8b5bb..b59b194be2f 100644
--- a/ld/scripttempl/v850.sc
+++ b/ld/scripttempl/v850.sc
@@ -76,6 +76,7 @@ SECTIONS
 
   .text		:
   {
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.text.*)}
 
@@ -108,6 +109,7 @@ SECTIONS
 
   .data		:
   {
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+*(.data.*)
     *(.gnu.linkonce.d*)}
diff --git a/ld/scripttempl/v850_rh850.sc b/ld/scripttempl/v850_rh850.sc
index e63e7db8884..78d99e25366 100644
--- a/ld/scripttempl/v850_rh850.sc
+++ b/ld/scripttempl/v850_rh850.sc
@@ -80,6 +80,7 @@ SECTIONS
 
   .text		:
   {
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.text.*)}
 
@@ -118,6 +119,7 @@ SECTIONS
 
   .data		:
   {
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+*(.data.*)
     *(.gnu.linkonce.d*)}
diff --git a/ld/scripttempl/visium.sc b/ld/scripttempl/visium.sc
index 0b90b888136..9038372499c 100644
--- a/ld/scripttempl/visium.sc
+++ b/ld/scripttempl/visium.sc
@@ -67,6 +67,7 @@ SECTIONS
 
   .text ${RELOCATING-0} : {
     ${RELOCATING+ _ftext  =  .;}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.text.*)}
     ${RELOCATING+*(.gnu.linkonce.t.*)}
@@ -131,6 +132,7 @@ SECTIONS
   .data ${RELOCATING-0} : {
     ${RELOCATING+ . = ALIGN(4);}
     ${RELOCATING+ _sdata  =  .;}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+*(.data.*)}
     ${RELOCATING+*(.gnu.linkonce.d.*)}
diff --git a/ld/scripttempl/xstormy16.sc b/ld/scripttempl/xstormy16.sc
index c4117fcde3e..4e180730afe 100644
--- a/ld/scripttempl/xstormy16.sc
+++ b/ld/scripttempl/xstormy16.sc
@@ -133,6 +133,7 @@ SECTIONS
     ${RELOCATING+__rdata = .;}
     ${RELOCATING+__data = .;}
     ${RELOCATING+${DATA_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.data)
     ${RELOCATING+*(.data.*)}
     ${RELOCATING+*(.gnu.linkonce.d.*)}
@@ -179,6 +180,7 @@ SECTIONS
   .text    ${RELOCATING-0} :
   {
     ${RELOCATING+${TEXT_START_SYMBOLS}}
+    ${RELOCATING+INCLUDE section_ordering_file}
     *(.text)
     ${RELOCATING+*(.text.*)}
     *(.stub)
--- /dev/null	2024-04-25 08:33:45.365694295 +0100
+++ current/ld/testsuite/ld-scripts/start.s	2024-04-24 14:27:08.712528579 +0100
@@ -0,0 +1,14 @@
+	.text
+	.global start	/* Used by SH targets.  */
+start:
+	.global _start
+_start:
+	.global __start
+__start:
+	.global _mainCRTStartup	/* Used by PE targets.  */
+_mainCRTStartup:
+	.global main	/* Used by HPPA targets.  */
+main:
+	.globl	_main	/* Used by LynxOS targets.  */
+_main:
+	.dc.a 0
--- /dev/null	2024-04-25 08:33:45.365694295 +0100
+++ current/ld/testsuite/ld-scripts/section-order-1a.d	2024-04-25 13:03:15.167491733 +0100
@@ -0,0 +1,17 @@
+#source: section-order-1b.s
+#source: section-order-1a.s
+#source: start.s
+#ld: --section-ordering-file section-order-1a.t
+#nm: -n
+
+#...
+[0-9a-f]+ T yyy
+#...
+[0-9a-f]+ T bar
+#...
+[0-9a-f]+ T [_]+start
+#...
+[0-9a-f]+ T xxx
+#...
+[0-9a-f]+ T foo
+#pass
--- /dev/null	2024-04-25 08:33:45.365694295 +0100
+++ current/ld/testsuite/ld-scripts/section-order-1a.s	2024-04-25 13:00:05.240474764 +0100
@@ -0,0 +1,19 @@
+	.section .text.foo
+	.globl	foo
+foo:
+	.dc.a 0
+	
+	.section .text.bar
+	.globl	bar
+bar:
+	.dc.a 0
+
+	.section .data.small
+	.globl small
+small:
+	.dc.a 0
+
+	.section .bar
+	.global bar
+bart:
+	.dc.a 0
--- /dev/null	2024-04-25 08:33:45.365694295 +0100
+++ current/ld/testsuite/ld-scripts/section-order-1a.t	2024-04-25 12:59:23.432471029 +0100
@@ -0,0 +1,20 @@
+.text.yyy
+
+# Multiple section-regexps can be separated by spaces
+.text.b?r .text
+
+# Inputs for different outputs can appear in a mixed order in the file.
+.data.small
+
+# Tabs count as separfators too.
+.text.xxx	.text.foo
+
+# Input sections whose names do not match the output section can be included by putting the output section name first.
+.data(.big*)
+
+# Multiple input sections can also be specified in this way.
+# Ordering of sections within the parenthesised list is not guaranteed.
+.data(.bar .baz*)
+
+# The linker will not warn if an entry is not used.
+.foo.bar
--- /dev/null	2024-04-25 08:33:45.365694295 +0100
+++ current/ld/testsuite/ld-scripts/section-order-1b.d	2024-04-25 13:03:36.592493646 +0100
@@ -0,0 +1,17 @@
+#source: section-order-1a.s
+#source: section-order-1b.s
+#source: start.s
+#ld: --section-ordering-file section-order-1b.t
+#nm: -n
+
+#...
+[0-9a-f]+ T yyy
+#...
+[0-9a-f]+ T bar
+#...
+[0-9a-f]+ T [_]+start
+#...
+[0-9a-f]+ T xxx
+#...
+[0-9a-f]+ T foo
+#pass
--- /dev/null	2024-04-25 08:33:45.365694295 +0100
+++ current/ld/testsuite/ld-scripts/section-order-1b.s	2024-04-25 12:59:47.416473174 +0100
@@ -0,0 +1,19 @@
+	.section .text.xxx
+	.globl	xxx
+xxx:
+	.dc.a 0
+	
+	.section .text.yyy
+	.globl	yyy
+yyy:
+	.dc.a 0
+
+	.section .big
+	.global big
+big:
+	.dc.a 0
+
+	.section .baz
+	.global baz
+baz:
+	.dc.a 0
--- /dev/null	2024-04-25 08:33:45.365694295 +0100
+++ current/ld/testsuite/ld-scripts/section-order-1b.t	2024-04-25 12:55:08.604453855 +0100
@@ -0,0 +1,4 @@
+.text.yyy
+.text.b?r
+.text(*t)
+.text.xxx .text.foo
--- /dev/null	2024-04-25 08:33:45.365694295 +0100
+++ current/ld/testsuite/ld-scripts/section-order-1c.d	2024-04-25 13:04:12.080496817 +0100
@@ -0,0 +1,6 @@
+#source: section-order-1a.s
+#source: section-order-1b.s
+#source: start.s
+#ld: --section-ordering-file section-order-1c.t
+#nm: -n
+#error: .*: 'INCLUDE section-order-1b.t' found in the section ordering file: 'section-order-1c.t'
--- /dev/null	2024-04-25 08:33:45.365694295 +0100
+++ current/ld/testsuite/ld-scripts/section-order-1c.t	2024-04-25 13:07:15.671497250 +0100
@@ -0,0 +1,5 @@
+.text.yyy
+.text.b?r
+INCLUDE section-order-1b.t
+.t*t
+.text.xxx .text.foo
--- /dev/null	2024-04-25 08:33:45.365694295 +0100
+++ current/ld/testsuite/ld-scripts/section-order-1d.d	2024-04-25 13:05:43.864501411 +0100
@@ -0,0 +1,13 @@
+#source: section-order-1b.s
+#source: section-order-1a.s
+#source: start.s
+#ld: --section-ordering-file section-order-1a.t
+#nm: -n
+
+#...
+[0-9a-f]+ D small
+#...
+[0-9a-f]+ D big
+#...
+[0-9a-f]+ D ba.*
+#pass
--- /dev/null	2024-04-25 08:33:45.365694295 +0100
+++ current/ld/testsuite/ld-scripts/section-order.exp	2024-04-25 13:02:50.591489535 +0100
@@ -0,0 +1,45 @@
+# Test for --section-ordering-file FILE.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+# The --section-ordering-file option is only supported by ELF and
+# PE COFF linkers, which allow for arbitrarily named sections, eg:
+# .text.*
+if { !([is_elf_format] || [is_pecoff_format]) } {
+    return
+}
+
+set old_ldflags $LDFLAGS
+if { [istarget spu*-*-*] } then {
+    set LDFLAGS "$LDFLAGS --local-store 0:0 --no-overlays"
+} elseif { [is_pecoff_format] } then {
+    set LDFLAGS "$LDFLAGS --image-base 0"
+} elseif { [is_xcoff_format] } then {
+    set LDFLAGS "$LDFLAGS -bnogc"
+}
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/section-order*.d]]
+foreach test_file $test_list {
+    set test_name [file rootname $test_file]
+    set map_file "tmpdir/[file tail $test_name].map"
+    verbose $test_name
+    run_dump_test $test_name
+}
+
+set LDFLAGS $old_ldflags

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: ld: Add --text-section-ordering-file (version 2)
  2024-04-25 13:01 RFC: ld: Add --text-section-ordering-file (version 2) Nick Clifton
@ 2024-04-25 15:32 ` H.J. Lu
  2024-04-26  9:38   ` Nick Clifton
  2024-04-26  1:46 ` Hans-Peter Nilsson
  2024-04-26  4:17 ` Alan Modra
  2 siblings, 1 reply; 13+ messages in thread
From: H.J. Lu @ 2024-04-25 15:32 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils, siddhesh

On Thu, Apr 25, 2024 at 6:01 AM Nick Clifton <nickc@redhat.com> wrote:
>
> Hi Guys,
>
>   Attached is a patch to add a --section-ordering-file option to the BFD
>   linker.  It is based upon H.J.'s original patch, but extended so that
>   it will work with multiple output sections.
>
>   There are a couple of points that I feel I should highlight:
>
>   * The option only works in conjunction with a modified linker script.
>
>     In particular the script must have: "INCLUDE section-ordering-file"
>     statements in it, wherever it wants section ordering to be allowed.
>     This statement can appear multiple times in a linker script,
>     although it would not make sense to have it appear more than once in
>     any given output section.  Here is an example:
>
>       SECTIONS
>       {
>         .text : {
>           INCLUDE section-ordering-file
>           *(.text)
>         }
>         .data : {
>           INCLUDE section-ordering-file
>           *(.data)
>         }
>       }
>
>   * H.J's original version allowed for linker script like
>     "filename(section)" syntax to be used to name sections, eg:
>     "*(.text.*)", as well as a simpler "section name regexp", eg
>     ".text.*", to be used.  This version only supports the latter
>     format.
>
>     In addition H.J.'s syntax allowed for abbreviated section names to
>     match.  So ".t*t" would match any section starting with ".t" and
>     ending with "t" and would put it into the .text section.  In this
>     version however the output section is selected based upon matching
>     the fixed part at the start of the pattern with the output section.
>     So ".t*t" would only work if the output section was called ".t".
>
>     To help compensate for this, and to allow arbitrary input sections
>     to be mapped to specific output sections, the output section name
>     can be provided as if it were a filename.  So .foo(.bar) would map
>     all sections called .bar to the output section .foo, but only if the
>     linker script has an output section called .foo, and only if that
>     output section declaration includes a INCLUDE section-ordering-file
>     statement.
>
>     Perhaps an example will make things clearer.  If the above linker
>     script is used and the section ordering file contains:
>
>       # A comment - this will be ignored.
>       .text.hot .text.cold .text.warm
>       .data.big
>       .data(.bar)
>       .text.foo*
>       .ignore(.me)
>
>     This is roughly equivalent to a linker script that looks like this:
>
>       SECTIONS
>       {
>         .text : {
>           *(.text.hot)
>           *(.text.cold)
>           *(.text.warm)
>           *(.text.foo*)
>           *(.text)
>         }
>         .data : {
>           *(.data.big)
>           *(.bar)
>           *(.data)
>         }
>       }
>
>     Note - the linker will not warn about entries in the section
>     ordering file that do not match an output section name.  So in the
>     above example the ".ignore(.me)" entry will not generate a warning
>     about it not being used.
>
>   Thoughts, comments, etc ?
>

Should it also handle .rodata, .bss and other data sections?

-- 
H.J.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: ld: Add --text-section-ordering-file (version 2)
  2024-04-25 13:01 RFC: ld: Add --text-section-ordering-file (version 2) Nick Clifton
  2024-04-25 15:32 ` H.J. Lu
@ 2024-04-26  1:46 ` Hans-Peter Nilsson
  2024-04-26  9:46   ` Nick Clifton
  2024-04-26  4:17 ` Alan Modra
  2 siblings, 1 reply; 13+ messages in thread
From: Hans-Peter Nilsson @ 2024-04-26  1:46 UTC (permalink / raw)
  To: Nick Clifton; +Cc: hjl.tools, binutils, siddhesh

On Thu, 25 Apr 2024, Nick Clifton wrote:

>   Thoughts, comments, etc ?

Sounds great! ...except:

>     match.  So ".t*t" would match any section starting with ".t" and
>     ending with "t" and would put it into the .text section.  In this
>     version however the output section is selected based upon matching
>     the fixed part at the start of the pattern with the output section.
>     So ".t*t" would only work if the output section was called ".t".

Do you mean '...if the output section was called ".tt"'?  Else, 
having a pattern .t*t matching an instance .t sounds confusing.  

Actually, thats still sounds confusing anyway; I don't 
understand the limitation, sorry for being thick.  If you need 
to keep the code simple or something, maybe just allow a 
trailing "*"?

(I've not paid attention to earlier versions.)

brgds, H-P

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: ld: Add --text-section-ordering-file (version 2)
  2024-04-25 13:01 RFC: ld: Add --text-section-ordering-file (version 2) Nick Clifton
  2024-04-25 15:32 ` H.J. Lu
  2024-04-26  1:46 ` Hans-Peter Nilsson
@ 2024-04-26  4:17 ` Alan Modra
  2024-04-26  9:59   ` Nick Clifton
  2 siblings, 1 reply; 13+ messages in thread
From: Alan Modra @ 2024-04-26  4:17 UTC (permalink / raw)
  To: Nick Clifton; +Cc: hjl.tools, binutils, siddhesh

On Thu, Apr 25, 2024 at 02:01:01PM +0100, Nick Clifton wrote:
> Hi Guys,
> 
>   Attached is a patch to add a --section-ordering-file option to the BFD
>   linker.  It is based upon H.J.'s original patch, but extended so that
>   it will work with multiple output sections.
> 
>   There are a couple of points that I feel I should highlight:
> 
>   * The option only works in conjunction with a modified linker script.
>   
>     In particular the script must have: "INCLUDE section-ordering-file"
>     statements in it, wherever it wants section ordering to be allowed.
>     This statement can appear multiple times in a linker script,
>     although it would not make sense to have it appear more than once in
>     any given output section.  Here is an example:
>     
>       SECTIONS
>       {
>         .text : {
>           INCLUDE section-ordering-file
>           *(.text)
>         }
>         .data : {
>           INCLUDE section-ordering-file
>           *(.data)
>         }
>       }
>     
>   * H.J's original version allowed for linker script like
>     "filename(section)" syntax to be used to name sections, eg:
>     "*(.text.*)", as well as a simpler "section name regexp", eg
>     ".text.*", to be used.  This version only supports the latter
>     format.
> 
>     In addition H.J.'s syntax allowed for abbreviated section names to
>     match.  So ".t*t" would match any section starting with ".t" and
>     ending with "t" and would put it into the .text section.  In this
>     version however the output section is selected based upon matching
>     the fixed part at the start of the pattern with the output section.
>     So ".t*t" would only work if the output section was called ".t".
> 
>     To help compensate for this, and to allow arbitrary input sections
>     to be mapped to specific output sections, the output section name
>     can be provided as if it were a filename.  So .foo(.bar) would map
>     all sections called .bar to the output section .foo, but only if the
>     linker script has an output section called .foo, and only if that
>     output section declaration includes a INCLUDE section-ordering-file
>     statement.
>     
>     Perhaps an example will make things clearer.  If the above linker
>     script is used and the section ordering file contains:
> 
>       # A comment - this will be ignored.
>       .text.hot .text.cold .text.warm
>       .data.big
>       .data(.bar)
>       .text.foo*
>       .ignore(.me)
> 
>     This is roughly equivalent to a linker script that looks like this:
> 
>       SECTIONS
>       {
>         .text : {
>           *(.text.hot)
>           *(.text.cold)
>           *(.text.warm)
>           *(.text.foo*)
>           *(.text)
>         }
>         .data : {
>           *(.data.big)
>           *(.bar)
>           *(.data)
>         }
>       }
> 
>     Note - the linker will not warn about entries in the section
>     ordering file that do not match an output section name.  So in the
>     above example the ".ignore(.me)" entry will not generate a warning
>     about it not being used.
> 
>   Thoughts, comments, etc ?

This seems really clunky to me.  How about a script that augments
the default script, but looks very similar to other scripts, ie. with
a SECTIONS clause?  To take your example, use a script like:

  SECTIONS
  {
    .text : {
      *(.text.hot)
      *(.text.cold)
      *(.text.warm)
      *(.text.foo*)
    }
    .data : {
      *(.data.big)
      *(.bar)
    }
  }

Then arrange to insert the contents of each output section statement
in this script at the start of corresponding output section statement
in the default script.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: ld: Add --text-section-ordering-file (version 2)
  2024-04-25 15:32 ` H.J. Lu
@ 2024-04-26  9:38   ` Nick Clifton
  0 siblings, 0 replies; 13+ messages in thread
From: Nick Clifton @ 2024-04-26  9:38 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils, siddhesh

Hi H.J.

> Should it also handle .rodata, .bss and other data sections?

It could.  I was not sure how much we should change the current
built-in linker scripts.  But you are right, it would be better
to allow for the possibility that users might want to order these
sections too.  I will make the change.

Cheers
   Nick



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: ld: Add --text-section-ordering-file (version 2)
  2024-04-26  1:46 ` Hans-Peter Nilsson
@ 2024-04-26  9:46   ` Nick Clifton
  2024-04-27  0:46     ` Hans-Peter Nilsson
  0 siblings, 1 reply; 13+ messages in thread
From: Nick Clifton @ 2024-04-26  9:46 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: hjl.tools, binutils, siddhesh

Hi Hans-Peter,

> Sounds great! ...except:
> 
>>      match.  So ".t*t" would match any section starting with ".t" and
>>      ending with "t" and would put it into the .text section.  In this
>>      version however the output section is selected based upon matching
>>      the fixed part at the start of the pattern with the output section.
>>      So ".t*t" would only work if the output section was called ".t".
> 
> Do you mean '...if the output section was called ".tt"'?  Else,
> having a pattern .t*t matching an instance .t sounds confusing.

No.  Basically the code compares each entry in the section ordering file
with the name of the output section that is currently being processed.
So if the output section is called ".text" then any entry in the ordering
file that starts with ".text" will be considered as valid for this section.
But this is a straight string comparison operation, not a regular expression
match.  So an entry for ".t*t" would not match an output section called ".text".

Now if the output section was called ".t" then this would match the ".t*t"
entry (and all of the .text.<whatever> entries that might be in the ordering
file).  Which would probably cause the ordering file not to work the way that
the user wants.  But since this only works if the linker script has allowed
ordering in the .t section, the user would have to deliberately create a
strange linker script, eg:

   SECTIONS
   {
      .t : { INCLUDE section-ordering-file ; *(.t) }
      .text { INCLUDE section-ordering-file ; *(.text) }
   }

I hope that this makes sense. :-)

Cheers
   Nick


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: ld: Add --text-section-ordering-file (version 2)
  2024-04-26  4:17 ` Alan Modra
@ 2024-04-26  9:59   ` Nick Clifton
  2024-04-26 12:43     ` Alan Modra
  0 siblings, 1 reply; 13+ messages in thread
From: Nick Clifton @ 2024-04-26  9:59 UTC (permalink / raw)
  To: Alan Modra; +Cc: hjl.tools, binutils, siddhesh

Hi Alan,

> This seems really clunky to me.  How about a script that augments
> the default script, but looks very similar to other scripts, ie. with
> a SECTIONS clause?  To take your example, use a script like:
> 
>    SECTIONS
>    {
>      .text : {
>        *(.text.hot)
>        *(.text.cold)
>        *(.text.warm)
>        *(.text.foo*)
>      }
>      .data : {
>        *(.data.big)
>        *(.bar)
>      }
>    }
> 
> Then arrange to insert the contents of each output section statement
> in this script at the start of corresponding output section statement
> in the default script.

Well I had several reasons:

   1. I wanted the feature to be compatible with the gold linker, which
      just uses the plain section name format, not the linker script format.

   2. I wanted users who are not familiar with linker scripts to be able
      to use the feature.  In particular I am hoping that package maintainers
      that profile their programs can use this feature to experiment with
      different section orderings without having to learn how to create
      their own scripts.

   3. I want the linker script to be able to define where, within an output
      section, the ordering should take place.  That way, if there are things
      that must appear at the start of the section, before any ordering, the
      script can make sure that this happens.  eg:

      .init : {
          LONG (0)
          INCLUDE section-ordering-file
          (*.init)
          LONG (0)
       }

      I just made that example up, but I am sure that you get the idea.

The other thing is practicality.  With the current method the contents of
the section ordering file can be parsed as they appear during the normal
linker script processing.  If on the other hand the ordering file was to
be processed first and then parts of it inserted ad hoc into the output
section statements, that would require a lot more hacking on the parser.
It could be done, but I like keeping things simple.

Cheers
   Nick




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: ld: Add --text-section-ordering-file (version 2)
  2024-04-26  9:59   ` Nick Clifton
@ 2024-04-26 12:43     ` Alan Modra
  2024-04-29  0:12       ` Alan Modra
  0 siblings, 1 reply; 13+ messages in thread
From: Alan Modra @ 2024-04-26 12:43 UTC (permalink / raw)
  To: Nick Clifton; +Cc: hjl.tools, binutils, siddhesh

On Fri, Apr 26, 2024 at 10:59:00AM +0100, Nick Clifton wrote:
> It could be done, but I like keeping things simple.

Here's a completely untested implementation of the idea I'm proposing,
written just to show that the linker modifications are relatively
small.  (There is a very good chance I've messed up list handling..)
What appears inside the --section-ordering-file output sections is
spliced in to corresponding output sections in the default script,
before the first input wild statement.

I like keeping things simple too.  This should work without modifying
default linker scripts (and user scripts!), and allows all the usual
ways of specifying input sections.  That means you can use constructs
like EXCLUDE_FILE, SORT, KEEP, *(.text .rdata) vs. *(.text) *(.rdata)
and so on.

diff --git a/ld/ld.h b/ld/ld.h
index fcdd9a2c083..15d9dc262b6 100644
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -196,6 +196,8 @@ typedef struct
 
   /* Default linker script.  */
   char *default_script;
+
+  char *section_ordering_file;
 } args_type;
 
 extern args_type command_line;
@@ -325,6 +327,7 @@ extern ld_config_type config;
 
 extern FILE * saved_script_handle;
 extern bool force_make_executable;
+extern bool in_section_ordering;
 
 extern int yyparse (void);
 extern void add_cref (const char *, bfd *, asection *, bfd_vma);
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 54d1af62ebe..f9fb50e99ec 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1299,6 +1299,7 @@ output_section_statement_newfunc (struct bfd_hash_entry *entry,
   ret->s.output_section_statement.section_alignment = NULL;
   ret->s.output_section_statement.block_value = 1;
   lang_list_init (&ret->s.output_section_statement.children);
+  lang_list_init (&ret->s.output_section_statement.sort_children);
   lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next);
 
   /* For every output section statement added to the list, except the
@@ -7613,13 +7614,19 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
   lang_output_section_statement_type *os;
 
   os = lang_output_section_statement_lookup (output_section_statement_name,
-					     constraint, 2);
+					     constraint,
+					     in_section_ordering ? 1 : 2);
   current_section = os;
 
+  /* Make next things chain into subchain of this.  */
+  push_stat_ptr (in_section_ordering ? &os->sort_children : &os->children);
+
+  if (in_section_ordering)
+    return os;
+
   if (os->addr_tree == NULL)
-    {
-      os->addr_tree = address_exp;
-    }
+    os->addr_tree = address_exp;
+
   os->sectype = sectype;
   if (sectype == type_section || sectype == typed_readonly_section)
     os->sectype_value = sectype_value;
@@ -7629,9 +7636,6 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
     os->flags = SEC_NO_FLAGS;
   os->block_value = 1;
 
-  /* Make next things chain into subchain of this.  */
-  push_stat_ptr (&os->children);
-
   os->align_lma_with_input = align_with_input == ALIGN_WITH_INPUT;
   if (os->align_lma_with_input && align != NULL)
     einfo (_("%F%P:%pS: error: align with input and explicit align specified\n"),
@@ -8127,9 +8131,33 @@ reset_resolved_wilds (void)
   lang_for_each_statement (reset_one_wild);
 }
 
+static void
+lang_os_merge_sort_children (void)
+{
+  lang_output_section_statement_type *os;
+  for (os = (void *) lang_os_list.head; os != NULL; os = os->next)
+    {
+      if (os->sort_children.head != NULL)
+	{
+	  lang_statement_union_type **where;
+	  for (where = &os->children.head;
+	       *where != NULL;
+	       where = &(*where)->header.next)
+	    if ((*where)->header.type == lang_wild_statement_enum)
+	      break;
+	  if (*where == NULL)
+	    where = &os->children.head;
+	  lang_list_insert_after (&os->children, &os->sort_children, where);
+	  lang_list_init (&os->sort_children);
+	}
+    }
+}
+
 void
 lang_process (void)
 {
+  lang_os_merge_sort_children ();
+
   /* Finalize dynamic list.  */
   if (link_info.dynamic_list)
     lang_finalize_version_expr_head (&link_info.dynamic_list->head);
@@ -8817,6 +8845,10 @@ lang_leave_output_section_statement (fill_type *fill, const char *memspec,
 				     lang_output_section_phdr_list *phdrs,
 				     const char *lma_memspec)
 {
+  pop_stat_ptr ();
+  if (in_section_ordering)
+    return;
+
   lang_get_regions (&current_section->region,
 		    &current_section->lma_region,
 		    memspec, lma_memspec,
@@ -8825,7 +8857,6 @@ lang_leave_output_section_statement (fill_type *fill, const char *memspec,
 
   current_section->fill = fill;
   current_section->phdrs = phdrs;
-  pop_stat_ptr ();
 }
 
 /* Set the output format type.  -oformat overrides scripts.  */
diff --git a/ld/ldlang.h b/ld/ldlang.h
index ea1c26d00f3..91947c56fda 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -162,6 +162,8 @@ typedef struct lang_output_section_statement_struct
 
   lang_output_section_phdr_list *phdrs;
 
+  lang_statement_list_type sort_children;
+
   /* Used by ELF SHF_LINK_ORDER sorting.  */
   void *data;
 
diff --git a/ld/ldlex.h b/ld/ldlex.h
index d575562a357..5708e6f5e34 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -62,6 +62,7 @@ enum option_values
   OPTION_SONAME,
   OPTION_SORT_COMMON,
   OPTION_SORT_SECTION,
+  OPTION_SECTION_ORDERING_FILE,
   OPTION_STATS,
   OPTION_SYMBOLIC,
   OPTION_SYMBOLIC_FUNCTIONS,
diff --git a/ld/ldmain.c b/ld/ldmain.c
index fe389681bd3..77b57a9fd32 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -90,6 +90,8 @@ bool version_printed;
 /* TRUE if we should demangle symbol names.  */
 bool demangling;
 
+bool in_section_ordering;
+
 args_type command_line;
 
 ld_config_type config;
@@ -446,6 +448,19 @@ main (int argc, char **argv)
       info_msg ("\n==================================================\n");
     }
 
+  if (command_line.section_ordering_file)
+    {
+      FILE *hold_script_handle;
+
+      hold_script_handle = saved_script_handle;
+      ldfile_open_command_file (command_line.section_ordering_file);
+      saved_script_handle = hold_script_handle;
+      in_section_ordering = true;
+      parser_input = input_script;
+      yyparse ();
+      in_section_ordering = false;
+    }
+
   if (command_line.force_group_allocation
       || !bfd_link_relocatable (&link_info))
     link_info.resolve_section_groups = true;
diff --git a/ld/lexsup.c b/ld/lexsup.c
index dad3b6059ed..0c337a4d170 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -487,6 +487,9 @@ static const struct ld_option ld_options[] =
   { {"sort-section", required_argument, NULL, OPTION_SORT_SECTION},
     '\0', N_("name|alignment"),
     N_("Sort sections by name or maximum alignment"), TWO_DASHES },
+  { {"section-ordering-file", required_argument, NULL, OPTION_SECTION_ORDERING_FILE},
+    '\0', N_("FILE"),
+    N_("Sort sections by statements in FILE"), TWO_DASHES },
   { {"spare-dynamic-tags", required_argument, NULL, OPTION_SPARE_DYNAMIC_TAGS},
     '\0', N_("COUNT"), N_("How many tags to reserve in .dynamic section"),
     TWO_DASHES },
@@ -1400,6 +1403,9 @@ parse_args (unsigned argc, char **argv)
 	    einfo (_("%F%P: invalid section sorting option: %s\n"),
 		   optarg);
 	  break;
+	case OPTION_SECTION_ORDERING_FILE:
+	  command_line.section_ordering_file = optarg;
+	  break;
 	case OPTION_STATS:
 	  config.stats = true;
 	  break;

-- 
Alan Modra

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: ld: Add --text-section-ordering-file (version 2)
  2024-04-26  9:46   ` Nick Clifton
@ 2024-04-27  0:46     ` Hans-Peter Nilsson
  0 siblings, 0 replies; 13+ messages in thread
From: Hans-Peter Nilsson @ 2024-04-27  0:46 UTC (permalink / raw)
  To: Nick Clifton; +Cc: hjl.tools, binutils, siddhesh

On Fri, 26 Apr 2024, Nick Clifton wrote:
> Hi Hans-Peter,
> 
> > Sounds great! ...except:
> > 
> > >      match.  So ".t*t" would match any section starting with ".t" and
> > >      ending with "t" and would put it into the .text section.  In this
> > >      version however the output section is selected based upon matching
> > >      the fixed part at the start of the pattern with the output section.
> > >      So ".t*t" would only work if the output section was called ".t".
> > 
> > Do you mean '...if the output section was called ".tt"'?  Else,
> > having a pattern .t*t matching an instance .t sounds confusing.
> 
> No.  Basically the code compares each entry in the section ordering file
> with the name of the output section that is currently being processed.
> So if the output section is called ".text" then any entry in the ordering
> file that starts with ".text" will be considered as valid for this section.
> But this is a straight string comparison operation, not a regular expression
> match.  So an entry for ".t*t" would not match an output section called
> ".text".
> 
> Now if the output section was called ".t" then this would match the ".t*t"
> entry (and all of the .text.<whatever> entries that might be in the ordering
> file).  Which would probably cause the ordering file not to work the way that
> the user wants.  But since this only works if the linker script has allowed
> ordering in the .t section, the user would have to deliberately create a
> strange linker script, eg:
> 
>   SECTIONS
>   {
>      .t : { INCLUDE section-ordering-file ; *(.t) }
>      .text { INCLUDE section-ordering-file ; *(.text) }
>   }
> 
> I hope that this makes sense. :-)

Honestly, no.  Sorry.  But feel free to ignore my ignorance.
I just hope my confusion makes sense to the wider audience.

I don't think ".t*t" should match ".t" but that it should match 
".text" and ".tt".  I'm certainly not going to insist.

brgds, H-P

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: ld: Add --text-section-ordering-file (version 2)
  2024-04-26 12:43     ` Alan Modra
@ 2024-04-29  0:12       ` Alan Modra
  2024-05-02 15:16         ` Nick Clifton
                           ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Alan Modra @ 2024-04-29  0:12 UTC (permalink / raw)
  To: Nick Clifton; +Cc: hjl.tools, binutils, siddhesh

On Fri, Apr 26, 2024 at 10:13:48PM +0930, Alan Modra wrote:
> On Fri, Apr 26, 2024 at 10:59:00AM +0100, Nick Clifton wrote:
> > It could be done, but I like keeping things simple.
> 
> Here's a completely untested implementation of the idea I'm proposing,
> written just to show that the linker modifications are relatively
> small.  (There is a very good chance I've messed up list handling..)
> What appears inside the --section-ordering-file output sections is
> spliced in to corresponding output sections in the default script,
> before the first input wild statement.
> 
> I like keeping things simple too.  This should work without modifying
> default linker scripts (and user scripts!), and allows all the usual
> ways of specifying input sections.  That means you can use constructs
> like EXCLUDE_FILE, SORT, KEEP, *(.text .rdata) vs. *(.text) *(.rdata)
> and so on.

The patch wasn't too far wrong.  I had some compile issues when plugin
support was disabled, and it is probably a bad idea to allow creation
of new output sections via --section-ordering-file, so that is now
disallowed.

I'm not putting forward this patch as a finished work, it's just a
demonstrator.

What I'd like to see is:
1) Lose that horrible "INCLUDE section-ordering-file" requirement for
   existing scripts.  Do you really want that put into every output
   section in every script in scripttempl/?
2) Parse the section ordering file in ldgram.y.  An entry under file:
   would be appropriate, like we do for version scripts.  That would
   at least lose the SECTIONS clause required by my demonstrator
   patch.  You wouldn't necessarily need to follow existing
   specification of output and input sections, or to support other
   things allowed in output sections, but I do think a syntax with an
   explicit output section is a good idea.  ie. not one where the
   output .text is deduced from the input .text.mumble.


diff --git a/ld/ld.h b/ld/ld.h
index fcdd9a2c083..15d9dc262b6 100644
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -196,6 +196,8 @@ typedef struct
 
   /* Default linker script.  */
   char *default_script;
+
+  char *section_ordering_file;
 } args_type;
 
 extern args_type command_line;
@@ -325,6 +327,7 @@ extern ld_config_type config;
 
 extern FILE * saved_script_handle;
 extern bool force_make_executable;
+extern bool in_section_ordering;
 
 extern int yyparse (void);
 extern void add_cref (const char *, bfd *, asection *, bfd_vma);
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 54d1af62ebe..6424d4764d1 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1299,6 +1299,7 @@ output_section_statement_newfunc (struct bfd_hash_entry *entry,
   ret->s.output_section_statement.section_alignment = NULL;
   ret->s.output_section_statement.block_value = 1;
   lang_list_init (&ret->s.output_section_statement.children);
+  lang_list_init (&ret->s.output_section_statement.sort_children);
   lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next);
 
   /* For every output section statement added to the list, except the
@@ -7613,13 +7614,21 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
   lang_output_section_statement_type *os;
 
   os = lang_output_section_statement_lookup (output_section_statement_name,
-					     constraint, 2);
+					     constraint,
+					     in_section_ordering ? 0 : 2);
+  if (os == NULL)
+    einfo (_("%F%P:%pS: error: output section must already exist\n"), NULL);
   current_section = os;
 
+  /* Make next things chain into subchain of this.  */
+  push_stat_ptr (in_section_ordering ? &os->sort_children : &os->children);
+
+  if (in_section_ordering)
+    return os;
+
   if (os->addr_tree == NULL)
-    {
-      os->addr_tree = address_exp;
-    }
+    os->addr_tree = address_exp;
+
   os->sectype = sectype;
   if (sectype == type_section || sectype == typed_readonly_section)
     os->sectype_value = sectype_value;
@@ -7629,9 +7638,6 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
     os->flags = SEC_NO_FLAGS;
   os->block_value = 1;
 
-  /* Make next things chain into subchain of this.  */
-  push_stat_ptr (&os->children);
-
   os->align_lma_with_input = align_with_input == ALIGN_WITH_INPUT;
   if (os->align_lma_with_input && align != NULL)
     einfo (_("%F%P:%pS: error: align with input and explicit align specified\n"),
@@ -7971,21 +7977,6 @@ find_rescan_insertion (lang_input_statement_type *add)
   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.)  */
-
-static void
-lang_list_insert_after (lang_statement_list_type *destlist,
-			lang_statement_list_type *srclist,
-			lang_statement_union_type **field)
-{
-  *(srclist->tail) = *field;
-  *field = srclist->head;
-  if (destlist->tail == field)
-    destlist->tail = srclist->tail;
-}
-
 /* Detach new nodes added to DESTLIST since the time ORIGLIST
    was taken as a copy of it and leave them in ORIGLIST.  */
 
@@ -8033,6 +8024,21 @@ find_next_input_statement (lang_statement_union_type **s)
 }
 #endif /* BFD_SUPPORTS_PLUGINS */
 
+/* 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.)  */
+
+static void
+lang_list_insert_after (lang_statement_list_type *destlist,
+			lang_statement_list_type *srclist,
+			lang_statement_union_type **field)
+{
+  *(srclist->tail) = *field;
+  *field = srclist->head;
+  if (destlist->tail == field)
+    destlist->tail = srclist->tail;
+}
+
 /* Add NAME to the list of garbage collection entry points.  */
 
 void
@@ -8127,9 +8133,34 @@ reset_resolved_wilds (void)
   lang_for_each_statement (reset_one_wild);
 }
 
+/* For each output section statement, splice any entries on the
+   sort_children list before the first wild statement on the children
+   list.  */
+
+static void
+lang_os_merge_sort_children (void)
+{
+  lang_output_section_statement_type *os;
+  for (os = (void *) lang_os_list.head; os != NULL; os = os->next)
+    {
+      if (os->sort_children.head != NULL)
+	{
+	  lang_statement_union_type **where;
+	  for (where = &os->children.head;
+	       *where != NULL;
+	       where = &(*where)->header.next)
+	    if ((*where)->header.type == lang_wild_statement_enum)
+	      break;
+	  lang_list_insert_after (&os->children, &os->sort_children, where);
+	}
+    }
+}
+
 void
 lang_process (void)
 {
+  lang_os_merge_sort_children ();
+
   /* Finalize dynamic list.  */
   if (link_info.dynamic_list)
     lang_finalize_version_expr_head (&link_info.dynamic_list->head);
@@ -8817,6 +8848,10 @@ lang_leave_output_section_statement (fill_type *fill, const char *memspec,
 				     lang_output_section_phdr_list *phdrs,
 				     const char *lma_memspec)
 {
+  pop_stat_ptr ();
+  if (in_section_ordering)
+    return;
+
   lang_get_regions (&current_section->region,
 		    &current_section->lma_region,
 		    memspec, lma_memspec,
@@ -8825,7 +8860,6 @@ lang_leave_output_section_statement (fill_type *fill, const char *memspec,
 
   current_section->fill = fill;
   current_section->phdrs = phdrs;
-  pop_stat_ptr ();
 }
 
 /* Set the output format type.  -oformat overrides scripts.  */
diff --git a/ld/ldlang.h b/ld/ldlang.h
index ea1c26d00f3..91947c56fda 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -162,6 +162,8 @@ typedef struct lang_output_section_statement_struct
 
   lang_output_section_phdr_list *phdrs;
 
+  lang_statement_list_type sort_children;
+
   /* Used by ELF SHF_LINK_ORDER sorting.  */
   void *data;
 
diff --git a/ld/ldlex.h b/ld/ldlex.h
index d575562a357..5708e6f5e34 100644
--- a/ld/ldlex.h
+++ b/ld/ldlex.h
@@ -62,6 +62,7 @@ enum option_values
   OPTION_SONAME,
   OPTION_SORT_COMMON,
   OPTION_SORT_SECTION,
+  OPTION_SECTION_ORDERING_FILE,
   OPTION_STATS,
   OPTION_SYMBOLIC,
   OPTION_SYMBOLIC_FUNCTIONS,
diff --git a/ld/ldmain.c b/ld/ldmain.c
index fe389681bd3..77b57a9fd32 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -90,6 +90,8 @@ bool version_printed;
 /* TRUE if we should demangle symbol names.  */
 bool demangling;
 
+bool in_section_ordering;
+
 args_type command_line;
 
 ld_config_type config;
@@ -446,6 +448,19 @@ main (int argc, char **argv)
       info_msg ("\n==================================================\n");
     }
 
+  if (command_line.section_ordering_file)
+    {
+      FILE *hold_script_handle;
+
+      hold_script_handle = saved_script_handle;
+      ldfile_open_command_file (command_line.section_ordering_file);
+      saved_script_handle = hold_script_handle;
+      in_section_ordering = true;
+      parser_input = input_script;
+      yyparse ();
+      in_section_ordering = false;
+    }
+
   if (command_line.force_group_allocation
       || !bfd_link_relocatable (&link_info))
     link_info.resolve_section_groups = true;
diff --git a/ld/lexsup.c b/ld/lexsup.c
index dad3b6059ed..0c337a4d170 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -487,6 +487,9 @@ static const struct ld_option ld_options[] =
   { {"sort-section", required_argument, NULL, OPTION_SORT_SECTION},
     '\0', N_("name|alignment"),
     N_("Sort sections by name or maximum alignment"), TWO_DASHES },
+  { {"section-ordering-file", required_argument, NULL, OPTION_SECTION_ORDERING_FILE},
+    '\0', N_("FILE"),
+    N_("Sort sections by statements in FILE"), TWO_DASHES },
   { {"spare-dynamic-tags", required_argument, NULL, OPTION_SPARE_DYNAMIC_TAGS},
     '\0', N_("COUNT"), N_("How many tags to reserve in .dynamic section"),
     TWO_DASHES },
@@ -1400,6 +1403,9 @@ parse_args (unsigned argc, char **argv)
 	    einfo (_("%F%P: invalid section sorting option: %s\n"),
 		   optarg);
 	  break;
+	case OPTION_SECTION_ORDERING_FILE:
+	  command_line.section_ordering_file = optarg;
+	  break;
 	case OPTION_STATS:
 	  config.stats = true;
 	  break;
diff --git a/ld/testsuite/ld-scripts/section-order-1a.d b/ld/testsuite/ld-scripts/section-order-1a.d
new file mode 100644
index 00000000000..03d848b83ea
--- /dev/null
+++ b/ld/testsuite/ld-scripts/section-order-1a.d
@@ -0,0 +1,17 @@
+#source: section-order-1b.s
+#source: section-order-1a.s
+#source: start.s
+#ld: --section-ordering-file section-order-1a.t
+#nm: -n
+
+#...
+[0-9a-f]+ T yyy
+#...
+[0-9a-f]+ T bar
+#...
+[0-9a-f]+ T [_]+start
+#...
+[0-9a-f]+ T xxx
+#...
+[0-9a-f]+ T foo
+#pass
diff --git a/ld/testsuite/ld-scripts/section-order-1a.s b/ld/testsuite/ld-scripts/section-order-1a.s
new file mode 100644
index 00000000000..17d311fd58f
--- /dev/null
+++ b/ld/testsuite/ld-scripts/section-order-1a.s
@@ -0,0 +1,19 @@
+	.section .text.foo
+	.globl	foo
+foo:
+	.dc.a 0
+
+	.section .text.bar
+	.globl	bar
+bar:
+	.dc.a 0
+
+	.section .data.small
+	.globl small
+small:
+	.dc.a 0
+
+	.section .bar
+	.global bar
+bart:
+	.dc.a 0
diff --git a/ld/testsuite/ld-scripts/section-order-1a.t b/ld/testsuite/ld-scripts/section-order-1a.t
new file mode 100644
index 00000000000..e3786818fea
--- /dev/null
+++ b/ld/testsuite/ld-scripts/section-order-1a.t
@@ -0,0 +1,15 @@
+SECTIONS
+{
+  .text : {
+    *(.text.yyy)
+    *(.text.b?r)
+    *(.text)
+    *(.text.xxx .text.foo)
+  }
+
+  .data : {
+    *(.data.small)
+    *(.big*)
+    *(.bar .baz*)
+  }
+}
diff --git a/ld/testsuite/ld-scripts/section-order-1b.d b/ld/testsuite/ld-scripts/section-order-1b.d
new file mode 100644
index 00000000000..41b4d16097e
--- /dev/null
+++ b/ld/testsuite/ld-scripts/section-order-1b.d
@@ -0,0 +1,17 @@
+#source: section-order-1a.s
+#source: section-order-1b.s
+#source: start.s
+#ld: --section-ordering-file section-order-1b.t
+#nm: -n
+
+#...
+[0-9a-f]+ T yyy
+#...
+[0-9a-f]+ T bar
+#...
+[0-9a-f]+ T [_]+start
+#...
+[0-9a-f]+ T xxx
+#...
+[0-9a-f]+ T foo
+#pass
diff --git a/ld/testsuite/ld-scripts/section-order-1b.s b/ld/testsuite/ld-scripts/section-order-1b.s
new file mode 100644
index 00000000000..7fe103d0ea6
--- /dev/null
+++ b/ld/testsuite/ld-scripts/section-order-1b.s
@@ -0,0 +1,19 @@
+	.section .text.xxx
+	.globl	xxx
+xxx:
+	.dc.a 0
+
+	.section .text.yyy
+	.globl	yyy
+yyy:
+	.dc.a 0
+
+	.section .big
+	.global big
+big:
+	.dc.a 0
+
+	.section .baz
+	.global baz
+baz:
+	.dc.a 0
diff --git a/ld/testsuite/ld-scripts/section-order-1b.t b/ld/testsuite/ld-scripts/section-order-1b.t
new file mode 100644
index 00000000000..896653b2608
--- /dev/null
+++ b/ld/testsuite/ld-scripts/section-order-1b.t
@@ -0,0 +1,9 @@
+SECTIONS {
+  .text : {
+    *(.text.yyy)
+    *(.text.b?r)
+    *(*t)
+    *(.text.xxx)
+    *(.text.foo)
+  }
+}
diff --git a/ld/testsuite/ld-scripts/section-order-1c.d b/ld/testsuite/ld-scripts/section-order-1c.d
new file mode 100644
index 00000000000..65819cbcb63
--- /dev/null
+++ b/ld/testsuite/ld-scripts/section-order-1c.d
@@ -0,0 +1,13 @@
+#source: section-order-1b.s
+#source: section-order-1a.s
+#source: start.s
+#ld: --section-ordering-file section-order-1a.t
+#nm: -n
+
+#...
+[0-9a-f]+ D small
+#...
+[0-9a-f]+ D big
+#...
+[0-9a-f]+ D ba.*
+#pass
diff --git a/ld/testsuite/ld-scripts/section-order.exp b/ld/testsuite/ld-scripts/section-order.exp
new file mode 100644
index 00000000000..9b87e746cd1
--- /dev/null
+++ b/ld/testsuite/ld-scripts/section-order.exp
@@ -0,0 +1,45 @@
+# Test for --section-ordering-file FILE.
+# Copyright (C) 2024 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+# The --section-ordering-file option is only supported by ELF and
+# PE COFF linkers, which allow for arbitrarily named sections, eg:
+# .text.*
+if { !([is_elf_format] || [is_pecoff_format]) } {
+    return
+}
+
+set old_ldflags $LDFLAGS
+if { [istarget spu*-*-*] } then {
+    set LDFLAGS "$LDFLAGS --local-store 0:0 --no-overlays"
+} elseif { [is_pecoff_format] } then {
+    set LDFLAGS "$LDFLAGS --image-base 0"
+} elseif { [is_xcoff_format] } then {
+    set LDFLAGS "$LDFLAGS -bnogc"
+}
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/section-order*.d]]
+foreach test_file $test_list {
+    set test_name [file rootname $test_file]
+    set map_file "tmpdir/[file tail $test_name].map"
+    verbose $test_name
+    run_dump_test $test_name
+}
+
+set LDFLAGS $old_ldflags
diff --git a/ld/testsuite/ld-scripts/start.s b/ld/testsuite/ld-scripts/start.s
new file mode 100644
index 00000000000..3f646267716
--- /dev/null
+++ b/ld/testsuite/ld-scripts/start.s
@@ -0,0 +1,14 @@
+	.text
+	.global start	/* Used by SH targets.  */
+start:
+	.global _start
+_start:
+	.global __start
+__start:
+	.global _mainCRTStartup	/* Used by PE targets.  */
+_mainCRTStartup:
+	.global main	/* Used by HPPA targets.  */
+main:
+	.globl	_main	/* Used by LynxOS targets.  */
+_main:
+	.dc.a 0

-- 
Alan Modra

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: ld: Add --text-section-ordering-file (version 2)
  2024-04-29  0:12       ` Alan Modra
@ 2024-05-02 15:16         ` Nick Clifton
  2024-05-06 18:27         ` H.J. Lu
  2024-05-07 16:39         ` RFC: ld: Add --text-section-ordering-file (version 4) Nick Clifton
  2 siblings, 0 replies; 13+ messages in thread
From: Nick Clifton @ 2024-05-02 15:16 UTC (permalink / raw)
  To: Alan Modra; +Cc: hjl.tools, binutils, siddhesh

Hi Alan,

> The patch wasn't too far wrong.  I had some compile issues when plugin
> support was disabled, and it is probably a bad idea to allow creation
> of new output sections via --section-ordering-file, so that is now
> disallowed.

Thanks for creating this.  I am playing with it at the moment.

> I'm not putting forward this patch as a finished work, it's just a
> demonstrator.
> 
> What I'd like to see is:
> 1) Lose that horrible "INCLUDE section-ordering-file" requirement for
>     existing scripts.  Do you really want that put into every output
>     section in every script in scripttempl/?

No, and removing the need to do this is definitely a good thing.

> 2) Parse the section ordering file in ldgram.y.  An entry under file:
>     would be appropriate, like we do for version scripts.  That would
>     at least lose the SECTIONS clause required by my demonstrator
>     patch.  You wouldn't necessarily need to follow existing
>     specification of output and input sections, or to support other
>     things allowed in output sections, but I do think a syntax with an
>     explicit output section is a good idea.  ie. not one where the
>     output .text is deduced from the input .text.mumble.

Hmm, OK, I will look into this.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: ld: Add --text-section-ordering-file (version 2)
  2024-04-29  0:12       ` Alan Modra
  2024-05-02 15:16         ` Nick Clifton
@ 2024-05-06 18:27         ` H.J. Lu
  2024-05-07 16:39         ` RFC: ld: Add --text-section-ordering-file (version 4) Nick Clifton
  2 siblings, 0 replies; 13+ messages in thread
From: H.J. Lu @ 2024-05-06 18:27 UTC (permalink / raw)
  To: Alan Modra, Noah Goldstein; +Cc: Nick Clifton, binutils, siddhesh

On Sun, Apr 28, 2024 at 5:12 PM Alan Modra <amodra@gmail.com> wrote:
>
> On Fri, Apr 26, 2024 at 10:13:48PM +0930, Alan Modra wrote:
> > On Fri, Apr 26, 2024 at 10:59:00AM +0100, Nick Clifton wrote:
> > > It could be done, but I like keeping things simple.
> >
> > Here's a completely untested implementation of the idea I'm proposing,
> > written just to show that the linker modifications are relatively
> > small.  (There is a very good chance I've messed up list handling..)
> > What appears inside the --section-ordering-file output sections is
> > spliced in to corresponding output sections in the default script,
> > before the first input wild statement.
> >
> > I like keeping things simple too.  This should work without modifying
> > default linker scripts (and user scripts!), and allows all the usual
> > ways of specifying input sections.  That means you can use constructs
> > like EXCLUDE_FILE, SORT, KEEP, *(.text .rdata) vs. *(.text) *(.rdata)
> > and so on.
>
> The patch wasn't too far wrong.  I had some compile issues when plugin
> support was disabled, and it is probably a bad idea to allow creation
> of new output sections via --section-ordering-file, so that is now
> disallowed.
>
> I'm not putting forward this patch as a finished work, it's just a
> demonstrator.
>
> What I'd like to see is:
> 1) Lose that horrible "INCLUDE section-ordering-file" requirement for
>    existing scripts.  Do you really want that put into every output
>    section in every script in scripttempl/?
> 2) Parse the section ordering file in ldgram.y.  An entry under file:
>    would be appropriate, like we do for version scripts.  That would
>    at least lose the SECTIONS clause required by my demonstrator
>    patch.  You wouldn't necessarily need to follow existing
>    specification of output and input sections, or to support other
>    things allowed in output sections, but I do think a syntax with an
>    explicit output section is a good idea.  ie. not one where the
>    output .text is deduced from the input .text.mumble.
>
>
> diff --git a/ld/ld.h b/ld/ld.h
> index fcdd9a2c083..15d9dc262b6 100644
> --- a/ld/ld.h
> +++ b/ld/ld.h
> @@ -196,6 +196,8 @@ typedef struct
>
>    /* Default linker script.  */
>    char *default_script;
> +
> +  char *section_ordering_file;
>  } args_type;
>
>  extern args_type command_line;
> @@ -325,6 +327,7 @@ extern ld_config_type config;
>
>  extern FILE * saved_script_handle;
>  extern bool force_make_executable;
> +extern bool in_section_ordering;
>
>  extern int yyparse (void);
>  extern void add_cref (const char *, bfd *, asection *, bfd_vma);
> diff --git a/ld/ldlang.c b/ld/ldlang.c
> index 54d1af62ebe..6424d4764d1 100644
> --- a/ld/ldlang.c
> +++ b/ld/ldlang.c
> @@ -1299,6 +1299,7 @@ output_section_statement_newfunc (struct bfd_hash_entry *entry,
>    ret->s.output_section_statement.section_alignment = NULL;
>    ret->s.output_section_statement.block_value = 1;
>    lang_list_init (&ret->s.output_section_statement.children);
> +  lang_list_init (&ret->s.output_section_statement.sort_children);
>    lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next);
>
>    /* For every output section statement added to the list, except the
> @@ -7613,13 +7614,21 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
>    lang_output_section_statement_type *os;
>
>    os = lang_output_section_statement_lookup (output_section_statement_name,
> -                                            constraint, 2);
> +                                            constraint,
> +                                            in_section_ordering ? 0 : 2);
> +  if (os == NULL)
> +    einfo (_("%F%P:%pS: error: output section must already exist\n"), NULL);
>    current_section = os;
>
> +  /* Make next things chain into subchain of this.  */
> +  push_stat_ptr (in_section_ordering ? &os->sort_children : &os->children);
> +
> +  if (in_section_ordering)
> +    return os;
> +
>    if (os->addr_tree == NULL)
> -    {
> -      os->addr_tree = address_exp;
> -    }
> +    os->addr_tree = address_exp;
> +
>    os->sectype = sectype;
>    if (sectype == type_section || sectype == typed_readonly_section)
>      os->sectype_value = sectype_value;
> @@ -7629,9 +7638,6 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
>      os->flags = SEC_NO_FLAGS;
>    os->block_value = 1;
>
> -  /* Make next things chain into subchain of this.  */
> -  push_stat_ptr (&os->children);
> -
>    os->align_lma_with_input = align_with_input == ALIGN_WITH_INPUT;
>    if (os->align_lma_with_input && align != NULL)
>      einfo (_("%F%P:%pS: error: align with input and explicit align specified\n"),
> @@ -7971,21 +7977,6 @@ find_rescan_insertion (lang_input_statement_type *add)
>    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.)  */
> -
> -static void
> -lang_list_insert_after (lang_statement_list_type *destlist,
> -                       lang_statement_list_type *srclist,
> -                       lang_statement_union_type **field)
> -{
> -  *(srclist->tail) = *field;
> -  *field = srclist->head;
> -  if (destlist->tail == field)
> -    destlist->tail = srclist->tail;
> -}
> -
>  /* Detach new nodes added to DESTLIST since the time ORIGLIST
>     was taken as a copy of it and leave them in ORIGLIST.  */
>
> @@ -8033,6 +8024,21 @@ find_next_input_statement (lang_statement_union_type **s)
>  }
>  #endif /* BFD_SUPPORTS_PLUGINS */
>
> +/* 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.)  */
> +
> +static void
> +lang_list_insert_after (lang_statement_list_type *destlist,
> +                       lang_statement_list_type *srclist,
> +                       lang_statement_union_type **field)
> +{
> +  *(srclist->tail) = *field;
> +  *field = srclist->head;
> +  if (destlist->tail == field)
> +    destlist->tail = srclist->tail;
> +}
> +
>  /* Add NAME to the list of garbage collection entry points.  */
>
>  void
> @@ -8127,9 +8133,34 @@ reset_resolved_wilds (void)
>    lang_for_each_statement (reset_one_wild);
>  }
>
> +/* For each output section statement, splice any entries on the
> +   sort_children list before the first wild statement on the children
> +   list.  */
> +
> +static void
> +lang_os_merge_sort_children (void)
> +{
> +  lang_output_section_statement_type *os;
> +  for (os = (void *) lang_os_list.head; os != NULL; os = os->next)
> +    {
> +      if (os->sort_children.head != NULL)
> +       {
> +         lang_statement_union_type **where;
> +         for (where = &os->children.head;
> +              *where != NULL;
> +              where = &(*where)->header.next)
> +           if ((*where)->header.type == lang_wild_statement_enum)
> +             break;
> +         lang_list_insert_after (&os->children, &os->sort_children, where);
> +       }
> +    }
> +}
> +
>  void
>  lang_process (void)
>  {
> +  lang_os_merge_sort_children ();
> +
>    /* Finalize dynamic list.  */
>    if (link_info.dynamic_list)
>      lang_finalize_version_expr_head (&link_info.dynamic_list->head);
> @@ -8817,6 +8848,10 @@ lang_leave_output_section_statement (fill_type *fill, const char *memspec,
>                                      lang_output_section_phdr_list *phdrs,
>                                      const char *lma_memspec)
>  {
> +  pop_stat_ptr ();
> +  if (in_section_ordering)
> +    return;
> +
>    lang_get_regions (&current_section->region,
>                     &current_section->lma_region,
>                     memspec, lma_memspec,
> @@ -8825,7 +8860,6 @@ lang_leave_output_section_statement (fill_type *fill, const char *memspec,
>
>    current_section->fill = fill;
>    current_section->phdrs = phdrs;
> -  pop_stat_ptr ();
>  }
>
>  /* Set the output format type.  -oformat overrides scripts.  */
> diff --git a/ld/ldlang.h b/ld/ldlang.h
> index ea1c26d00f3..91947c56fda 100644
> --- a/ld/ldlang.h
> +++ b/ld/ldlang.h
> @@ -162,6 +162,8 @@ typedef struct lang_output_section_statement_struct
>
>    lang_output_section_phdr_list *phdrs;
>
> +  lang_statement_list_type sort_children;
> +
>    /* Used by ELF SHF_LINK_ORDER sorting.  */
>    void *data;
>
> diff --git a/ld/ldlex.h b/ld/ldlex.h
> index d575562a357..5708e6f5e34 100644
> --- a/ld/ldlex.h
> +++ b/ld/ldlex.h
> @@ -62,6 +62,7 @@ enum option_values
>    OPTION_SONAME,
>    OPTION_SORT_COMMON,
>    OPTION_SORT_SECTION,
> +  OPTION_SECTION_ORDERING_FILE,
>    OPTION_STATS,
>    OPTION_SYMBOLIC,
>    OPTION_SYMBOLIC_FUNCTIONS,
> diff --git a/ld/ldmain.c b/ld/ldmain.c
> index fe389681bd3..77b57a9fd32 100644
> --- a/ld/ldmain.c
> +++ b/ld/ldmain.c
> @@ -90,6 +90,8 @@ bool version_printed;
>  /* TRUE if we should demangle symbol names.  */
>  bool demangling;
>
> +bool in_section_ordering;
> +
>  args_type command_line;
>
>  ld_config_type config;
> @@ -446,6 +448,19 @@ main (int argc, char **argv)
>        info_msg ("\n==================================================\n");
>      }
>
> +  if (command_line.section_ordering_file)
> +    {
> +      FILE *hold_script_handle;
> +
> +      hold_script_handle = saved_script_handle;
> +      ldfile_open_command_file (command_line.section_ordering_file);
> +      saved_script_handle = hold_script_handle;
> +      in_section_ordering = true;
> +      parser_input = input_script;
> +      yyparse ();
> +      in_section_ordering = false;
> +    }
> +
>    if (command_line.force_group_allocation
>        || !bfd_link_relocatable (&link_info))
>      link_info.resolve_section_groups = true;
> diff --git a/ld/lexsup.c b/ld/lexsup.c
> index dad3b6059ed..0c337a4d170 100644
> --- a/ld/lexsup.c
> +++ b/ld/lexsup.c
> @@ -487,6 +487,9 @@ static const struct ld_option ld_options[] =
>    { {"sort-section", required_argument, NULL, OPTION_SORT_SECTION},
>      '\0', N_("name|alignment"),
>      N_("Sort sections by name or maximum alignment"), TWO_DASHES },
> +  { {"section-ordering-file", required_argument, NULL, OPTION_SECTION_ORDERING_FILE},
> +    '\0', N_("FILE"),
> +    N_("Sort sections by statements in FILE"), TWO_DASHES },
>    { {"spare-dynamic-tags", required_argument, NULL, OPTION_SPARE_DYNAMIC_TAGS},
>      '\0', N_("COUNT"), N_("How many tags to reserve in .dynamic section"),
>      TWO_DASHES },
> @@ -1400,6 +1403,9 @@ parse_args (unsigned argc, char **argv)
>             einfo (_("%F%P: invalid section sorting option: %s\n"),
>                    optarg);
>           break;
> +       case OPTION_SECTION_ORDERING_FILE:
> +         command_line.section_ordering_file = optarg;
> +         break;
>         case OPTION_STATS:
>           config.stats = true;
>           break;
> diff --git a/ld/testsuite/ld-scripts/section-order-1a.d b/ld/testsuite/ld-scripts/section-order-1a.d
> new file mode 100644
> index 00000000000..03d848b83ea
> --- /dev/null
> +++ b/ld/testsuite/ld-scripts/section-order-1a.d
> @@ -0,0 +1,17 @@
> +#source: section-order-1b.s
> +#source: section-order-1a.s
> +#source: start.s
> +#ld: --section-ordering-file section-order-1a.t
> +#nm: -n
> +
> +#...
> +[0-9a-f]+ T yyy
> +#...
> +[0-9a-f]+ T bar
> +#...
> +[0-9a-f]+ T [_]+start
> +#...
> +[0-9a-f]+ T xxx
> +#...
> +[0-9a-f]+ T foo
> +#pass
> diff --git a/ld/testsuite/ld-scripts/section-order-1a.s b/ld/testsuite/ld-scripts/section-order-1a.s
> new file mode 100644
> index 00000000000..17d311fd58f
> --- /dev/null
> +++ b/ld/testsuite/ld-scripts/section-order-1a.s
> @@ -0,0 +1,19 @@
> +       .section .text.foo
> +       .globl  foo
> +foo:
> +       .dc.a 0
> +
> +       .section .text.bar
> +       .globl  bar
> +bar:
> +       .dc.a 0
> +
> +       .section .data.small
> +       .globl small
> +small:
> +       .dc.a 0
> +
> +       .section .bar
> +       .global bar
> +bart:
> +       .dc.a 0
> diff --git a/ld/testsuite/ld-scripts/section-order-1a.t b/ld/testsuite/ld-scripts/section-order-1a.t
> new file mode 100644
> index 00000000000..e3786818fea
> --- /dev/null
> +++ b/ld/testsuite/ld-scripts/section-order-1a.t
> @@ -0,0 +1,15 @@
> +SECTIONS
> +{
> +  .text : {
> +    *(.text.yyy)
> +    *(.text.b?r)
> +    *(.text)
> +    *(.text.xxx .text.foo)
> +  }
> +
> +  .data : {
> +    *(.data.small)
> +    *(.big*)
> +    *(.bar .baz*)
> +  }
> +}
> diff --git a/ld/testsuite/ld-scripts/section-order-1b.d b/ld/testsuite/ld-scripts/section-order-1b.d
> new file mode 100644
> index 00000000000..41b4d16097e
> --- /dev/null
> +++ b/ld/testsuite/ld-scripts/section-order-1b.d
> @@ -0,0 +1,17 @@
> +#source: section-order-1a.s
> +#source: section-order-1b.s
> +#source: start.s
> +#ld: --section-ordering-file section-order-1b.t
> +#nm: -n
> +
> +#...
> +[0-9a-f]+ T yyy
> +#...
> +[0-9a-f]+ T bar
> +#...
> +[0-9a-f]+ T [_]+start
> +#...
> +[0-9a-f]+ T xxx
> +#...
> +[0-9a-f]+ T foo
> +#pass
> diff --git a/ld/testsuite/ld-scripts/section-order-1b.s b/ld/testsuite/ld-scripts/section-order-1b.s
> new file mode 100644
> index 00000000000..7fe103d0ea6
> --- /dev/null
> +++ b/ld/testsuite/ld-scripts/section-order-1b.s
> @@ -0,0 +1,19 @@
> +       .section .text.xxx
> +       .globl  xxx
> +xxx:
> +       .dc.a 0
> +
> +       .section .text.yyy
> +       .globl  yyy
> +yyy:
> +       .dc.a 0
> +
> +       .section .big
> +       .global big
> +big:
> +       .dc.a 0
> +
> +       .section .baz
> +       .global baz
> +baz:
> +       .dc.a 0
> diff --git a/ld/testsuite/ld-scripts/section-order-1b.t b/ld/testsuite/ld-scripts/section-order-1b.t
> new file mode 100644
> index 00000000000..896653b2608
> --- /dev/null
> +++ b/ld/testsuite/ld-scripts/section-order-1b.t
> @@ -0,0 +1,9 @@
> +SECTIONS {
> +  .text : {
> +    *(.text.yyy)
> +    *(.text.b?r)
> +    *(*t)
> +    *(.text.xxx)
> +    *(.text.foo)
> +  }
> +}
> diff --git a/ld/testsuite/ld-scripts/section-order-1c.d b/ld/testsuite/ld-scripts/section-order-1c.d
> new file mode 100644
> index 00000000000..65819cbcb63
> --- /dev/null
> +++ b/ld/testsuite/ld-scripts/section-order-1c.d
> @@ -0,0 +1,13 @@
> +#source: section-order-1b.s
> +#source: section-order-1a.s
> +#source: start.s
> +#ld: --section-ordering-file section-order-1a.t
> +#nm: -n
> +
> +#...
> +[0-9a-f]+ D small
> +#...
> +[0-9a-f]+ D big
> +#...
> +[0-9a-f]+ D ba.*
> +#pass
> diff --git a/ld/testsuite/ld-scripts/section-order.exp b/ld/testsuite/ld-scripts/section-order.exp
> new file mode 100644
> index 00000000000..9b87e746cd1
> --- /dev/null
> +++ b/ld/testsuite/ld-scripts/section-order.exp
> @@ -0,0 +1,45 @@
> +# Test for --section-ordering-file FILE.
> +# Copyright (C) 2024 Free Software Foundation, Inc.
> +#
> +# This file is part of the GNU Binutils.
> +#
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
> +# MA 02110-1301, USA.
> +
> +# The --section-ordering-file option is only supported by ELF and
> +# PE COFF linkers, which allow for arbitrarily named sections, eg:
> +# .text.*
> +if { !([is_elf_format] || [is_pecoff_format]) } {
> +    return
> +}
> +
> +set old_ldflags $LDFLAGS
> +if { [istarget spu*-*-*] } then {
> +    set LDFLAGS "$LDFLAGS --local-store 0:0 --no-overlays"
> +} elseif { [is_pecoff_format] } then {
> +    set LDFLAGS "$LDFLAGS --image-base 0"
> +} elseif { [is_xcoff_format] } then {
> +    set LDFLAGS "$LDFLAGS -bnogc"
> +}
> +
> +set test_list [lsort [glob -nocomplain $srcdir/$subdir/section-order*.d]]
> +foreach test_file $test_list {
> +    set test_name [file rootname $test_file]
> +    set map_file "tmpdir/[file tail $test_name].map"
> +    verbose $test_name
> +    run_dump_test $test_name
> +}
> +
> +set LDFLAGS $old_ldflags
> diff --git a/ld/testsuite/ld-scripts/start.s b/ld/testsuite/ld-scripts/start.s
> new file mode 100644
> index 00000000000..3f646267716
> --- /dev/null
> +++ b/ld/testsuite/ld-scripts/start.s
> @@ -0,0 +1,14 @@
> +       .text
> +       .global start   /* Used by SH targets.  */
> +start:
> +       .global _start
> +_start:
> +       .global __start
> +__start:
> +       .global _mainCRTStartup /* Used by PE targets.  */
> +_mainCRTStartup:
> +       .global main    /* Used by HPPA targets.  */
> +main:
> +       .globl  _main   /* Used by LynxOS targets.  */
> +_main:
> +       .dc.a 0
>
> --
> Alan Modra

Noah is also working on something similar.

-- 
H.J.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: RFC: ld: Add --text-section-ordering-file (version 4)
  2024-04-29  0:12       ` Alan Modra
  2024-05-02 15:16         ` Nick Clifton
  2024-05-06 18:27         ` H.J. Lu
@ 2024-05-07 16:39         ` Nick Clifton
  2 siblings, 0 replies; 13+ messages in thread
From: Nick Clifton @ 2024-05-07 16:39 UTC (permalink / raw)
  To: Binutils; +Cc: hjl.tools, siddhesh

[-- Attachment #1: Type: text/plain, Size: 517 bytes --]

Hi Guys,

   So here is an augmented version of Alan's patch.  All that
   it does is to add some documentation and enhance one of the
   tests so that it checks ordering the .data section as well
   as the .text section.

   Any comments ?

   If there is nothing too seriously wrong with it, I would like
   to check the patch in so that we can start testing it in the
   real world.  We can always augment or change it later on, but
   it would be nice to have something that people can play with.

Cheers
   Nick

[-- Attachment #2: section-ordering-file.patch.4 --]
[-- Type: application/x-troff-man, Size: 21073 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2024-05-07 16:40 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-25 13:01 RFC: ld: Add --text-section-ordering-file (version 2) Nick Clifton
2024-04-25 15:32 ` H.J. Lu
2024-04-26  9:38   ` Nick Clifton
2024-04-26  1:46 ` Hans-Peter Nilsson
2024-04-26  9:46   ` Nick Clifton
2024-04-27  0:46     ` Hans-Peter Nilsson
2024-04-26  4:17 ` Alan Modra
2024-04-26  9:59   ` Nick Clifton
2024-04-26 12:43     ` Alan Modra
2024-04-29  0:12       ` Alan Modra
2024-05-02 15:16         ` Nick Clifton
2024-05-06 18:27         ` H.J. Lu
2024-05-07 16:39         ` RFC: ld: Add --text-section-ordering-file (version 4) Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).