gas/ELF: allow specifying entity size for arbitrary sections

The spec doesn't tie entity size to just SHF_MERGE and SHF_STRINGS
sections. Introduce a new "section letter" 'E' to allow recording (and
checking) of entity size even without 'M' or 'S'.
This commit is contained in:
Jan Beulich
2025-08-15 12:19:59 +02:00
parent 21ff588912
commit 98e6d3f5bd
7 changed files with 71 additions and 30 deletions

View File

@@ -869,20 +869,16 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
else if ((flags & SEC_LOAD) != 0)
flags |= SEC_DATA;
if ((hdr->sh_flags & SHF_MERGE) != 0)
{
flags |= SEC_MERGE;
newsect->entsize = hdr->sh_entsize;
}
flags |= SEC_MERGE;
if ((hdr->sh_flags & SHF_STRINGS) != 0)
{
flags |= SEC_STRINGS;
newsect->entsize = hdr->sh_entsize;
}
flags |= SEC_STRINGS;
if ((hdr->sh_flags & SHF_TLS) != 0)
flags |= SEC_THREAD_LOCAL;
if ((hdr->sh_flags & SHF_EXCLUDE) != 0)
flags |= SEC_EXCLUDE;
newsect->entsize = hdr->sh_entsize;
switch (elf_elfheader (abfd)->e_ident[EI_OSABI])
{
/* FIXME: We should not recognize SHF_GNU_MBIND for ELFOSABI_NONE,
@@ -3770,6 +3766,9 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
if ((asect->flags & (SEC_GROUP | SEC_EXCLUDE)) == SEC_EXCLUDE)
this_hdr->sh_flags |= SHF_EXCLUDE;
if (this_hdr->sh_entsize == 0)
this_hdr->sh_entsize = asect->entsize;
/* If the section has relocs, set up a section header for the
SHT_REL[A] section. If two relocation sections are required for
this section, it is up to the processor-specific back-end to

View File

@@ -1,5 +1,8 @@
-*- text -*-
* ELF targets can now have section entity size specified for arbitrary
sections, using the new attribute letter 'E'.
* NaCl target support is removed.
Changes in 2.45:

View File

@@ -792,7 +792,7 @@ change_section (const char *name,
= match_p->linked_to_symbol_name;
bfd_set_section_flags (sec, flags);
if (flags & (SEC_MERGE | SEC_STRINGS))
if (entsize != 0)
sec->entsize = entsize;
elf_group_name (sec) = match_p->group_name;
@@ -847,7 +847,7 @@ change_section (const char *name,
processor or application specific attribute as suspicious? */
elf_section_flags (sec) = attr;
if ((flags & (SEC_MERGE | SEC_STRINGS))
if (entsize != 0
&& old_sec->entsize != (unsigned) entsize)
as_bad (_("changed section entity size for %s"), name);
}
@@ -871,7 +871,8 @@ obj_elf_change_section (const char *name,
static bfd_vma
obj_elf_parse_section_letters (char *str, size_t len, bool push,
bool *is_clone, int *inherit, bfd_vma *gnu_attr)
bool *is_clone, int *inherit, bfd_vma *gnu_attr,
bool *has_entsize)
{
bfd_vma attr = 0;
@@ -913,6 +914,9 @@ obj_elf_parse_section_letters (char *str, size_t len, bool push,
case 'x':
attr |= SHF_EXECINSTR;
break;
case 'E':
*has_entsize = true;
break;
case 'G':
attr |= SHF_GROUP;
break;
@@ -978,8 +982,8 @@ obj_elf_parse_section_letters (char *str, size_t len, bool push,
{
as_bad (_("unrecognized .%ssection attribute: want %s%s%s,? or number"),
push ? "push" : "",
gnu_attr != NULL ? "a,d,e,o,w,x,G,M,R,S,T"
: "a,e,o,w,x,G,M,S,T",
gnu_attr != NULL ? "a,d,e,o,w,x,E,G,M,R,S,T"
: "a,e,o,w,x,E,G,M,S,T",
md_extra != NULL ? "," : "", md_extra);
return attr;
}
@@ -1187,7 +1191,7 @@ obj_elf_section (int push)
bfd_vma attr;
bfd_vma gnu_attr;
int entsize;
bool linkonce;
bool linkonce, has_entsize;
subsegT new_subsection = 0;
struct elf_section_match match;
unsigned long linked_to_section_index = -1UL;
@@ -1232,6 +1236,7 @@ obj_elf_section (int push)
attr = 0;
gnu_attr = 0;
entsize = 0;
has_entsize = false;
linkonce = 0;
if (*input_line_pointer == ',')
@@ -1276,7 +1281,8 @@ obj_elf_section (int push)
== ELFOSABI_GNU)
|| (bed->elf_osabi
== ELFOSABI_FREEBSD)
? &gnu_attr : NULL);
? &gnu_attr : NULL,
&has_entsize);
if (inherit > 0)
attr |= elf_section_flags (now_seg);
@@ -1285,6 +1291,9 @@ obj_elf_section (int push)
if (inherit)
type = elf_section_type (now_seg);
if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0)
has_entsize = true;
SKIP_WHITESPACE ();
if (*input_line_pointer == ',')
{
@@ -1324,16 +1333,18 @@ obj_elf_section (int push)
}
SKIP_WHITESPACE ();
if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0
&& *input_line_pointer == ',')
if (has_entsize && *input_line_pointer == ',')
{
++input_line_pointer;
SKIP_WHITESPACE ();
if (inherit && *input_line_pointer == ','
&& ((bfd_section_flags (now_seg)
& (SEC_MERGE | SEC_STRINGS)) != 0
|| now_seg->entsize))
goto fetch_entsize;
if (is_end_of_stmt (*input_line_pointer)
&& (bfd_section_flags (now_seg)
& (SEC_MERGE | SEC_STRINGS)) != 0)
goto fetch_entsize;
if (is_end_of_stmt (*input_line_pointer))
{
/* ??? This is here for older versions of gcc that
test for gas string merge support with
@@ -1341,7 +1352,7 @@ obj_elf_section (int push)
Unfortunately '@' begins a comment on arm.
This isn't as_warn because gcc tests with
--fatal-warnings. */
as_tsktsk (_("missing merge / string entity size, 1 assumed"));
as_tsktsk (_("missing section entity size, 1 assumed"));
entsize = 1;
}
else
@@ -1350,15 +1361,17 @@ obj_elf_section (int push)
SKIP_WHITESPACE ();
if (entsize <= 0)
{
as_warn (_("invalid merge / string entity size"));
as_warn (_("invalid section entity size"));
attr &= ~(SHF_MERGE | SHF_STRINGS);
has_entsize = false;
entsize = 0;
}
}
}
else if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0 && inherit
&& (bfd_section_flags (now_seg)
& (SEC_MERGE | SEC_STRINGS)) != 0)
else if (has_entsize && inherit
&& ((bfd_section_flags (now_seg)
& (SEC_MERGE | SEC_STRINGS)) != 0
|| now_seg->entsize))
{
fetch_entsize:
entsize = now_seg->entsize;
@@ -1369,6 +1382,7 @@ obj_elf_section (int push)
entsize must be specified if SHF_MERGE is set. */
as_warn (_("entity size for SHF_MERGE not specified"));
attr &= ~(SHF_MERGE | SHF_STRINGS);
has_entsize = false;
}
else if ((attr & SHF_STRINGS) != 0)
{
@@ -1378,6 +1392,11 @@ obj_elf_section (int push)
compatibility. */
entsize = 1;
}
else if (has_entsize)
{
as_warn (_("entity size not specified"));
has_entsize = false;
}
if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0 && type == SHT_NOBITS)
as_warn (_("bogus SHF_MERGE / SHF_STRINGS for SHT_NOBITS section"));

