aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2023-11-01 13:51:17 +0000
committerNick Clifton <nickc@redhat.com>2023-11-01 13:51:17 +0000
commit85921e9a2588bf4820b827fc1630f5d7da22cb1c (patch)
treefb6aeb7e8af93f947d5930d90cfcc3e41812e4d7 /ld
parentf514e6e48061661cacfc980cd5272fd99887d38b (diff)
downloadgdb-85921e9a2588bf4820b827fc1630f5d7da22cb1c.zip
gdb-85921e9a2588bf4820b827fc1630f5d7da22cb1c.tar.gz
gdb-85921e9a2588bf4820b827fc1630f5d7da22cb1c.tar.bz2
ld: Support input section description keyword: REVERSE
PR 27565 * ldlex.l: Add REVERSE. * ldgram.y: Allow REVERSE to be used wherever a sorting command can be used. * ld.h (struct wildcard_spec): Add 'reversed' field. * ldlang.h (lang_wild_statement_struct): Add 'filenames_reversed' field. * ldlang.c (compare_sections): Add reversed parameter. (wild_sort): Reverse the comparison if requested. (print_wild_statement): Handle the reversed field. * ld.texi: Document the new feature. * NEWS: Mention the new feature. * testsuite/ld-scripts/sort-file-reversed-1.d: New test driver. * testsuite/ld-scripts/sort-file-reversed-1.t: New test source. * testsuite/ld-scripts/sort-file-reversed-2.t: New test source. * testsuite/ld-scripts/sort-file-reversed-2.d: New test driver. * testsuite/ld-scripts/sort-sections-reversed-1.d: New test driver. * testsuite/ld-scripts/sort-sections-reversed-1.t: New test source. * testsuite/ld-scripts/sort-sections-reversed-2.t: New test source. * testsuite/ld-scripts/sort-sections-reversed-2.d: New test driver. * testsuite/ld-scripts/sort-sections-reversed-3.d: New test driver. * testsuite/ld-scripts/sort-sections-reversed-3.t: New test source.
Diffstat (limited to 'ld')
-rw-r--r--ld/ChangeLog24
-rw-r--r--ld/NEWS4
-rw-r--r--ld/ld.h13
-rw-r--r--ld/ld.texi38
-rw-r--r--ld/ldgram.y59
-rw-r--r--ld/ldlang.c44
-rw-r--r--ld/ldlang.h25
-rw-r--r--ld/ldlex.l1
-rw-r--r--ld/testsuite/ld-scripts/sort-file-reversed-1.d18
-rw-r--r--ld/testsuite/ld-scripts/sort-file-reversed-1.t6
-rw-r--r--ld/testsuite/ld-scripts/sort-file-reversed-2.d19
-rw-r--r--ld/testsuite/ld-scripts/sort-file-reversed-2.t6
-rw-r--r--ld/testsuite/ld-scripts/sort-sections-reversed-1.d13
-rw-r--r--ld/testsuite/ld-scripts/sort-sections-reversed-1.t5
-rw-r--r--ld/testsuite/ld-scripts/sort-sections-reversed-2.d13
-rw-r--r--ld/testsuite/ld-scripts/sort-sections-reversed-2.t5
-rw-r--r--ld/testsuite/ld-scripts/sort-sections-reversed-3.d15
-rw-r--r--ld/testsuite/ld-scripts/sort-sections-reversed-3.t5
18 files changed, 274 insertions, 39 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 49c73eb..95f4712 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,27 @@
+2023-11-01 Nick Clifton <nickc@redhat.com>
+
+ PR 27565
+ * ldlex.l: Add REVERSE.
+ * ldgram.y: Allow REVERSE to be used wherever a sorting command
+ can be used.
+ * ld.h (struct wildcard_spec): Add 'reversed' field.
+ * ldlang.h (lang_wild_statement_struct): Add 'filenames_reversed' field.
+ * ldlang.c (compare_sections): Add reversed parameter.
+ (wild_sort): Reverse the comparison if requested.
+ (print_wild_statement): Handle the reversed field.
+ * ld.texi: Document the new feature.
+ * NEWS: Mention the new feature.
+ * testsuite/ld-scripts/sort-file-reversed-1.d: New test driver.
+ * testsuite/ld-scripts/sort-file-reversed-1.t: New test source.
+ * testsuite/ld-scripts/sort-file-reversed-2.t: New test source.
+ * testsuite/ld-scripts/sort-file-reversed-2.d: New test driver.
+ * testsuite/ld-scripts/sort-sections-reversed-1.d: New test driver.
+ * testsuite/ld-scripts/sort-sections-reversed-1.t: New test source.
+ * testsuite/ld-scripts/sort-sections-reversed-2.t: New test source.
+ * testsuite/ld-scripts/sort-sections-reversed-2.d: New test driver.
+ * testsuite/ld-scripts/sort-sections-reversed-3.d: New test driver.
+ * testsuite/ld-scripts/sort-sections-reversed-3.t: New test source.
+
2023-10-30 Nick Clifton <nickc@redhat.com>
* po/ka.po: New Georgian translation.
diff --git a/ld/NEWS b/ld/NEWS
index 4b990c7..e696bba 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -12,6 +12,10 @@ Changes in 2.41:
* The linker command line option --print-map-locals can be used to include
local symbols in a linker map. (ELF targets only).
+* A new linker script sorting directive has been added: REVERSE. This reverses
+ the order of the sorting. It be combined with either SORT_BY_INIT_PRIORITY
+ or SORT_BY_NAME.
+
* For most ELF based targets, if the --enable-linker-version option is used
then the version of the linker will be inserted as a string into the .comment
section.
diff --git a/ld/ld.h b/ld/ld.h
index a0f8a15..f51add3 100644
--- a/ld/ld.h
+++ b/ld/ld.h
@@ -96,11 +96,14 @@ extern sort_type sort_section;
struct wildcard_spec
{
- const char *name;
- struct name_list *exclude_name_list;
- struct flag_info *section_flag_list;
- size_t namelen, prefixlen, suffixlen;
- sort_type sorted;
+ const char * name;
+ struct name_list * exclude_name_list;
+ struct flag_info * section_flag_list;
+ size_t namelen;
+ size_t prefixlen;
+ size_t suffixlen;
+ sort_type sorted;
+ bool reversed;
};
struct wildcard_list
diff --git a/ld/ld.texi b/ld/ld.texi
index 1f56ded..7ae01b1 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -5263,6 +5263,35 @@ the init_priority. In @code{.ctors.NNNNN} and @code{.dtors.NNNNN},
@cindex SORT
@code{SORT} is an alias for @code{SORT_BY_NAME}.
+@cindex REVERSE
+@code{REVERSE} indicates that the sorting should be reversed. If used
+on its own then @code{REVERSE} implies @code{SORT_BY_NAME}, otherwise
+it reverses the enclosed @code{SORT..} command. Note - reverse
+sorting of alignment is not currently supported.
+
+Note - the sorting commands only accept a single wildcard pattern. So
+for example the following will not work:
+@smallexample
+ *(REVERSE(.text* .init*))
+@end smallexample
+To resolve this problem list the patterns individually, like this:
+@smallexample
+ *(REVERSE(.text*))
+ *(REVERSE(.init*))
+@end smallexample
+
+Note - you can put the @code{EXCLUDE_FILE} command inside a sorting
+command, but not the other way around. So for example:
+@smallexample
+ *(SORT_BY_NAME(EXCLUDE_FILE(foo) .text*))
+@end smallexample
+will work, but:
+@smallexample
+ *(EXCLUDE_FILE(foo) SORT_BY_NAME(.text*))
+@end smallexample
+will not.
+
+
When there are nested section sorting commands in linker script, there
can be at most 1 level of nesting for section sorting commands.
@@ -5282,6 +5311,15 @@ treated the same as @code{SORT_BY_NAME} (wildcard section pattern).
@code{SORT_BY_ALIGNMENT} (@code{SORT_BY_ALIGNMENT} (wildcard section pattern))
is treated the same as @code{SORT_BY_ALIGNMENT} (wildcard section pattern).
@item
+@code{SORT_BY_NAME} (@code{REVERSE} (wildcard section pattern))
+reverse sorts by name.
+@item
+@code{REVERSE} (@code{SORT_BY_NAME} (wildcard section pattern))
+reverse sorts by name.
+@item
+@code{SORT_BY_INIT_PRIORITY} (@code{REVERSE} (wildcard section pattern))
+reverse sorts by init priority.
+@item
All other nested section sorting commands are invalid.
@end enumerate
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 2b4b507..7b7ae8a 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -102,7 +102,7 @@ static void yyerror (const char *);
%type <flag_info> sect_flags
%type <name> memspec_opt memspec_at_opt paren_script_name casesymlist
%type <cname> wildcard_name
-%type <wildcard> section_name_spec filename_spec wildcard_maybe_exclude
+%type <wildcard> section_name_spec filename_spec wildcard_maybe_exclude wildcard_maybe_reverse
%token <bigint> INT
%token <name> NAME LNAME
%type <integer> length
@@ -132,7 +132,7 @@ static void yyerror (const char *);
%token SECTIONS PHDRS INSERT_K AFTER BEFORE LINKER_VERSION
%token DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END DATA_SEGMENT_END
%token SORT_BY_NAME SORT_BY_ALIGNMENT SORT_NONE
-%token SORT_BY_INIT_PRIORITY
+%token SORT_BY_INIT_PRIORITY REVERSE
%token '{' '}'
%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
%token INHIBIT_COMMON_ALLOCATION FORCE_GROUP_ALLOCATION
@@ -440,6 +440,7 @@ wildcard_maybe_exclude:
$$.sorted = none;
$$.exclude_name_list = NULL;
$$.section_flag_list = NULL;
+ $$.reversed = false;
}
| EXCLUDE_FILE '(' exclude_name_list ')' wildcard_name
{
@@ -447,65 +448,95 @@ wildcard_maybe_exclude:
$$.sorted = none;
$$.exclude_name_list = $3;
$$.section_flag_list = NULL;
+ $$.reversed = false;
}
;
-filename_spec:
+wildcard_maybe_reverse:
wildcard_maybe_exclude
- | SORT_BY_NAME '(' wildcard_maybe_exclude ')'
+ | REVERSE '(' wildcard_maybe_exclude ')'
{
$$ = $3;
+ $$.reversed = true;
$$.sorted = by_name;
}
- | SORT_NONE '(' wildcard_maybe_exclude ')'
+ ;
+
+filename_spec:
+ wildcard_maybe_reverse
+ | SORT_BY_NAME '(' wildcard_maybe_reverse ')'
+ {
+ $$ = $3;
+ $$.sorted = by_name;
+ }
+ | SORT_NONE '(' wildcard_maybe_reverse ')'
{
$$ = $3;
$$.sorted = by_none;
+ $$.reversed = false;
+ }
+ | REVERSE '(' SORT_BY_NAME '(' wildcard_maybe_exclude ')' ')'
+ {
+ $$ = $5;
+ $$.sorted = by_name;
+ $$.reversed = true;
}
;
section_name_spec:
- wildcard_maybe_exclude
- | SORT_BY_NAME '(' wildcard_maybe_exclude ')'
+ wildcard_maybe_reverse
+ | SORT_BY_NAME '(' wildcard_maybe_reverse ')'
{
$$ = $3;
$$.sorted = by_name;
}
- | SORT_BY_ALIGNMENT '(' wildcard_maybe_exclude ')'
+ | SORT_BY_ALIGNMENT '(' wildcard_maybe_reverse ')'
{
$$ = $3;
$$.sorted = by_alignment;
}
- | SORT_NONE '(' wildcard_maybe_exclude ')'
+ | SORT_NONE '(' wildcard_maybe_reverse ')'
{
$$ = $3;
$$.sorted = by_none;
}
- | SORT_BY_NAME '(' SORT_BY_ALIGNMENT '(' wildcard_maybe_exclude ')' ')'
+ | SORT_BY_NAME '(' SORT_BY_ALIGNMENT '(' wildcard_maybe_reverse ')' ')'
{
$$ = $5;
$$.sorted = by_name_alignment;
}
- | SORT_BY_NAME '(' SORT_BY_NAME '(' wildcard_maybe_exclude ')' ')'
+ | SORT_BY_NAME '(' SORT_BY_NAME '(' wildcard_maybe_reverse ')' ')'
{
$$ = $5;
$$.sorted = by_name;
}
- | SORT_BY_ALIGNMENT '(' SORT_BY_NAME '(' wildcard_maybe_exclude ')' ')'
+ | SORT_BY_ALIGNMENT '(' SORT_BY_NAME '(' wildcard_maybe_reverse ')' ')'
{
$$ = $5;
$$.sorted = by_alignment_name;
}
- | SORT_BY_ALIGNMENT '(' SORT_BY_ALIGNMENT '(' wildcard_maybe_exclude ')' ')'
+ | SORT_BY_ALIGNMENT '(' SORT_BY_ALIGNMENT '(' wildcard_maybe_reverse ')' ')'
{
$$ = $5;
$$.sorted = by_alignment;
}
- | SORT_BY_INIT_PRIORITY '(' wildcard_maybe_exclude ')'
+ | SORT_BY_INIT_PRIORITY '(' wildcard_maybe_reverse ')'
{
$$ = $3;
$$.sorted = by_init_priority;
}
+ | REVERSE '(' SORT_BY_NAME '(' wildcard_maybe_exclude ')' ')'
+ {
+ $$ = $5;
+ $$.sorted = by_name;
+ $$.reversed = true;
+ }
+ | REVERSE '(' SORT_BY_INIT_PRIORITY '(' wildcard_maybe_exclude ')' ')'
+ {
+ $$ = $5;
+ $$.sorted = by_init_priority;
+ $$.reversed = true;
+ }
;
sect_flag_list: NAME
diff --git a/ld/ldlang.c b/ld/ldlang.c
index c20247a..566c2b8 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -539,7 +539,7 @@ get_init_priority (const asection *sec)
/* Compare sections ASEC and BSEC according to SORT. */
static int
-compare_section (sort_type sort, asection *asec, asection *bsec)
+compare_section (sort_type sort, asection *asec, asection *bsec, bool reversed)
{
int ret;
int a_priority, b_priority;
@@ -554,7 +554,10 @@ compare_section (sort_type sort, asection *asec, asection *bsec)
b_priority = get_init_priority (bsec);
if (a_priority < 0 || b_priority < 0)
goto sort_by_name;
- ret = a_priority - b_priority;
+ if (reversed)
+ ret = b_priority - a_priority;
+ else
+ ret = a_priority - b_priority;
if (ret)
break;
else
@@ -568,11 +571,17 @@ compare_section (sort_type sort, asection *asec, asection *bsec)
case by_name:
sort_by_name:
- ret = strcmp (bfd_section_name (asec), bfd_section_name (bsec));
+ if (reversed)
+ ret = strcmp (bfd_section_name (bsec), bfd_section_name (asec));
+ else
+ ret = strcmp (bfd_section_name (asec), bfd_section_name (bsec));
break;
case by_name_alignment:
- ret = strcmp (bfd_section_name (asec), bfd_section_name (bsec));
+ if (reversed)
+ ret = strcmp (bfd_section_name (bsec), bfd_section_name (asec));
+ else
+ ret = strcmp (bfd_section_name (asec), bfd_section_name (bsec));
if (ret)
break;
/* Fall through. */
@@ -647,7 +656,11 @@ wild_sort (lang_wild_statement_type *wild,
else
ln = sort_filename (lsec->owner);
- i = filename_cmp (fn, ln);
+ if (wild->filenames_reversed)
+ i = filename_cmp (ln, fn);
+ else
+ i = filename_cmp (fn, ln);
+
if (i > 0)
{ tree = &((*tree)->right); continue; }
else if (i < 0)
@@ -660,7 +673,11 @@ wild_sort (lang_wild_statement_type *wild,
if (la)
ln = sort_filename (lsec->owner);
- i = filename_cmp (fn, ln);
+ if (wild->filenames_reversed)
+ i = filename_cmp (ln, fn);
+ else
+ i = filename_cmp (fn, ln);
+
if (i > 0)
{ tree = &((*tree)->right); continue; }
else if (i < 0)
@@ -673,7 +690,7 @@ wild_sort (lang_wild_statement_type *wild,
/* Find the correct node to append this section. */
if (sec && sec->spec.sorted != none && sec->spec.sorted != by_none
- && compare_section (sec->spec.sorted, section, (*tree)->section) < 0)
+ && compare_section (sec->spec.sorted, section, (*tree)->section, sec->spec.reversed) < 0)
tree = &((*tree)->left);
else
tree = &((*tree)->right);
@@ -5151,10 +5168,14 @@ print_wild_statement (lang_wild_statement_type *w,
if (w->filenames_sorted)
minfo ("SORT_BY_NAME(");
+ if (w->filenames_reversed)
+ minfo ("REVERSE(");
if (w->filename != NULL)
minfo ("%s", w->filename);
else
minfo ("*");
+ if (w->filenames_reversed)
+ minfo (")");
if (w->filenames_sorted)
minfo (")");
@@ -5199,6 +5220,12 @@ print_wild_statement (lang_wild_statement_type *w,
break;
}
+ if (sec->spec.reversed)
+ {
+ minfo ("REVERSE(");
+ closing_paren++;
+ }
+
if (sec->spec.exclude_name_list != NULL)
{
name_list *tmp;
@@ -8500,9 +8527,10 @@ lang_add_wild (struct wildcard_spec *filespec,
if (filespec != NULL)
{
new_stmt->filename = filespec->name;
- new_stmt->filenames_sorted = filespec->sorted == by_name;
+ new_stmt->filenames_sorted = (filespec->sorted == by_name || filespec->reversed);
new_stmt->section_flag_list = filespec->section_flag_list;
new_stmt->exclude_name_list = filespec->exclude_name_list;
+ new_stmt->filenames_reversed = filespec->reversed;
}
new_stmt->section_list = section_list;
new_stmt->keep_sections = keep_sections;
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 463cce3..63749ea 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -390,18 +390,19 @@ typedef struct lang_section_bst
struct lang_wild_statement_struct
{
- lang_statement_header_type header;
- const char *filename;
- bool filenames_sorted;
- bool any_specs_sorted;
- struct wildcard_list *section_list;
- bool keep_sections;
- lang_statement_list_type children;
- struct name_list *exclude_name_list;
- lang_statement_list_type matching_sections;
-
- lang_section_bst_type *tree, **rightmost;
- struct flag_info *section_flag_list;
+ lang_statement_header_type header;
+ lang_statement_list_type children;
+ lang_statement_list_type matching_sections;
+ lang_section_bst_type * tree;
+ lang_section_bst_type ** rightmost;
+ struct wildcard_list * section_list;
+ struct name_list * exclude_name_list;
+ struct flag_info * section_flag_list;
+ const char * filename;
+ bool filenames_sorted;
+ bool filenames_reversed;
+ bool any_specs_sorted;
+ bool keep_sections;
};
typedef struct lang_address_statement_struct
diff --git a/ld/ldlex.l b/ld/ldlex.l
index 94b2ea7..101f527 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -322,6 +322,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
<WILD>"SORT" { RTOKEN(SORT_BY_NAME); }
<WILD>"SORT_BY_INIT_PRIORITY" { RTOKEN(SORT_BY_INIT_PRIORITY); }
<WILD>"SORT_NONE" { RTOKEN(SORT_NONE); }
+<WILD>"REVERSE" { RTOKEN(REVERSE); }
<EXPRESSION>"NOLOAD" { RTOKEN(NOLOAD); }
<EXPRESSION>"READONLY" { RTOKEN(READONLY); }
<EXPRESSION>"DSECT" { RTOKEN(DSECT); }
diff --git a/ld/testsuite/ld-scripts/sort-file-reversed-1.d b/ld/testsuite/ld-scripts/sort-file-reversed-1.d
new file mode 100644
index 0000000..d1d56bd
--- /dev/null
+++ b/ld/testsuite/ld-scripts/sort-file-reversed-1.d
@@ -0,0 +1,18 @@
+#source: sort-file1.s
+#source: sort-file2.s
+#ld: -T sort-file-reversed-1.t --no-warn-rwx-segments
+#nm: -n
+
+# Check that SORT_BY_NAME+REVERSE on filenames works.
+# The text sections should come in reversed sorted order, the data
+# sections in input order. Note how we specifically pass
+# the object filenames in alphabetical order
+#...
+0[0-9a-f]* t infile2
+#...
+0[0-9a-f]* t infile1
+#...
+0[0-9a-f]* d data1
+#...
+0[0-9a-f]* d data2
+#pass
diff --git a/ld/testsuite/ld-scripts/sort-file-reversed-1.t b/ld/testsuite/ld-scripts/sort-file-reversed-1.t
new file mode 100644
index 0000000..dd177d3
--- /dev/null
+++ b/ld/testsuite/ld-scripts/sort-file-reversed-1.t
@@ -0,0 +1,6 @@
+SECTIONS
+{
+ .text : { SORT_BY_NAME(REVERSE(*))(.text*) }
+ .data : { *(.data*) }
+ /DISCARD/ : { *(.*) }
+}
diff --git a/ld/testsuite/ld-scripts/sort-file-reversed-2.d b/ld/testsuite/ld-scripts/sort-file-reversed-2.d
new file mode 100644
index 0000000..3e829f2
--- /dev/null
+++ b/ld/testsuite/ld-scripts/sort-file-reversed-2.d
@@ -0,0 +1,19 @@
+#source: sort-file1.s
+#source: sort-file2.s
+#ld: -T sort-file-reversed-2.t --no-warn-rwx-segments
+#nm: -n
+
+# Check that REVERSE+SORT_BY_NAME on filenames works.
+# Also check that REVERSE implies SORT_BY_NAME.
+# The text sections should come in reversed sorted order, the data
+# sections in reversed order too. Note how we specifically pass
+# the object filenames in alphabetical order
+#...
+0[0-9a-f]* t infile2
+#...
+0[0-9a-f]* t infile1
+#...
+0[0-9a-f]* d data2
+#...
+0[0-9a-f]* d data1
+#pass
diff --git a/ld/testsuite/ld-scripts/sort-file-reversed-2.t b/ld/testsuite/ld-scripts/sort-file-reversed-2.t
new file mode 100644
index 0000000..1379852
--- /dev/null
+++ b/ld/testsuite/ld-scripts/sort-file-reversed-2.t
@@ -0,0 +1,6 @@
+SECTIONS
+{
+ .text : { REVERSE(SORT_BY_NAME(*))(.text*) }
+ .data : { REVERSE(*)(.data*) }
+ /DISCARD/ : { *(.*) }
+}
diff --git a/ld/testsuite/ld-scripts/sort-sections-reversed-1.d b/ld/testsuite/ld-scripts/sort-sections-reversed-1.d
new file mode 100644
index 0000000..57f88e5
--- /dev/null
+++ b/ld/testsuite/ld-scripts/sort-sections-reversed-1.d
@@ -0,0 +1,13 @@
+#source: sort_b_a.s
+#ld: -T sort-sections-reversed-1.t --no-warn-rwx-segments
+#nm: -n
+
+#...
+0[0-9a-f]* t text3
+#...
+0[0-9a-f]* t text2
+#...
+0[0-9a-f]* t text1
+#...
+0[0-9a-f]* t text
+#pass
diff --git a/ld/testsuite/ld-scripts/sort-sections-reversed-1.t b/ld/testsuite/ld-scripts/sort-sections-reversed-1.t
new file mode 100644
index 0000000..cc7f85e
--- /dev/null
+++ b/ld/testsuite/ld-scripts/sort-sections-reversed-1.t
@@ -0,0 +1,5 @@
+SECTIONS
+{
+ .text : { *(SORT_BY_NAME(REVERSE(.text*))) }
+ /DISCARD/ : { *(.*) }
+}
diff --git a/ld/testsuite/ld-scripts/sort-sections-reversed-2.d b/ld/testsuite/ld-scripts/sort-sections-reversed-2.d
new file mode 100644
index 0000000..1eaa479
--- /dev/null
+++ b/ld/testsuite/ld-scripts/sort-sections-reversed-2.d
@@ -0,0 +1,13 @@
+#source: sort_b_a.s
+#ld: -T sort-sections-reversed-2.t --no-warn-rwx-segments
+#nm: -n
+
+#...
+0[0-9a-f]* t text3
+#...
+0[0-9a-f]* t text2
+#...
+0[0-9a-f]* t text1
+#...
+0[0-9a-f]* t text
+#pass
diff --git a/ld/testsuite/ld-scripts/sort-sections-reversed-2.t b/ld/testsuite/ld-scripts/sort-sections-reversed-2.t
new file mode 100644
index 0000000..3fa082e
--- /dev/null
+++ b/ld/testsuite/ld-scripts/sort-sections-reversed-2.t
@@ -0,0 +1,5 @@
+SECTIONS
+{
+ .text : { *(REVERSE(SORT_BY_INIT_PRIORITY(.text*))) }
+ /DISCARD/ : { *(REVERSE(.*)) }
+}
diff --git a/ld/testsuite/ld-scripts/sort-sections-reversed-3.d b/ld/testsuite/ld-scripts/sort-sections-reversed-3.d
new file mode 100644
index 0000000..e7f244c
--- /dev/null
+++ b/ld/testsuite/ld-scripts/sort-sections-reversed-3.d
@@ -0,0 +1,15 @@
+#source: sort_b_a.s
+#ld: -T sort-sections-reversed-3.t --no-warn-rwx-segments
+#nm: -n
+
+# Check that REVERSE implies SORT_BY_NAME for sections.
+# Also check that EXCLUDE_FILE() is supported inside REVERSE.
+#...
+0[0-9a-f]* t text3
+#...
+0[0-9a-f]* t text2
+#...
+0[0-9a-f]* t text1
+#...
+0[0-9a-f]* t text
+#pass
diff --git a/ld/testsuite/ld-scripts/sort-sections-reversed-3.t b/ld/testsuite/ld-scripts/sort-sections-reversed-3.t
new file mode 100644
index 0000000..15414a8
--- /dev/null
+++ b/ld/testsuite/ld-scripts/sort-sections-reversed-3.t
@@ -0,0 +1,5 @@
+SECTIONS
+{
+ .text : { *(REVERSE(EXCLUDE_FILE(foo) .text*)) }
+ /DISCARD/ : { *(.*) }
+}