From b04b2360b7ccb6ae967f6a301db628b3d363708b Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 16 Feb 2022 18:04:53 +0000 Subject: [PATCH] Add support for specifying a section type in linker scripts. Resolves: #2052801 --- binutils-section-type.patch | 369 ++++++++++++++++++++++++++++++++++++ binutils.spec | 9 +- 2 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 binutils-section-type.patch diff --git a/binutils-section-type.patch b/binutils-section-type.patch new file mode 100644 index 0000000..b8ebfa7 --- /dev/null +++ b/binutils-section-type.patch @@ -0,0 +1,369 @@ +diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h +index 3b2a4f49a9b..78a0a1dea42 100644 +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h +@@ -1170,6 +1170,9 @@ typedef struct bfd_section + This is used when support for non-contiguous memory regions is enabled. */ + struct bfd_section *already_assigned; + ++ /* Explicitly specified section type, if non-zero. */ ++ unsigned int type; ++ + } asection; + + /* Relax table contains information about instructions which can +@@ -1352,8 +1355,8 @@ discarded_section (const asection *sec) + /* symbol, symbol_ptr_ptr, */ \ + (struct bfd_symbol *) SYM, &SEC.symbol, \ + \ +- /* map_head, map_tail, already_assigned */ \ +- { NULL }, { NULL }, NULL \ ++ /* map_head, map_tail, already_assigned, type */ \ ++ { NULL }, { NULL }, NULL, 0 \ + \ + } + +diff --git a/bfd/elf.c b/bfd/elf.c +index a67415e76e1..82b53be99f9 100644 +--- a/bfd/elf.c ++++ b/bfd/elf.c +@@ -3280,7 +3280,9 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) + + /* If the section type is unspecified, we set it based on + asect->flags. */ +- if ((asect->flags & SEC_GROUP) != 0) ++ if (asect->type != 0) ++ sh_type = asect->type; ++ else if ((asect->flags & SEC_GROUP) != 0) + sh_type = SHT_GROUP; + else + sh_type = bfd_elf_get_default_section_type (asect->flags); +diff --git a/bfd/section.c b/bfd/section.c +index 899438a1c5e..2de7dbf661a 100644 +--- a/bfd/section.c ++++ b/bfd/section.c +@@ -737,8 +737,8 @@ CODE_FRAGMENT + . {* symbol, symbol_ptr_ptr, *} \ + . (struct bfd_symbol *) SYM, &SEC.symbol, \ + . \ +-. {* map_head, map_tail, already_assigned *} \ +-. { NULL }, { NULL }, NULL \ ++. {* map_head, map_tail, already_assigned, type *} \ ++. { NULL }, { NULL }, NULL, 0 \ + . \ + . } + . +diff --git a/ld/NEWS b/ld/NEWS +index dbb402d1f8a..a498abaf0f9 100644 +--- a/ld/NEWS ++++ b/ld/NEWS +@@ -1,5 +1,8 @@ + -*- text -*- + ++* TYPE= is now supported in an output section description to set the ++ section type value. ++ + Changes in 2.38: + + * Add -z pack-relative-relocs/-z no pack-relative-relocs to x86 ELF +diff --git a/ld/ld.texi b/ld/ld.texi +index fc75e9b3625..d57e9221410 100644 +--- a/ld/ld.texi ++++ b/ld/ld.texi +@@ -5483,13 +5483,23 @@ loaded into memory when the program is run. + @item READONLY + The section should be marked as read-only. + @item DSECT +-@itemx COPY +-@itemx INFO +-@itemx OVERLAY ++@item COPY ++@item INFO ++@item OVERLAY + These type names are supported for backward compatibility, and are + rarely used. They all have the same effect: the section should be + marked as not allocatable, so that no memory is allocated for the + section when the program is run. ++@item TYPE = @var{type} ++Set the section type to the integer @var{type}. When generating an ELF ++output file, type names @code{SHT_PROGBITS}, @code{SHT_STRTAB}, ++@code{SHT_NOTE}, @code {SHT_NOBITS}, @code{SHT_INIT_ARRAY}, ++@code{SHT_FINI_ARRAY}, and @code{SHT_PREINIT_ARRAY} are also allowed ++for @var{type}. It is the user's responsibility to ensure that any ++special requirements of the section type are met. ++@item READONLY ( TYPE = @var{type} ) ++This form of the syntax combines the @var{READONLY} type with the ++type specified by @var{type}. + @end table + + @kindex NOLOAD +diff --git a/ld/ldgram.y b/ld/ldgram.y +index 11c2f219c05..3a904e39482 100644 +--- a/ld/ldgram.y ++++ b/ld/ldgram.y +@@ -47,6 +47,7 @@ + #endif + + static enum section_type sectype; ++static etree_type *sectype_value; + static lang_memory_region_type *region; + + static bool ldgram_had_keep = false; +@@ -139,6 +140,7 @@ static int error_index; + %token LD_FEATURE + %token NOLOAD DSECT COPY INFO OVERLAY + %token READONLY ++%token TYPE + %token DEFINED TARGET_K SEARCH_DIR MAP ENTRY + %token NEXT + %token SIZEOF ALIGNOF ADDR LOADADDR MAX_K MIN_K +@@ -1058,9 +1060,8 @@ section: NAME + { + ldlex_popstate (); + ldlex_wild (); +- lang_enter_output_section_statement($1, $3, sectype, +- $5, $7, $4, +- $8, $6); ++ lang_enter_output_section_statement ($1, $3, sectype, ++ sectype_value, $5, $7, $4, $8, $6); + } + '{' + statement_list_opt +@@ -1130,8 +1131,10 @@ type: + | COPY { sectype = noalloc_section; } + | INFO { sectype = noalloc_section; } + | OVERLAY { sectype = noalloc_section; } ++ | READONLY '(' TYPE '=' exp ')' { sectype = typed_readonly_section; sectype_value = $5; } + | READONLY { sectype = readonly_section; } +- ; ++ | TYPE '=' exp { sectype = type_section; sectype_value = $3; } ++ ; + + atype: + '(' type ')' +diff --git a/ld/ldlang.c b/ld/ldlang.c +index 474784c874a..1733f8e65c4 100644 +--- a/ld/ldlang.c ++++ b/ld/ldlang.c +@@ -1891,8 +1891,8 @@ lang_insert_orphan (asection *s, + address = exp_intop (0); + + os_tail = (lang_output_section_statement_type **) lang_os_list.tail; +- os = lang_enter_output_section_statement (secname, address, normal_section, +- NULL, NULL, NULL, constraint, 0); ++ os = lang_enter_output_section_statement ( ++ secname, address, normal_section, 0, NULL, NULL, NULL, constraint, 0); + + if (add_child == NULL) + add_child = &os->children; +@@ -2635,10 +2635,12 @@ lang_add_section (lang_statement_list_type *ptr, + case normal_section: + case overlay_section: + case first_overlay_section: ++ case type_section: + break; + case noalloc_section: + flags &= ~SEC_ALLOC; + break; ++ case typed_readonly_section: + case readonly_section: + flags |= SEC_READONLY; + break; +@@ -4209,6 +4211,7 @@ map_input_to_output_sections + { + lang_output_section_statement_type *tos; + flagword flags; ++ unsigned int type = 0; + + switch (s->header.type) + { +@@ -4264,6 +4267,42 @@ map_input_to_output_sections + case readonly_section: + flags |= SEC_READONLY; + break; ++ case typed_readonly_section: ++ flags |= SEC_READONLY; ++ /* Fall through. */ ++ case type_section: ++ if (os->sectype_value->type.node_class == etree_name ++ && os->sectype_value->type.node_code == NAME) ++ { ++ const char *name = os->sectype_value->name.name; ++ if (strcmp (name, "SHT_PROGBITS") == 0) ++ type = SHT_PROGBITS; ++ else if (strcmp (name, "SHT_STRTAB") == 0) ++ type = SHT_STRTAB; ++ else if (strcmp (name, "SHT_NOTE") == 0) ++ type = SHT_NOTE; ++ else if (strcmp (name, "SHT_NOBITS") == 0) ++ type = SHT_NOBITS; ++ else if (strcmp (name, "SHT_INIT_ARRAY") == 0) ++ type = SHT_INIT_ARRAY; ++ else if (strcmp (name, "SHT_FINI_ARRAY") == 0) ++ type = SHT_FINI_ARRAY; ++ else if (strcmp (name, "SHT_PREINIT_ARRAY") == 0) ++ type = SHT_PREINIT_ARRAY; ++ else ++ einfo (_ ("%F%P: invalid type for output section `%s'\n"), ++ os->name); ++ } ++ else ++ { ++ exp_fold_tree_no_dot (os->sectype_value); ++ if (expld.result.valid_p) ++ type = expld.result.value; ++ else ++ einfo (_ ("%F%P: invalid type for output section `%s'\n"), ++ os->name); ++ } ++ break; + case noload_section: + if (bfd_get_flavour (link_info.output_bfd) + == bfd_target_elf_flavour) +@@ -4276,6 +4315,7 @@ map_input_to_output_sections + init_os (os, flags | SEC_READONLY); + else + os->bfd_section->flags |= flags; ++ os->bfd_section->type = type; + break; + case lang_input_section_enum: + break; +@@ -7506,6 +7546,7 @@ lang_output_section_statement_type * + lang_enter_output_section_statement (const char *output_section_statement_name, + etree_type *address_exp, + enum section_type sectype, ++ etree_type *sectype_value, + etree_type *align, + etree_type *subalign, + etree_type *ebase, +@@ -7523,10 +7564,12 @@ lang_enter_output_section_statement (const char *output_section_statement_name, + os->addr_tree = address_exp; + } + os->sectype = sectype; +- if (sectype != noload_section) +- os->flags = SEC_NO_FLAGS; +- else ++ if (sectype == type_section || sectype == typed_readonly_section) ++ os->sectype_value = sectype_value; ++ else if (sectype == noload_section) + os->flags = SEC_NEVER_LOAD; ++ else ++ os->flags = SEC_NO_FLAGS; + os->block_value = 1; + + /* Make next things chain into subchain of this. */ +@@ -8842,7 +8885,7 @@ lang_enter_overlay_section (const char *name) + etree_type *size; + + lang_enter_output_section_statement (name, overlay_vma, overlay_section, +- 0, overlay_subalign, 0, 0, 0); ++ 0, 0, overlay_subalign, 0, 0, 0); + + /* If this is the first section, then base the VMA of future + sections on this one. This will work correctly even if `.' is +diff --git a/ld/ldlang.h b/ld/ldlang.h +index 0d057c9bee9..95f6e468b30 100644 +--- a/ld/ldlang.h ++++ b/ld/ldlang.h +@@ -122,7 +122,9 @@ enum section_type + overlay_section, + noload_section, + noalloc_section, +- readonly_section ++ type_section, ++ readonly_section, ++ typed_readonly_section + }; + + /* This structure holds a list of program headers describing +@@ -166,6 +168,7 @@ typedef struct lang_output_section_statement_struct + int constraint; + flagword flags; + enum section_type sectype; ++ etree_type *sectype_value; + unsigned int processed_vma : 1; + unsigned int processed_lma : 1; + unsigned int all_input_readonly : 1; +@@ -545,7 +548,7 @@ extern void lang_add_output + (const char *, int from_script); + extern lang_output_section_statement_type *lang_enter_output_section_statement + (const char *, etree_type *, enum section_type, etree_type *, etree_type *, +- etree_type *, int, int); ++ etree_type *, etree_type *, int, int); + extern void lang_final + (void); + extern void lang_relax_sections +diff --git a/ld/ldlex.l b/ld/ldlex.l +index 78db16e3a48..c38b46b9336 100644 +--- a/ld/ldlex.l ++++ b/ld/ldlex.l +@@ -323,6 +323,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* + "DSECT" { RTOKEN(DSECT); } + "COPY" { RTOKEN(COPY); } + "INFO" { RTOKEN(INFO); } ++"TYPE" { RTOKEN(TYPE); } + "ONLY_IF_RO" { RTOKEN(ONLY_IF_RO); } + "ONLY_IF_RW" { RTOKEN(ONLY_IF_RW); } + "SPECIAL" { RTOKEN(SPECIAL); } +diff --git a/ld/mri.c b/ld/mri.c +index b428ab0d0bf..5749870ef1e 100644 +--- a/ld/mri.c ++++ b/ld/mri.c +@@ -210,8 +210,8 @@ mri_draw_tree (void) + base = p->vma ? p->vma : exp_nameop (NAME, "."); + + lang_enter_output_section_statement (p->name, base, +- p->ok_to_load ? normal_section : noload_section, +- align, subalign, NULL, 0, 0); ++ p->ok_to_load ? normal_section : noload_section, 0, ++ align, subalign, NULL, 0, 0); + base = 0; + tmp = (struct wildcard_list *) xmalloc (sizeof *tmp); + tmp->next = NULL; +diff --git a/ld/testsuite/ld-scripts/output-section-types.d b/ld/testsuite/ld-scripts/output-section-types.d +index ab124fa4dd7..2ecacaba57d 100644 +--- a/ld/testsuite/ld-scripts/output-section-types.d ++++ b/ld/testsuite/ld-scripts/output-section-types.d +@@ -1,13 +1,17 @@ + #ld: -Toutput-section-types.t + #source: align2a.s +-#objdump: -h ++#readelf: -S --wide + #target: [is_elf_format] + + #... +- . \.rom.* +-[ ]+ALLOC, READONLY +- . \.ro.* +-[ ]+CONTENTS, ALLOC, LOAD, READONLY, DATA +- . \.over.* +-[ ]+CONTENTS, READONLY ++.* .rom +NOBITS +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248] ++.* .ro +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248] ++.* .over +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 + +0 +0 +[1248] ++.* progbits +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248] ++.* strtab +STRTAB +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248] ++.* note +NOTE +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248] ++.* init_array +INIT_ARRAY +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +0 +0 +[1248] ++.* fini_array +FINI_ARRAY +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +0 +0 +[1248] ++.* preinit_array +PREINIT_ARRAY +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +0 +0 +[1248] ++.* .ro.note +NOTE +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248] + #pass +diff --git a/ld/testsuite/ld-scripts/output-section-types.t b/ld/testsuite/ld-scripts/output-section-types.t +index d8fdfda1a03..18fc5c11980 100644 +--- a/ld/testsuite/ld-scripts/output-section-types.t ++++ b/ld/testsuite/ld-scripts/output-section-types.t +@@ -2,6 +2,13 @@ SECTIONS { + .rom (NOLOAD) : { LONG(1234); } + .ro (READONLY) : { LONG(5678); } + .over (OVERLAY) : { LONG(0123); } ++ progbits (TYPE=SHT_PROGBITS) : { BYTE(1) } ++ strtab (TYPE = SHT_STRTAB) : { BYTE(0) } ++ note (TYPE =SHT_NOTE) : { BYTE(8) } ++ init_array (TYPE= 14) : { QUAD(14) } ++ fini_array ( TYPE=SHT_FINI_ARRAY) : { QUAD(15) } ++ preinit_array (TYPE=SHT_PREINIT_ARRAY ) : { QUAD(16) } ++ .ro.note (READONLY (TYPE=SHT_NOTE)) : { LONG(5678); } + /DISCARD/ : { *(*) } + + } diff --git a/binutils.spec b/binutils.spec index 8a2bcc6..4875d8e 100644 --- a/binutils.spec +++ b/binutils.spec @@ -39,7 +39,7 @@ Summary: A GNU collection of binary utilities Name: binutils%{?name_cross}%{?_with_debug:-debug} Version: 2.38 -Release: 1%{?dist} +Release: 2%{?dist} License: GPLv3+ URL: https://sourceware.org/binutils @@ -285,6 +285,10 @@ Patch18: binutils-autoconf-version.patch # Lifetime: Who knows. Patch19: gcc12-libtool-no-rpath.patch +# Purpose: Add support for specifying section types in linker scripts. +# Lifetime: Fixed in 2.39 +Patch20: binutils-section-type.patch + #---------------------------------------------------------------------------- Provides: bundled(libiberty) @@ -895,6 +899,9 @@ exit 0 #---------------------------------------------------------------------------- %changelog +* Wed Feb 16 2022 Nick Clifton - 2.38-2 +- Add support for specifying a section type in linker scripts. (#2052801 + * Wed Feb 09 2022 Nick Clifton - 2.38-1 - Rebase on GNU Binutils 2.38.