View File

@@ -7004,12 +7004,14 @@ section) in the same file.
section is writable
@item x
section is executable
@item E
section has a (non-zero) element/entry size
@item G
section is a member of a section group
@item M
section is mergeable
@item S
section contains zero terminated strings
@item G
section is a member of a section group
@item T
section is used for thread-local-storage
@item ?
@@ -7118,8 +7120,8 @@ is not generally a good idea as section indices are rarely known at assembly
time, but the facility is provided for testing purposes. An index of zero is
allowed. It indicates that the linked-to section has already been discarded.
Note: If both one of @var{M} or @var{S} and @var{o} flags are present, then the
fields for the Merge/String flag should come first, like this:
Note: If both one of @var{M}, @var{S}, or @var{E} and @var{o} flags are present,
then the type and entry size fields should come first, like this:
@smallexample
.section @var{name},"@var{flags}"Mo,@@@var{type},@var{entsize},@var{SymbolName}
@@ -7142,8 +7144,8 @@ indicates that only one copy of this section should be retained
an alias for comdat
@end table
Note: Uf both one of @var{M} or @var{S} and @var{G} flags are present then the
fields for the Merge/String flag should come first, like this:
Note: If both one of @var{M}, @var{S}, or @var{E} and @var{G} flags are present
then the type and entry size fields should come first, like this:
@smallexample
.section @var{name} , "@var{flags}"MG, @@@var{type}, @var{entsize}, @var{GroupName}[, @var{linkage}]

View File

@@ -293,6 +293,7 @@ if { [is_elf_format] } then {
run_dump_test "sh-link-zero"
run_dump_test "string"
run_dump_test "size"
run_dump_test "entsize"
run_dump_test "dwarf2-1" $dump_opts
run_dump_test "dwarf2-2" $dump_opts
run_dump_test "dwarf2-3" $dump_opts

View File

@@ -0,0 +1,9 @@
#readelf: -SW
#name: sections with entity size
#...
[ ]*\[.*\][ ]+\.merge[ ]+PROGBITS[ ]+0+[ ]+[0-9a-f]+[ ]+0+18[ ]+0c[ ]+AM[ ].*
[ ]*\[.*\][ ]+\.string[ ]+PROGBITS[ ]+0+[ ]+[0-9a-f]+[ ]+0+6[ ]+02[ ]+AS[ ].*
[ ]*\[.*\][ ]+\.custom[ ]+PROGBITS[ ]+0+[ ]+[0-9a-f]+[ ]+0+c[ ]+06[ ]+A[ ].*
[ ]*\[.*\][ ]+\.bss\.custom[ ]+NOBITS[ ]+0+[ ]+[0-9a-f]+[ ]+0+1e[ ]+06[ ]+WA[ ].*
#pass

View File

@@ -0,0 +1,8 @@
.section .merge, "aM", 12
.dc.l 1, 2, 3, 4, 5, 6
.section .string, "aS", %progbits, 2
.dc.w 0x0020, 0x0021, 0x0022
.section .custom, "aE", 6
.dc.w 5, 6, 7, 8, 9, 0
.section .bss.custom, "awE", %nobits, 6
.skip 30