[binutils-gdb] gas: elf: Relax rules for SHF_STRING sections

Richard Earnshaw rearnsha@sourceware.org
Mon Jan 20 10:16:22 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=c3190b22b03ab147a048395546a8abfa7a4c47de

commit c3190b22b03ab147a048395546a8abfa7a4c47de
Author: Richard Earnshaw <rearnsha@arm.com>
Date:   Fri Jan 17 15:03:47 2025 +0000

    gas: elf: Relax rules for SHF_STRING sections
    
    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.

Diff:
---
 gas/config/obj-elf.c           | 14 ++++++++++++--
 gas/doc/as.texi                | 28 ++++++++++++++++++----------
 gas/testsuite/gas/elf/elf.exp  |  1 +
 gas/testsuite/gas/elf/string.d |  9 +++++++++
 gas/testsuite/gas/elf/string.s | 10 ++++++++++
 5 files changed, 50 insertions(+), 12 deletions(-)

diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 52080cb5bc1..6670b9add0f 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -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"));
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index c9f65a47125..d95ce9cf714 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -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:
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 5103880ccdf..1f42c3f3723 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -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
index 00000000000..6fcfe468af5
--- /dev/null
+++ b/gas/testsuite/gas/elf/string.d
@@ -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
index 00000000000..78c22f7496c
--- /dev/null
+++ b/gas/testsuite/gas/elf/string.s
@@ -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


More information about the Binutils-cvs mailing list