From: Richard Earnshaw Date: Fri, 17 Jan 2025 15:03:47 +0000 (+0000) Subject: gas: elf: Relax rules for SHF_STRING sections X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c3190b22b03ab147a048395546a8abfa7a4c47de;p=thirdparty%2Fbinutils-gdb.git 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 --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