aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2023-08-25 14:55:12 +0200
committerJan Beulich <jbeulich@suse.com>2023-08-25 14:55:12 +0200
commitcefaa117f7675ce690c0ec38c353e7e4195dedcb (patch)
tree70932f74748ffb22d3dde9f13a5667acc2064c30 /gas/config
parent7b793987b5e1f35a6a8a442da24ebd3f7dbf08f3 (diff)
downloadbinutils-cefaa117f7675ce690c0ec38c353e7e4195dedcb.zip
binutils-cefaa117f7675ce690c0ec38c353e7e4195dedcb.tar.gz
binutils-cefaa117f7675ce690c0ec38c353e7e4195dedcb.tar.bz2
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.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/obj-elf.c53
1 files changed, 50 insertions, 3 deletions
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 142f004..a9258ce 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -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"));