gas/ELF: allow "inheriting" section attributes and type
authorJan Beulich <jbeulich@suse.com>
Fri, 25 Aug 2023 12:55:12 +0000 (14:55 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 25 Aug 2023 12:55:12 +0000 (14:55 +0200)
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
gas/doc/as.texi
gas/testsuite/gas/elf/elf.exp
gas/testsuite/gas/elf/section30.d [new file with mode: 0644]
gas/testsuite/gas/elf/section30.s [new file with mode: 0644]

index 142f004f0b67c4cefa78afec59e9f5bed7bd5fad..a9258ce334cfcbc811d58b3681a0376f76847498 100644 (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"));
index 15867dfcb5e85f36e259d69c288b58f0afe56a3d..6a3e5eed39f58118d2a43f84d24dbbf3f9714fd2 100644 (file)
@@ -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
index 00eadc8c372d42673a10a42041a8fe3045d44402..854c78aebd34265510f8d6260dd73cda7550609c 100644 (file)
@@ -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 (file)
index 0000000..821af1e
--- /dev/null
@@ -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 (file)
index 0000000..aeda04c
--- /dev/null
@@ -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