From 6e8376fa569e62379a42b91b0afd1f4086f1d897 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 10 May 2024 16:59:05 +0100 Subject: [PATCH] Add --section-ordering command line option to the bfd linker. --- ld/NEWS | 3 ++ ld/ld.h | 4 ++ ld/ld.texi | 72 +++++++++++++++++++++++--- ld/ldfile.c | 15 +----- ld/ldfile.h | 19 ++++++- ld/ldgram.y | 36 ++++++++++++- ld/ldlang.c | 81 +++++++++++++++++++++--------- ld/ldlang.h | 5 ++ ld/ldlex.h | 2 + ld/ldlex.l | 11 ++-- ld/ldmain.c | 55 ++++++++++++++------ ld/lexsup.c | 9 ++++ ld/testsuite/ld-scripts/section-order-1a.d | 22 ++++++++ ld/testsuite/ld-scripts/section-order-1a.s | 29 +++++++++++ ld/testsuite/ld-scripts/section-order-1a.t | 14 ++++++ ld/testsuite/ld-scripts/section-order-1b.d | 18 +++++++ ld/testsuite/ld-scripts/section-order-1b.s | 34 +++++++++++++ ld/testsuite/ld-scripts/section-order-1b.t | 7 +++ ld/testsuite/ld-scripts/section-order-1c.d | 14 ++++++ ld/testsuite/ld-scripts/section-order-1d.d | 18 +++++++ ld/testsuite/ld-scripts/section-order.exp | 45 +++++++++++++++++ ld/testsuite/ld-scripts/start.s | 14 ++++++ 22 files changed, 462 insertions(+), 65 deletions(-) create mode 100644 ld/testsuite/ld-scripts/section-order-1a.d create mode 100644 ld/testsuite/ld-scripts/section-order-1a.s create mode 100644 ld/testsuite/ld-scripts/section-order-1a.t create mode 100644 ld/testsuite/ld-scripts/section-order-1b.d create mode 100644 ld/testsuite/ld-scripts/section-order-1b.s create mode 100644 ld/testsuite/ld-scripts/section-order-1b.t create mode 100644 ld/testsuite/ld-scripts/section-order-1c.d create mode 100644 ld/testsuite/ld-scripts/section-order-1d.d create mode 100644 ld/testsuite/ld-scripts/section-order.exp create mode 100644 ld/testsuite/ld-scripts/start.s diff --git a/ld/NEWS b/ld/NEWS index f70d2157339..00eb46047d1 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -1,5 +1,8 @@ -*- text -*- +* Add --section-ordering-file option to add extra mapping of input + sections to output sections. + * Add -plugin-save-temps to store plugin intermediate files permanently. Changes in 2.42: diff --git a/ld/ld.h b/ld/ld.h index fcdd9a2c083..0dee944cf2a 100644 --- a/ld/ld.h +++ b/ld/ld.h @@ -196,6 +196,9 @@ typedef struct /* Default linker script. */ char *default_script; + + /* Linker script fragment provided by the --section-order command line option. */ + char *section_ordering_file; } args_type; extern args_type command_line; @@ -325,6 +328,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/ld.texi b/ld/ld.texi index ca9574dfc71..b32bb463f3f 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -302,6 +302,7 @@ and the script command language. If @emph{no} binary input files at all are specified, the linker does not produce any output, and issues the message @samp{No input files}. +@anchor{unrecognised-input-files} If the linker cannot recognize the format of an object file, it will assume that it is a linker script. A script specified in this way augments the main linker script used for the link (either the default @@ -1163,18 +1164,32 @@ a linker bug report. @itemx --script=@var{scriptfile} Use @var{scriptfile} as the linker script. This script replaces @command{ld}'s default linker script (rather than adding to it), -unless the script contains @code{INSERT}, so -@var{commandfile} must specify everything necessary to describe the -output file. @xref{Scripts}. If @var{scriptfile} does not exist in -the current directory, @code{ld} looks for it in the directories -specified by any preceding @samp{-L} options. Multiple @samp{-T} -options accumulate. +unless the script contains @code{INSERT}, so @var{commandfile} must +specify everything necessary to describe the output file. +@xref{Scripts}. + +If @var{scriptfile} does not exist in the current directory, @code{ld} +looks for it in the directories specified by any preceding @samp{-L} +options. + +Command line options that appear before the @option{-T} option can +affect the script, but command line options that appear after it do +not. + +Multiple @samp{-T} options will accumulate if they are augmenting the +current script, otherwise the last, non-augmenting, @option{-T} option +will be used. + +There are other ways of specifying linker scripts. See +@xref{--default-script}, @xref{--section-ordering-file} and +@xref{unrecognised-input-files}. @kindex -dT @var{script} @kindex --default-script=@var{script} @cindex script files @item -dT @var{scriptfile} @itemx --default-script=@var{scriptfile} +@anchor{--default-script} Use @var{scriptfile} as the default linker script. @xref{Scripts}. This option is similar to the @option{--script} option except that @@ -2521,6 +2536,51 @@ warning and continue with the link. @end ifset +@kindex --section-ordering-file +@item --section-ordering-file=@var{script} +@anchor{--section-ordering-file} +This option is used to augment the current linker script with +additional mapping of input sections to output sections. This file +must use the same syntax for @code{SECTIONS} as is used in normal +linker scripts, but it should not do anything other than place input +sections into output sections. @pxref{SECTIONS} + +A second constraint on the section ordering script is that it can only +reference output sections that are already defined by whichever linker +script is currently in use. (Ie the default linker script or a script +specified on the command line). The benefit of the section ordering +script however is that the input sections are mapped to the start of +the output sections, so that they can ensure the ordering of sections +in the output section. For example, imagine that the default linker +script looks like this: + +@smallexample +SECTIONS @{ + .text : @{ *(.text.hot) ; *(.text .text.*) @} + .data : @{ *(.data.big) ; *(.data .data.*) @} + @} +@end smallexample + +Then if a section ordering file like this is used: + +@smallexample + .text : @{ *(.text.first) ; *(.text.z*) @} + .data : @{ foo.o(.data.first) ; *(.data.small) @} +@end smallexample + +This would be equivalent to a linker script like this: + +@smallexample +SECTIONS @{ + .text : @{ *(.text.first) ; *(.text.z*) ; *(.text.hot) ; *(.text .text.*) @} + .data : @{ foo.o(.data.first) ; *(.data.small) ; *(.data.big) ; *(.data .data.*) @} + @} +@end smallexample + +The advantage of the section ordering file is that it can be used to +order those sections that matter to the user without having to worry +about any other sections, or memory regions, or anything else. + @kindex -shared @kindex -Bshareable @item -shared diff --git a/ld/ldfile.c b/ld/ldfile.c index dc9875d8813..f1107a1b7d7 100644 --- a/ld/ldfile.c +++ b/ld/ldfile.c @@ -871,19 +871,7 @@ ldfile_find_command_file (const char *name, return result; } -enum script_open_style { - script_nonT, - script_T, - script_defaultT -}; - -struct script_name_list -{ - struct script_name_list *next; - enum script_open_style open_how; - char name[1]; -}; - +struct script_name_list *processed_scripts = NULL; /* Open command file NAME. */ static void @@ -891,7 +879,6 @@ ldfile_open_command_file_1 (const char *name, enum script_open_style open_how) { FILE *ldlex_input_stack; bool sysrooted; - static struct script_name_list *processed_scripts = NULL; struct script_name_list *script; size_t len; diff --git a/ld/ldfile.h b/ld/ldfile.h index f17677e9e9a..f79abf2310d 100644 --- a/ld/ldfile.h +++ b/ld/ldfile.h @@ -29,7 +29,8 @@ extern const char *ldfile_output_machine_name; /* Structure used to hold the list of directories to search for libraries. */ -typedef struct search_dirs { +typedef struct search_dirs +{ /* Next directory on list. */ struct search_dirs *next; /* Name of directory. */ @@ -38,6 +39,22 @@ typedef struct search_dirs { bool cmdline; } search_dirs_type; +enum script_open_style +{ + script_nonT, + script_T, + script_defaultT +}; + +struct script_name_list +{ + struct script_name_list * next; + enum script_open_style open_how; + char name[1]; +}; + +extern struct script_name_list * processed_scripts; + extern search_dirs_type *search_head; extern void ldfile_add_arch diff --git a/ld/ldgram.y b/ld/ldgram.y index 0d531fddfa1..07c19ba8692 100644 --- a/ld/ldgram.y +++ b/ld/ldgram.y @@ -157,7 +157,7 @@ static void yyerror (const char *); %token LOG2CEIL FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL %token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START %token VERS_TAG VERS_IDENTIFIER -%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT +%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT INPUT_SECTION_ORDERING_SCRIPT %token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL INPUT_SECTION_FLAGS ALIGN_WITH_INPUT %token EXCLUDE_FILE %token CONSTANT @@ -172,6 +172,7 @@ file: INPUT_SCRIPT script_file | INPUT_MRI_SCRIPT mri_script_file | INPUT_VERSION_SCRIPT version_script_file + | INPUT_SECTION_ORDERING_SCRIPT section_ordering_script_file | INPUT_DYNAMIC_LIST dynamic_list_file | INPUT_DEFSYM defsym_expr ; @@ -1539,6 +1540,39 @@ opt_semicolon: | ';' ; +section_ordering_script_file: + { + ldlex_script (); + PUSH_ERROR (_("section-ordering-file script")); + } + section_ordering_list + { + ldlex_popstate (); + POP_ERROR (); + } + ; + +section_ordering_list: + section_ordering_list section_order + | section_ordering_list statement_anywhere + | + ; + +section_order: NAME ':' + { + ldlex_wild (); + lang_enter_output_section_statement + ($1, NULL, 0, NULL, NULL, NULL, NULL, 0, 0); + } + '{' + statement_list_opt + '}' + { + ldlex_popstate (); + lang_leave_output_section_statement (NULL, NULL, NULL, NULL); + } + opt_comma + %% static void yyerror (const char *arg) diff --git a/ld/ldlang.c b/ld/ldlang.c index 54d1af62ebe..9e8cc224f4d 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,22 @@ 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) /* && in_section_ordering */ + einfo (_("%F%P:%pS: error: output section '%s' must already exist\n"), + NULL, output_section_statement_name); 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 +7639,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 +7978,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 +8025,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 +8134,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 +8849,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 (¤t_section->region, ¤t_section->lma_region, memspec, lma_memspec, @@ -8825,7 +8861,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..4c1bb002f8e 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -141,7 +141,12 @@ typedef struct lang_output_section_phdr_list typedef struct lang_output_section_statement_struct { lang_statement_header_type header; + /* Input sections to be mapped to this output section. */ lang_statement_list_type children; + /* Input sections to be mapped to the start of this output section. + These sections are provided by the --section-ordering file, if used. */ + lang_statement_list_type sort_children; + struct lang_output_section_statement_struct *next; struct lang_output_section_statement_struct *prev; const char *name; diff --git a/ld/ldlex.h b/ld/ldlex.h index d575562a357..7a0c3b4be94 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, @@ -477,6 +478,7 @@ typedef enum input_enum input_script, input_mri_script, input_version_script, + input_section_ordering_script, input_dynamic_list, input_defsym } input_type; diff --git a/ld/ldlex.l b/ld/ldlex.l index e113c90812b..aa613100db0 100644 --- a/ld/ldlex.l +++ b/ld/ldlex.l @@ -120,11 +120,12 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* parser_input = input_selected; switch (t) { - case input_script: return INPUT_SCRIPT; break; - case input_mri_script: return INPUT_MRI_SCRIPT; break; - case input_version_script: return INPUT_VERSION_SCRIPT; break; - case input_dynamic_list: return INPUT_DYNAMIC_LIST; break; - case input_defsym: return INPUT_DEFSYM; break; + case input_script: return INPUT_SCRIPT; + case input_mri_script: return INPUT_MRI_SCRIPT; + case input_version_script: return INPUT_VERSION_SCRIPT; + case input_section_ordering_script: return INPUT_SECTION_ORDERING_SCRIPT; + case input_dynamic_list: return INPUT_DYNAMIC_LIST; + case input_defsym: return INPUT_DEFSYM; default: abort (); } } diff --git a/ld/ldmain.c b/ld/ldmain.c index fe389681bd3..037099b9d37 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; @@ -246,6 +248,26 @@ ld_bfd_error_handler (const char *fmt, va_list ap) (*default_bfd_error_handler) (fmt, ap); } +static void +display_external_script (void) +{ + if (saved_script_handle == NULL) + return; + + static const int ld_bufsz = 8193; + size_t n; + char *buf = (char *) xmalloc (ld_bufsz); + + rewind (saved_script_handle); + while ((n = fread (buf, 1, ld_bufsz - 1, saved_script_handle)) > 0) + { + buf[n] = 0; + info_msg ("%s", buf); + } + rewind (saved_script_handle); + free (buf); +} + int main (int argc, char **argv) { @@ -416,26 +438,13 @@ main (int argc, char **argv) if (verbose) { if (saved_script_handle) - info_msg (_("using external linker script:")); + info_msg (_("using external linker script: %s"), processed_scripts->name); else info_msg (_("using internal linker script:")); info_msg ("\n==================================================\n"); if (saved_script_handle) - { - static const int ld_bufsz = 8193; - size_t n; - char *buf = (char *) xmalloc (ld_bufsz); - - rewind (saved_script_handle); - while ((n = fread (buf, 1, ld_bufsz - 1, saved_script_handle)) > 0) - { - buf[n] = 0; - info_msg ("%s", buf); - } - rewind (saved_script_handle); - free (buf); - } + display_external_script (); else { int isfile; @@ -446,6 +455,22 @@ 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); + if (verbose) + display_external_script (); + saved_script_handle = hold_script_handle; + in_section_ordering = true; + parser_input = input_section_ordering_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..4125d849f2c 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,12 @@ parse_args (unsigned argc, char **argv) einfo (_("%F%P: invalid section sorting option: %s\n"), optarg); break; + case OPTION_SECTION_ORDERING_FILE: + if (command_line.section_ordering_file != NULL + && strcmp (optarg, command_line.section_ordering_file) != 0) + einfo (_("%P: warning: section ordering file changed. Ignoring earlier definition\n")); + 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..40730b82a8d --- /dev/null +++ b/ld/testsuite/ld-scripts/section-order-1a.d @@ -0,0 +1,22 @@ +#name: Text Section Ordering (section-order-1a) +#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 +#... +[0-9a-f]+ T qqq +#... +[0-9a-f]+ T zzz +#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..2394a7ba902 --- /dev/null +++ b/ld/testsuite/ld-scripts/section-order-1a.s @@ -0,0 +1,29 @@ + .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 + + .section .text.zzz + .global zzz +zzz: + .dc.a 0 + + .section .data.bbb + .global bbb +bbb: + .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..2e28bfa8451 --- /dev/null +++ b/ld/testsuite/ld-scripts/section-order-1a.t @@ -0,0 +1,14 @@ +.text : { + *(.text.yyy) + *(.text.b?r) + *(.text) + *(.text.xxx .text.foo) +} + +.data : { + *(.data.small) + *(.big*) + *(.bar .baz*) + *(.data.ccc) +} + 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..caf713dd915 --- /dev/null +++ b/ld/testsuite/ld-scripts/section-order-1b.d @@ -0,0 +1,18 @@ +#name: Text Section Ordering (section-order-1b) +#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..49a0b32475a --- /dev/null +++ b/ld/testsuite/ld-scripts/section-order-1b.s @@ -0,0 +1,34 @@ + .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 + + .section .text.qqq + .global qqq +qqq: + .dc.a 0 + + .section .data.ccc + .global ccc +ccc: + .dc.a 0 + + .data + .global data_symbol +data_symbol: + .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..6a36250dcbc --- /dev/null +++ b/ld/testsuite/ld-scripts/section-order-1b.t @@ -0,0 +1,7 @@ +.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..ad06d4ac0d4 --- /dev/null +++ b/ld/testsuite/ld-scripts/section-order-1c.d @@ -0,0 +1,14 @@ +#name: Data Section Ordering (section-order-1c) +#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-1d.d b/ld/testsuite/ld-scripts/section-order-1d.d new file mode 100644 index 00000000000..d0165056e66 --- /dev/null +++ b/ld/testsuite/ld-scripts/section-order-1d.d @@ -0,0 +1,18 @@ +#name: Data Section Ordering (section-order-1d) +#source: section-order-1a.s +#source: section-order-1b.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 bart +#... +[0-9a-f]+ D ccc +#... +[0-9a-f]+ D bbb +#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 -- 2.11.4.GIT