Add support for specifying a section type in linker scripts.
Resolves: #2052801
This commit is contained in:
parent
10575a5d52
commit
b04b2360b7
369
binutils-section-type.patch
Normal file
369
binutils-section-type.patch
Normal file
@ -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=<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 <integer> 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\[\]\-\!\^\\]|::)*
|
||||
<EXPRESSION>"DSECT" { RTOKEN(DSECT); }
|
||||
<EXPRESSION>"COPY" { RTOKEN(COPY); }
|
||||
<EXPRESSION>"INFO" { RTOKEN(INFO); }
|
||||
+<EXPRESSION>"TYPE" { RTOKEN(TYPE); }
|
||||
<SCRIPT,EXPRESSION>"ONLY_IF_RO" { RTOKEN(ONLY_IF_RO); }
|
||||
<SCRIPT,EXPRESSION>"ONLY_IF_RW" { RTOKEN(ONLY_IF_RW); }
|
||||
<SCRIPT,EXPRESSION>"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/ : { *(*) }
|
||||
|
||||
}
|
@ -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 <nickc@redhat.comn> - 2.38-2
|
||||
- Add support for specifying a section type in linker scripts. (#2052801
|
||||
|
||||
* Wed Feb 09 2022 Nick Clifton <nickc@redhat.comn> - 2.38-1
|
||||
- Rebase on GNU Binutils 2.38.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user