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
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;
*is_clone = false;
*inherit = 0;
while (len > 0)
{
@@ -923,6 +925,8 @@ obj_elf_parse_section_letters (char *str, size_t len,
len -= (end - str);
str = end;
}
else if (!attr && !*gnu_attr && (*str == '+' || *str == '-'))
*inherit = *str == '+' ? 1 : -1;
else
as_fatal ("%s", bad_msg);
}
@@ -1171,6 +1175,7 @@ obj_elf_section (int push)
if (*input_line_pointer == '"')
{
bool is_clone;
int inherit;
beg = demand_copy_C_string (&dummy);
if (beg == NULL)
@@ -1178,8 +1183,15 @@ obj_elf_section (int push)
ignore_rest_of_line ();
return;
}
attr |= obj_elf_parse_section_letters (beg, strlen (beg),
&is_clone, &gnu_attr);
attr = obj_elf_parse_section_letters (beg, strlen (beg), &is_clone,
&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 ();
if (*input_line_pointer == ',')
@@ -1224,6 +1236,9 @@ obj_elf_section (int push)
{
++input_line_pointer;
SKIP_WHITESPACE ();
if (inherit && *input_line_pointer == ','
&& (bfd_section_flags (now_seg) & SEC_MERGE) != 0)
goto fetch_entsize;
entsize = get_absolute_expression ();
SKIP_WHITESPACE ();
if (entsize < 0)
@@ -1233,6 +1248,12 @@ obj_elf_section (int push)
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)
{
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);
}
else if (inherit && *input_line_pointer == ','
&& (elf_section_flags (now_seg) & SHF_LINK_ORDER) != 0)
goto fetch_linked_to;
else
{
char c;
@@ -1260,6 +1284,17 @@ obj_elf_section (int push)
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)
{
@@ -1270,6 +1305,10 @@ obj_elf_section (int push)
if ((attr & SHF_GROUP) != 0 && *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 ();
if (match.group_name == NULL)
attr &= ~SHF_GROUP;
@@ -1286,6 +1325,14 @@ obj_elf_section (int push)
else if (startswith (name, ".gnu.linkonce"))
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)
{
as_warn (_("group name for SHF_GROUP not specified"));