mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-06 07:33:08 +00:00
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:
11
bfd/elf.c
11
bfd/elf.c
@@ -869,20 +869,16 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
|
|||||||
else if ((flags & SEC_LOAD) != 0)
|
else if ((flags & SEC_LOAD) != 0)
|
||||||
flags |= SEC_DATA;
|
flags |= SEC_DATA;
|
||||||
if ((hdr->sh_flags & SHF_MERGE) != 0)
|
if ((hdr->sh_flags & SHF_MERGE) != 0)
|
||||||
{
|
|
||||||
flags |= SEC_MERGE;
|
flags |= SEC_MERGE;
|
||||||
newsect->entsize = hdr->sh_entsize;
|
|
||||||
}
|
|
||||||
if ((hdr->sh_flags & SHF_STRINGS) != 0)
|
if ((hdr->sh_flags & SHF_STRINGS) != 0)
|
||||||
{
|
|
||||||
flags |= SEC_STRINGS;
|
flags |= SEC_STRINGS;
|
||||||
newsect->entsize = hdr->sh_entsize;
|
|
||||||
}
|
|
||||||
if ((hdr->sh_flags & SHF_TLS) != 0)
|
if ((hdr->sh_flags & SHF_TLS) != 0)
|
||||||
flags |= SEC_THREAD_LOCAL;
|
flags |= SEC_THREAD_LOCAL;
|
||||||
if ((hdr->sh_flags & SHF_EXCLUDE) != 0)
|
if ((hdr->sh_flags & SHF_EXCLUDE) != 0)
|
||||||
flags |= SEC_EXCLUDE;
|
flags |= SEC_EXCLUDE;
|
||||||
|
|
||||||
|
newsect->entsize = hdr->sh_entsize;
|
||||||
|
|
||||||
switch (elf_elfheader (abfd)->e_ident[EI_OSABI])
|
switch (elf_elfheader (abfd)->e_ident[EI_OSABI])
|
||||||
{
|
{
|
||||||
/* FIXME: We should not recognize SHF_GNU_MBIND for ELFOSABI_NONE,
|
/* 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)
|
if ((asect->flags & (SEC_GROUP | SEC_EXCLUDE)) == SEC_EXCLUDE)
|
||||||
this_hdr->sh_flags |= SHF_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
|
/* If the section has relocs, set up a section header for the
|
||||||
SHT_REL[A] section. If two relocation sections are required for
|
SHT_REL[A] section. If two relocation sections are required for
|
||||||
this section, it is up to the processor-specific back-end to
|
this section, it is up to the processor-specific back-end to
|
||||||
|
|||||||
3
gas/NEWS
3
gas/NEWS
@@ -1,5 +1,8 @@
|
|||||||
-*- text -*-
|
-*- text -*-
|
||||||
|
|
||||||
|
* ELF targets can now have section entity size specified for arbitrary
|
||||||
|
sections, using the new attribute letter 'E'.
|
||||||
|
|
||||||
* NaCl target support is removed.
|
* NaCl target support is removed.
|
||||||
|
|
||||||
Changes in 2.45:
|
Changes in 2.45:
|
||||||
|
|||||||
@@ -792,7 +792,7 @@ change_section (const char *name,
|
|||||||
= match_p->linked_to_symbol_name;
|
= match_p->linked_to_symbol_name;
|
||||||
|
|
||||||
bfd_set_section_flags (sec, flags);
|
bfd_set_section_flags (sec, flags);
|
||||||
if (flags & (SEC_MERGE | SEC_STRINGS))
|
if (entsize != 0)
|
||||||
sec->entsize = entsize;
|
sec->entsize = entsize;
|
||||||
elf_group_name (sec) = match_p->group_name;
|
elf_group_name (sec) = match_p->group_name;
|
||||||
|
|
||||||
@@ -847,7 +847,7 @@ change_section (const char *name,
|
|||||||
processor or application specific attribute as suspicious? */
|
processor or application specific attribute as suspicious? */
|
||||||
elf_section_flags (sec) = attr;
|
elf_section_flags (sec) = attr;
|
||||||
|
|
||||||
if ((flags & (SEC_MERGE | SEC_STRINGS))
|
if (entsize != 0
|
||||||
&& old_sec->entsize != (unsigned) entsize)
|
&& old_sec->entsize != (unsigned) entsize)
|
||||||
as_bad (_("changed section entity size for %s"), name);
|
as_bad (_("changed section entity size for %s"), name);
|
||||||
}
|
}
|
||||||
@@ -871,7 +871,8 @@ obj_elf_change_section (const char *name,
|
|||||||
|
|
||||||
static bfd_vma
|
static bfd_vma
|
||||||
obj_elf_parse_section_letters (char *str, size_t len, bool push,
|
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;
|
bfd_vma attr = 0;
|
||||||
|
|
||||||
@@ -913,6 +914,9 @@ obj_elf_parse_section_letters (char *str, size_t len, bool push,
|
|||||||
case 'x':
|
case 'x':
|
||||||
attr |= SHF_EXECINSTR;
|
attr |= SHF_EXECINSTR;
|
||||||
break;
|
break;
|
||||||
|
case 'E':
|
||||||
|
*has_entsize = true;
|
||||||
|
break;
|
||||||
case 'G':
|
case 'G':
|
||||||
attr |= SHF_GROUP;
|
attr |= SHF_GROUP;
|
||||||
break;
|
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"),
|
as_bad (_("unrecognized .%ssection attribute: want %s%s%s,? or number"),
|
||||||
push ? "push" : "",
|
push ? "push" : "",
|
||||||
gnu_attr != NULL ? "a,d,e,o,w,x,G,M,R,S,T"
|
gnu_attr != NULL ? "a,d,e,o,w,x,E,G,M,R,S,T"
|
||||||
: "a,e,o,w,x,G,M,S,T",
|
: "a,e,o,w,x,E,G,M,S,T",
|
||||||
md_extra != NULL ? "," : "", md_extra);
|
md_extra != NULL ? "," : "", md_extra);
|
||||||
return attr;
|
return attr;
|
||||||
}
|
}
|
||||||
@@ -1187,7 +1191,7 @@ obj_elf_section (int push)
|
|||||||
bfd_vma attr;
|
bfd_vma attr;
|
||||||
bfd_vma gnu_attr;
|
bfd_vma gnu_attr;
|
||||||
int entsize;
|
int entsize;
|
||||||
bool linkonce;
|
bool linkonce, has_entsize;
|
||||||
subsegT new_subsection = 0;
|
subsegT new_subsection = 0;
|
||||||
struct elf_section_match match;
|
struct elf_section_match match;
|
||||||
unsigned long linked_to_section_index = -1UL;
|
unsigned long linked_to_section_index = -1UL;
|
||||||
@@ -1232,6 +1236,7 @@ obj_elf_section (int push)
|
|||||||
attr = 0;
|
attr = 0;
|
||||||
gnu_attr = 0;
|
gnu_attr = 0;
|
||||||
entsize = 0;
|
entsize = 0;
|
||||||
|
has_entsize = false;
|
||||||
linkonce = 0;
|
linkonce = 0;
|
||||||
|
|
||||||
if (*input_line_pointer == ',')
|
if (*input_line_pointer == ',')
|
||||||
@@ -1276,7 +1281,8 @@ obj_elf_section (int push)
|
|||||||
== ELFOSABI_GNU)
|
== ELFOSABI_GNU)
|
||||||
|| (bed->elf_osabi
|
|| (bed->elf_osabi
|
||||||
== ELFOSABI_FREEBSD)
|
== ELFOSABI_FREEBSD)
|
||||||
? &gnu_attr : NULL);
|
? &gnu_attr : NULL,
|
||||||
|
&has_entsize);
|
||||||
|
|
||||||
if (inherit > 0)
|
if (inherit > 0)
|
||||||
attr |= elf_section_flags (now_seg);
|
attr |= elf_section_flags (now_seg);
|
||||||
@@ -1285,6 +1291,9 @@ obj_elf_section (int push)
|
|||||||
if (inherit)
|
if (inherit)
|
||||||
type = elf_section_type (now_seg);
|
type = elf_section_type (now_seg);
|
||||||
|
|
||||||
|
if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0)
|
||||||
|
has_entsize = true;
|
||||||
|
|
||||||
SKIP_WHITESPACE ();
|
SKIP_WHITESPACE ();
|
||||||
if (*input_line_pointer == ',')
|
if (*input_line_pointer == ',')
|
||||||
{
|
{
|
||||||
@@ -1324,16 +1333,18 @@ obj_elf_section (int push)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SKIP_WHITESPACE ();
|
SKIP_WHITESPACE ();
|
||||||
if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0
|
if (has_entsize && *input_line_pointer == ',')
|
||||||
&& *input_line_pointer == ',')
|
|
||||||
{
|
{
|
||||||
++input_line_pointer;
|
++input_line_pointer;
|
||||||
SKIP_WHITESPACE ();
|
SKIP_WHITESPACE ();
|
||||||
if (inherit && *input_line_pointer == ','
|
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)
|
&& (bfd_section_flags (now_seg)
|
||||||
& (SEC_MERGE | SEC_STRINGS)) != 0)
|
& (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
|
/* ??? This is here for older versions of gcc that
|
||||||
test for gas string merge support with
|
test for gas string merge support with
|
||||||
@@ -1341,7 +1352,7 @@ obj_elf_section (int push)
|
|||||||
Unfortunately '@' begins a comment on arm.
|
Unfortunately '@' begins a comment on arm.
|
||||||
This isn't as_warn because gcc tests with
|
This isn't as_warn because gcc tests with
|
||||||
--fatal-warnings. */
|
--fatal-warnings. */
|
||||||
as_tsktsk (_("missing merge / string entity size, 1 assumed"));
|
as_tsktsk (_("missing section entity size, 1 assumed"));
|
||||||
entsize = 1;
|
entsize = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1350,15 +1361,17 @@ obj_elf_section (int push)
|
|||||||
SKIP_WHITESPACE ();
|
SKIP_WHITESPACE ();
|
||||||
if (entsize <= 0)
|
if (entsize <= 0)
|
||||||
{
|
{
|
||||||
as_warn (_("invalid merge / string entity size"));
|
as_warn (_("invalid section entity size"));
|
||||||
attr &= ~(SHF_MERGE | SHF_STRINGS);
|
attr &= ~(SHF_MERGE | SHF_STRINGS);
|
||||||
|
has_entsize = false;
|
||||||
entsize = 0;
|
entsize = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0 && inherit
|
else if (has_entsize && inherit
|
||||||
&& (bfd_section_flags (now_seg)
|
&& ((bfd_section_flags (now_seg)
|
||||||
& (SEC_MERGE | SEC_STRINGS)) != 0)
|
& (SEC_MERGE | SEC_STRINGS)) != 0
|
||||||
|
|| now_seg->entsize))
|
||||||
{
|
{
|
||||||
fetch_entsize:
|
fetch_entsize:
|
||||||
entsize = now_seg->entsize;
|
entsize = now_seg->entsize;
|
||||||
@@ -1369,6 +1382,7 @@ obj_elf_section (int push)
|
|||||||
entsize must be specified if SHF_MERGE is set. */
|
entsize must be specified if SHF_MERGE is set. */
|
||||||
as_warn (_("entity size for SHF_MERGE not specified"));
|
as_warn (_("entity size for SHF_MERGE not specified"));
|
||||||
attr &= ~(SHF_MERGE | SHF_STRINGS);
|
attr &= ~(SHF_MERGE | SHF_STRINGS);
|
||||||
|
has_entsize = false;
|
||||||
}
|
}
|
||||||
else if ((attr & SHF_STRINGS) != 0)
|
else if ((attr & SHF_STRINGS) != 0)
|
||||||
{
|
{
|
||||||
@@ -1378,6 +1392,11 @@ obj_elf_section (int push)
|
|||||||
compatibility. */
|
compatibility. */
|
||||||
entsize = 1;
|
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)
|
if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0 && type == SHT_NOBITS)
|
||||||
as_warn (_("bogus SHF_MERGE / SHF_STRINGS for SHT_NOBITS section"));
|
as_warn (_("bogus SHF_MERGE / SHF_STRINGS for SHT_NOBITS section"));
|
||||||
|
|||||||
@@ -7004,12 +7004,14 @@ section) in the same file.
|
|||||||
section is writable
|
section is writable
|
||||||
@item x
|
@item x
|
||||||
section is executable
|
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
|
@item M
|
||||||
section is mergeable
|
section is mergeable
|
||||||
@item S
|
@item S
|
||||||
section contains zero terminated strings
|
section contains zero terminated strings
|
||||||
@item G
|
|
||||||
section is a member of a section group
|
|
||||||
@item T
|
@item T
|
||||||
section is used for thread-local-storage
|
section is used for thread-local-storage
|
||||||
@item ?
|
@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
|
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.
|
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
|
Note: If both one of @var{M}, @var{S}, or @var{E} and @var{o} flags are present,
|
||||||
fields for the Merge/String flag should come first, like this:
|
then the type and entry size fields should come first, like this:
|
||||||
|
|
||||||
@smallexample
|
@smallexample
|
||||||
.section @var{name},"@var{flags}"Mo,@@@var{type},@var{entsize},@var{SymbolName}
|
.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
|
an alias for comdat
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
Note: Uf both one of @var{M} or @var{S} and @var{G} flags are present then the
|
Note: If both one of @var{M}, @var{S}, or @var{E} and @var{G} flags are present
|
||||||
fields for the Merge/String flag should come first, like this:
|
then the type and entry size fields should come first, like this:
|
||||||
|
|
||||||
@smallexample
|
@smallexample
|
||||||
.section @var{name} , "@var{flags}"MG, @@@var{type}, @var{entsize}, @var{GroupName}[, @var{linkage}]
|
.section @var{name} , "@var{flags}"MG, @@@var{type}, @var{entsize}, @var{GroupName}[, @var{linkage}]
|
||||||
|
|||||||
@@ -293,6 +293,7 @@ if { [is_elf_format] } then {
|
|||||||
run_dump_test "sh-link-zero"
|
run_dump_test "sh-link-zero"
|
||||||
run_dump_test "string"
|
run_dump_test "string"
|
||||||
run_dump_test "size"
|
run_dump_test "size"
|
||||||
|
run_dump_test "entsize"
|
||||||
run_dump_test "dwarf2-1" $dump_opts
|
run_dump_test "dwarf2-1" $dump_opts
|
||||||
run_dump_test "dwarf2-2" $dump_opts
|
run_dump_test "dwarf2-2" $dump_opts
|
||||||
run_dump_test "dwarf2-3" $dump_opts
|
run_dump_test "dwarf2-3" $dump_opts
|
||||||
|
|||||||
9
gas/testsuite/gas/elf/entsize.d
Normal file
9
gas/testsuite/gas/elf/entsize.d
Normal 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
|
||||||
8
gas/testsuite/gas/elf/entsize.s
Normal file
8
gas/testsuite/gas/elf/entsize.s
Normal 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
|
||||||
Reference in New Issue
Block a user