From cefaa117f7675ce690c0ec38c353e7e4195dedcb Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 25 Aug 2023 14:55:12 +0200 Subject: [PATCH] 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. --- gas/config/obj-elf.c | 53 ++++++++++++++++++++++-- gas/doc/as.texi | 12 ++++++ gas/testsuite/gas/elf/elf.exp | 5 +++ gas/testsuite/gas/elf/section30.d | 28 +++++++++++++ gas/testsuite/gas/elf/section30.s | 67 +++++++++++++++++++++++++++++++ 5 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 gas/testsuite/gas/elf/section30.d create mode 100644 gas/testsuite/gas/elf/section30.s diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 142f004f0b6..a9258ce334c 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")); diff --git a/gas/doc/as.texi b/gas/doc/as.texi index 15867dfcb5e..6a3e5eed39f 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -6818,6 +6818,12 @@ section is a member of a section group section is used for thread-local-storage @item ? 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 retained section (apply SHF_GNU_RETAIN to prevent linker garbage 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 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: @table @code diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp index 00eadc8c372..854c78aebd3 100644 --- a/gas/testsuite/gas/elf/elf.exp +++ b/gas/testsuite/gas/elf/elf.exp @@ -280,6 +280,11 @@ if { [is_elf_format] } then { run_dump_test "section27" run_dump_test "section28" 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 "size" run_dump_test "dwarf2-1" $dump_opts diff --git a/gas/testsuite/gas/elf/section30.d b/gas/testsuite/gas/elf/section30.d new file mode 100644 index 00000000000..821af1e2cd5 --- /dev/null +++ b/gas/testsuite/gas/elf/section30.d @@ -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 diff --git a/gas/testsuite/gas/elf/section30.s b/gas/testsuite/gas/elf/section30.s new file mode 100644 index 00000000000..aeda04c6514 --- /dev/null +++ b/gas/testsuite/gas/elf/section30.s @@ -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 -- 2.30.2