gas/ELF: allow "inheriting" section attributes and type

While --sectname-subst is nice, it isn't enough to e.g. mimic
-f{function,data}-sections in assembly code, when such use is to be
optional (e.g. dependent upon some configuration setting).

Assign meaning to '+' and '-' as section attribute letters, allowing
to inherit the prior section's attributes (and possibly type) along
with adding or removing some. Note that documenting the interaction
with '?' as undefined is a precautionary measure.

While touching the function invocation, stop using |= on the result of
obj_elf_parse_section_letters(): "attr" is firmly zero ahead of the
call.
This commit is contained in:
Jan Beulich
2023-08-25 14:55:12 +02:00
parent 7b793987b5
commit cefaa117f7
5 changed files with 162 additions and 3 deletions

View File

@@ -822,10 +822,12 @@ obj_elf_change_section (const char *name,
static bfd_vma static bfd_vma
obj_elf_parse_section_letters (char *str, size_t len, obj_elf_parse_section_letters (char *str, size_t len,
bool *is_clone, bfd_vma *gnu_attr) bool *is_clone, int *inherit, bfd_vma *gnu_attr)
{ {
bfd_vma attr = 0; bfd_vma attr = 0;
*is_clone = false; *is_clone = false;
*inherit = 0;
while (len > 0) while (len > 0)
{ {
@@ -923,6 +925,8 @@ obj_elf_parse_section_letters (char *str, size_t len,
len -= (end - str); len -= (end - str);
str = end; str = end;
} }
else if (!attr && !*gnu_attr && (*str == '+' || *str == '-'))
*inherit = *str == '+' ? 1 : -1;
else else
as_fatal ("%s", bad_msg); as_fatal ("%s", bad_msg);
} }
@@ -1171,6 +1175,7 @@ obj_elf_section (int push)
if (*input_line_pointer == '"') if (*input_line_pointer == '"')
{ {
bool is_clone; bool is_clone;
int inherit;
beg = demand_copy_C_string (&dummy); beg = demand_copy_C_string (&dummy);
if (beg == NULL) if (beg == NULL)
@@ -1178,8 +1183,15 @@ obj_elf_section (int push)
ignore_rest_of_line (); ignore_rest_of_line ();
return; return;
} }
attr |= obj_elf_parse_section_letters (beg, strlen (beg), attr = obj_elf_parse_section_letters (beg, strlen (beg), &is_clone,
&is_clone, &gnu_attr); &inherit, &gnu_attr);
if (inherit > 0)
attr |= elf_section_flags (now_seg);
else if (inherit < 0)
attr = elf_section_flags (now_seg) & ~attr;
if (inherit)
type = elf_section_type (now_seg);
SKIP_WHITESPACE (); SKIP_WHITESPACE ();
if (*input_line_pointer == ',') if (*input_line_pointer == ',')
@@ -1224,6 +1236,9 @@ obj_elf_section (int push)
{ {
++input_line_pointer; ++input_line_pointer;
SKIP_WHITESPACE (); SKIP_WHITESPACE ();
if (inherit && *input_line_pointer == ','
&& (bfd_section_flags (now_seg) & SEC_MERGE) != 0)
goto fetch_entsize;
entsize = get_absolute_expression (); entsize = get_absolute_expression ();
SKIP_WHITESPACE (); SKIP_WHITESPACE ();
if (entsize < 0) if (entsize < 0)
@@ -1233,6 +1248,12 @@ obj_elf_section (int push)
entsize = 0; entsize = 0;
} }
} }
else if ((attr & SHF_MERGE) != 0 && inherit
&& (bfd_section_flags (now_seg) & SEC_MERGE) != 0)
{
fetch_entsize:
entsize = now_seg->entsize;
}
else if ((attr & SHF_MERGE) != 0) else if ((attr & SHF_MERGE) != 0)
{ {
as_warn (_("entity size for SHF_MERGE not specified")); as_warn (_("entity size for SHF_MERGE not specified"));
@@ -1248,6 +1269,9 @@ obj_elf_section (int push)
{ {
linked_to_section_index = strtoul (input_line_pointer, & input_line_pointer, 0); linked_to_section_index = strtoul (input_line_pointer, & input_line_pointer, 0);
} }
else if (inherit && *input_line_pointer == ','
&& (elf_section_flags (now_seg) & SHF_LINK_ORDER) != 0)
goto fetch_linked_to;
else else
{ {
char c; char c;
@@ -1260,6 +1284,17 @@ obj_elf_section (int push)
match.linked_to_symbol_name = xmemdup0 (beg, length); match.linked_to_symbol_name = xmemdup0 (beg, length);
} }
} }
else if ((attr & SHF_LINK_ORDER) != 0 && inherit
&& (elf_section_flags (now_seg) & SHF_LINK_ORDER) != 0)
{
fetch_linked_to:
if (now_seg->map_head.linked_to_symbol_name)
match.linked_to_symbol_name =
now_seg->map_head.linked_to_symbol_name;
else
linked_to_section_index =
elf_section_data (now_seg)->this_hdr.sh_link;
}
if ((attr & SHF_GROUP) != 0 && is_clone) if ((attr & SHF_GROUP) != 0 && is_clone)
{ {
@@ -1270,6 +1305,10 @@ obj_elf_section (int push)
if ((attr & SHF_GROUP) != 0 && *input_line_pointer == ',') if ((attr & SHF_GROUP) != 0 && *input_line_pointer == ',')
{ {
++input_line_pointer; ++input_line_pointer;
SKIP_WHITESPACE ();
if (inherit && *input_line_pointer == ','
&& (elf_section_flags (now_seg) & SHF_GROUP) != 0)
goto fetch_group;
match.group_name = obj_elf_section_name (); match.group_name = obj_elf_section_name ();
if (match.group_name == NULL) if (match.group_name == NULL)
attr &= ~SHF_GROUP; attr &= ~SHF_GROUP;
@@ -1286,6 +1325,14 @@ obj_elf_section (int push)
else if (startswith (name, ".gnu.linkonce")) else if (startswith (name, ".gnu.linkonce"))
linkonce = 1; linkonce = 1;
} }
else if ((attr & SHF_GROUP) != 0 && inherit
&& (elf_section_flags (now_seg) & SHF_GROUP) != 0)
{
fetch_group:
match.group_name = elf_group_name (now_seg);
linkonce =
(bfd_section_flags (now_seg) & SEC_LINK_ONCE) != 0;
}
else if ((attr & SHF_GROUP) != 0) else if ((attr & SHF_GROUP) != 0)
{ {
as_warn (_("group name for SHF_GROUP not specified")); as_warn (_("group name for SHF_GROUP not specified"));

View File

@@ -6818,6 +6818,12 @@ section is a member of a section group
section is used for thread-local-storage section is used for thread-local-storage
@item ? @item ?
section is a member of the previously-current section's group, if any section is a member of the previously-current section's group, if any
@item +
section inherits attributes and (unless explicitly specified) type from the
previously-current section, adding other attributes as specified
@item -
section inherits attributes and (unless explicitly specified) type from the
previously-current section, removing other attributes as specified
@item R @item R
retained section (apply SHF_GNU_RETAIN to prevent linker garbage retained section (apply SHF_GNU_RETAIN to prevent linker garbage
collection, GNU ELF extension) collection, GNU ELF extension)
@@ -6839,6 +6845,12 @@ section may have the executable (@code{x}) flag added. Also note that the
@code{.attach_to_group} directive can be used to add a section to a group even @code{.attach_to_group} directive can be used to add a section to a group even
if the section was not originally declared to be part of that group. if the section was not originally declared to be part of that group.
Note further that @code{+} and @code{-} need to come first and can only take
the effect described here unless overridden by a target. The attributes
inherited are those in effect at the time the directive is processed.
Attributes added later (see above) will not be inherited. Using either
together with @code{?} is undefined at this point.
The optional @var{type} argument may contain one of the following constants: The optional @var{type} argument may contain one of the following constants:
@table @code @table @code

View File

@@ -280,6 +280,11 @@ if { [is_elf_format] } then {
run_dump_test "section27" run_dump_test "section27"
run_dump_test "section28" run_dump_test "section28"
run_dump_test "section29" run_dump_test "section29"
if { ![istarget "rx-*-*"] } then {
run_dump_test "section30"
} else {
run_dump_test "section30" {{as -muse-conventional-section-names}}
}
run_dump_test "sh-link-zero" run_dump_test "sh-link-zero"
run_dump_test "size" run_dump_test "size"
run_dump_test "dwarf2-1" $dump_opts run_dump_test "dwarf2-1" $dump_opts

View File

@@ -0,0 +1,28 @@
#as: --sectname-subst
#readelf: -SW
#name: --sectname-subst plus section attr/type inherting
# Targets setting NO_PSEUDO_DOT don't allow macros of certain names.
#notarget: m681*-*-* m68hc1*-*-* s12z-*-* spu-*-* xgate-*-* z80-*-*
#...
\[..\] \.group +GROUP +[0-9a-f]+ [0-9a-f]+ 0+c 04 +[1-9][0-9]* +[1-9][0-9]* +4
\[..\] \.text +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+0 00 AX 0 0 +[1-9][0-9]*
\[..\] \.data +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+0 00 WA 0 0 +[1-9][0-9]*
\[..\] \.bss +NOBITS +[0-9a-f]+ [0-9a-f]+ 0+0 00 WA 0 0 +[1-9][0-9]*
#...
\[..\] \.text\.func1 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
\[..\] \.text\.func2 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
\[..\] \.data\.data1 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+1 00 WA 0 0 1
#...
\[..\] \.bss\.data2 +NOBITS +[0-9a-f]+ [0-9a-f]+ 0+2 00 WA 0 0 1
\[..\] \.rodata +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+0 00 A 0 0 1
\[..\] \.rodata\.data3 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+3 00 A 0 0 1
\[..\] \.rodata\.str1\.1 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+0 01 AMS 0 0 1
\[..\] \.rodata\.str1\.1\.str1 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+8 01 AMS 0 0 1
\[..\] \.rodata\.2 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+0 00 AL [1-9] 0 1
\[..\] \.rodata\.2\.data4 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+4 00 AL [1-9] 0 1
\[..\] \.bss\.data5 +NOBITS +[0-9a-f]+ [0-9a-f]+ 0+5 00 WA 0 0 1
\[..\] \.rodata\.3 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+0 00 AG 0 0 1
\[..\] \.rodata\.3\.data6 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+6 00 AG 0 0 1
\[..\] \.bss\.data7 +NOBITS +[0-9a-f]+ [0-9a-f]+ 0+7 00 WA 0 0 1
#pass

View File

@@ -0,0 +1,67 @@
.macro func name:req
.pushsection %S.\name, "+"
.type \name, %function
.global \name
.hidden \name
\name:
.endm
.macro data name:req
.pushsection %S.\name, "+"
.type \name, %object
\name:
.endm
.macro end name:req
.size \name, . - \name
.popsection
.endm
.text
func func1
.nop
end func1
func func2
.nop
.nop
end func2
.data
data data1
.byte 1
end data1
.section .bss
data data2
.skip 2
end data2
.section .rodata, "a", %progbits
data data3
.byte 3, 3, 3
end data3
.section .rodata.str1.1, "aMS", %progbits, 1
data str1
.asciz "string1"
end str1
.section .rodata.2, "ao", %progbits, func1
data data4
.byte 4, 4, 4, 4
end data4
.pushsection .bss.data5, "-o", %nobits
.type data5, %object
data5: .fill 5
end data5
.section .rodata.3, "aG", %progbits, sig1, comdat
data data6
.byte 6, 6, 6, 6, 6, 6
end data6
.pushsection .bss.data7, "-G", %nobits
.type data7, %object
data7: .skip 7
end data7