aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Earnshaw <rearnsha@arm.com>2025-01-17 15:03:47 +0000
committerRichard Earnshaw <rearnsha@arm.com>2025-01-20 10:07:15 +0000
commitc3190b22b03ab147a048395546a8abfa7a4c47de (patch)
treee8665d8f704a0f5fc9d8daf6ce7a1715ef9bdc6b
parentbf2da5d57d7532855e56538a4a7242c705b1d27d (diff)
downloadbinutils-c3190b22b03ab147a048395546a8abfa7a4c47de.zip
binutils-c3190b22b03ab147a048395546a8abfa7a4c47de.tar.gz
binutils-c3190b22b03ab147a048395546a8abfa7a4c47de.tar.bz2
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.
-rw-r--r--gas/config/obj-elf.c14
-rw-r--r--gas/doc/as.texi28
-rw-r--r--gas/testsuite/gas/elf/elf.exp1
-rw-r--r--gas/testsuite/gas/elf/string.d9
-rw-r--r--gas/testsuite/gas/elf/string.s10
5 files changed, 50 insertions, 12 deletions
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 52080cb..6670b9a 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 c9f65a4..d95ce9c 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 5103880..1f42c3f 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 0000000..6fcfe46
--- /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 0000000..78c22f7
--- /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