]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: elf: Relax rules for SHF_STRING sections
authorRichard Earnshaw <rearnsha@arm.com>
Fri, 17 Jan 2025 15:03:47 +0000 (15:03 +0000)
committerRichard Earnshaw <rearnsha@arm.com>
Mon, 20 Jan 2025 10:07:15 +0000 (10:07 +0000)
Commit af3394d97a8c5187085c0eec5fb03e8da88db5fb allowed sections
declared with "S" (SHF_STRING) to specify the entity size, but then
would warn if the entity size was omitted, as with the old syntax.

Unfortunately, since specifying the entity size is incompatible with
binutils 2.43 or earlier, this makes it impossible to specify a
strings section in source code without generating an assembly warning
(the new syntax isn't supported in older assemblers and the old syntax
generates warnings).

Nevertheless, the old code was wrong in that it did not set the entity
size at all, in contravention of the ELF specification (though to date
there are no known cases where this mattered outside of mergeable
sections).

Fix this by permitting the original syntax without a warning again,
but by defaulting the entity size to 1.  This is compatible with the
most common case of strings being byte-based.

Added some tests for the various flavours of declaration that we
support.

gas/config/obj-elf.c
gas/doc/as.texi
gas/testsuite/gas/elf/elf.exp
gas/testsuite/gas/elf/string.d [new file with mode: 0644]
gas/testsuite/gas/elf/string.s [new file with mode: 0644]

index 52080cb5bc1afb091a7680f932579132aaf592ac..6670b9add0f76ddc71bd0c50892ed8ebb2ee2cee 100644 (file)
@@ -1340,11 +1340,21 @@ obj_elf_section (int push)
            fetch_entsize:
              entsize = now_seg->entsize;
            }
-         else if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0)
+         else if ((attr & SHF_MERGE) != 0)
            {
-             as_warn (_("entity size for SHF_MERGE / SHF_STRINGS not specified"));
+             /* ??? Perhaps we should error here.  The manual says that
+                entsize must be specified if SHF_MERGE is set.  */
+             as_warn (_("entity size for SHF_MERGE not specified"));
              attr &= ~(SHF_MERGE | SHF_STRINGS);
            }
+         else if ((attr & SHF_STRINGS) != 0)
+           {
+             /* Ideally we would warn about this, but older versions
+                of gas did not permit an entity size to be specified,
+                so we have to default this silently for
+                compatibility.  */
+             entsize = 1;
+           }
 
          if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0 && type == SHT_NOBITS)
            as_warn (_("bogus SHF_MERGE / SHF_STRINGS for SHT_NOBITS section"));
index c9f65a471257046c8b41803efd636735802c6e93..d95ce9cf714f6fd4b8a517df4c73db06f8a1392f 100644 (file)
@@ -7011,7 +7011,16 @@ Note - some sections, eg @code{.text} and @code{.data} are considered to be
 special and have fixed types.  Any attempt to declare them with a different
 type will generate an error from the assembler.
 
-If @var{flags} contains the @code{M} and/or @code{S} symbol then the @var{type}
+If @var{flags} contains the @code{S} flag then the section contains
+zero-terminated strings.  The size of each character in the string is specified
+in octets by the entity size, @var{entsize}, which defaults to @code{1}, but
+can be set using the syntax
+
+@smallexample
+.section @var{name}, "@var{flags}"S[, @@@var{type}] [, @var{entsize}]
+@end smallexample
+
+If @var{flags} contains the @code{M} flag then the @var{type}
 argument must be specified as well as an extra argument---@var{entsize}---like
 this:
 
@@ -7019,15 +7028,14 @@ this:
 .section @var{name} , "@var{flags}"M, @@@var{type}, @var{entsize}
 @end smallexample
 
-Sections with the @code{M} flag but not @code{S} flag must contain fixed size
-constants, each @var{entsize} octets long. Sections with @code{S} must contain
-zero terminated strings where each character is @var{entsize} bytes long. For
-@code{M} sections the linker may remove duplicates within sections with
-the same name, same entity size and same flags.  @var{entsize} must be an
-absolute expression.  For sections with both @code{M} and @code{S}, a string
-which is a suffix of a larger string is considered a duplicate.  Thus
-@code{"def"} will be merged with @code{"abcdef"};  A reference to the first
-@code{"def"} will be changed to a reference to @code{"abcdef"+3}.
+Sections with the @code{M} flag but not the @code{S} flag must contain fixed
+size constants, each @var{entsize} octets long.  For @code{M} sections the
+linker may remove duplicates within sections with the same name, same entity
+size and same flags.  @var{entsize} must be an absolute expression.  For
+sections with both @code{M} and @code{S}, a string which is a suffix of a
+larger string is considered a duplicate.  Thus @code{"def"} will be merged with
+@code{"abcdef"}; A reference to the first @code{"def"} will be changed to a
+reference to @code{"abcdef"+3}.
 
 If @var{flags} contains the @code{o} flag, then the @var{type} argument
 must be present along with an additional field like this:
index 5103880ccdfecf49d952f3eb1ba499a4b891e3fd..1f42c3f372326f630eadbd7f83068e4f25c5dcca 100644 (file)
@@ -292,6 +292,7 @@ if { [is_elf_format] } then {
     run_dump_test "section29"
     run_dump_test "section30" $dump_opts
     run_dump_test "sh-link-zero"
+    run_dump_test "string"
     run_dump_test "size"
     run_dump_test "dwarf2-1" $dump_opts
     run_dump_test "dwarf2-2" $dump_opts
diff --git a/gas/testsuite/gas/elf/string.d b/gas/testsuite/gas/elf/string.d
new file mode 100644 (file)
index 0000000..6fcfe46
--- /dev/null
@@ -0,0 +1,9 @@
+#readelf: -SW
+#name: string sections
+
+#...
+[      ]*\[.*\][       ]+\.str1[       ]+PROGBITS[     ]+0+[   ]+[0-9a-f]+[    ]+[0-9a-f]+[    ]+01[   ]+S[    ]+.*
+[      ]*\[.*\][       ]+\.str2[       ]+PROGBITS[     ]+0+[   ]+[0-9a-f]+[    ]+[0-9a-f]+[    ]+01[   ]+S[    ]+.*
+[      ]*\[.*\][       ]+\.str3[       ]+PROGBITS[     ]+0+[   ]+[0-9a-f]+[    ]+[0-9a-f]+[    ]+01[   ]+S[    ]+.*
+[      ]*\[.*\][       ]+\.str4[       ]+PROGBITS[     ]+0+[   ]+[0-9a-f]+[    ]+[0-9a-f]+[    ]+02[   ]+S[    ]+.*
+#pass
diff --git a/gas/testsuite/gas/elf/string.s b/gas/testsuite/gas/elf/string.s
new file mode 100644 (file)
index 0000000..78c22f7
--- /dev/null
@@ -0,0 +1,10 @@
+# Test extended forms of string section.  Only the first of these was supported
+# in binutils 2.43 and earlier, but it failed to set the entity size.  
+       .section .str1,"S"
+       .asciz "abc"
+       .section .str2,"S",1
+       .asciz "def"
+       .section .str3,"S",%progbits
+       .asciz "ghi"
+       .section .str4,"S",%progbits,2
+       .short 32, 0