gas: Avoid section symbols as group signatures

Message ID 20260727110447.3174-1-kirill@korins.ky
State New
Headers
Series gas: Avoid section symbols as group signatures |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 fail Patch failed to apply

Commit Message

Kirill A. Korinsky July 27, 2026, 11:04 a.m. UTC
  When a COMDAT group signature matches its section name,
symbol_find_exact finds the existing section symbol. GAS then reuses
this unnamed STT_SECTION symbol as the group signature, although the
signature requires a distinct named symbol.

Reject section symbols when selecting an existing signature; GAS then
creates the usual named local STT_NOTYPE symbol.

This issue was discovered during the OpenBSD/sparc64 LLVM toolchain port
and the attempt to upstream its LLVM changes:
https://github.com/llvm/llvm-project/pull/207609

An LLD workaround for these objects was rejected upstream:
https://github.com/llvm/llvm-project/pull/209841

The LLD workaround was tested while building GCC 15.2.0 and GCC 16.1.0
on OpenBSD/sparc64 with the LLVM toolchain.
---
 gas/config/obj-elf.c           | 1 +
 gas/testsuite/gas/elf/elf.exp  | 1 +
 gas/testsuite/gas/elf/group2.d | 8 ++++++++
 gas/testsuite/gas/elf/group2.s | 2 ++
 4 files changed, 12 insertions(+)
 create mode 100644 gas/testsuite/gas/elf/group2.d
 create mode 100644 gas/testsuite/gas/elf/group2.s
  

Comments

Kirill A. Korinsky July 27, 2026, 4:56 p.m. UTC | #1
On Mon, 27 Jul 2026 13:04:47 +0200,
"Kirill A. Korinsky" <kirill@korins.ky> wrote:
> 
> When a COMDAT group signature matches its section name,
> symbol_find_exact finds the existing section symbol. GAS then reuses
> this unnamed STT_SECTION symbol as the group signature, although the
> signature requires a distinct named symbol.
> 
> Reject section symbols when selecting an existing signature; GAS then
> creates the usual named local STT_NOTYPE symbol.
> 
> This issue was discovered during the OpenBSD/sparc64 LLVM toolchain port
> and the attempt to upstream its LLVM changes:
> https://github.com/llvm/llvm-project/pull/207609
> 
> An LLD workaround for these objects was rejected upstream:
> https://github.com/llvm/llvm-project/pull/209841
> 
> The LLD workaround was tested while building GCC 15.2.0 and GCC 16.1.0
> on OpenBSD/sparc64 with the LLVM toolchain.
> ---
>  gas/config/obj-elf.c           | 1 +
>  gas/testsuite/gas/elf/elf.exp  | 1 +
>  gas/testsuite/gas/elf/group2.d | 8 ++++++++
>  gas/testsuite/gas/elf/group2.s | 2 ++
>  4 files changed, 12 insertions(+)
>  create mode 100644 gas/testsuite/gas/elf/group2.d
>  create mode 100644 gas/testsuite/gas/elf/group2.s
> 

I'd like to withdraw this patch because future tests proofs that it is not
complete and still needs some LLD side workaround, or future work in GAS
  

Patch

diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 337726191..ca0ce0039 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -2286,6 +2286,7 @@  elf_adjust_symtab (void)
 	 name of the group.  */
       sy = symbol_find_exact (group_name);
       if (!sy
+	  || symbol_section_p (sy)
 	  || (sy != symbol_lastP
 	      && (sy->sy_next == NULL
 		  || sy->sy_next->sy_previous != sy)))
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 4196fd7da..93929c982 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -116,6 +116,7 @@  if { [is_elf_format] } then {
     run_dump_test "group0c"
     run_dump_test "group1a"
     run_dump_test "group1b"
+    run_dump_test "group2"
     case $target_triplet in {
 	{ hppa64*-*-hpux* } { }
 	default {
diff --git a/gas/testsuite/gas/elf/group2.d b/gas/testsuite/gas/elf/group2.d
new file mode 100644
index 000000000..37dec8c7e
--- /dev/null
+++ b/gas/testsuite/gas/elf/group2.d
@@ -0,0 +1,8 @@ 
+#readelf: -sW
+#name: section group signature matching section name
+#source: group2.s
+#not-target: *-*-solaris*
+
+#...
+.*NOTYPE[ 	]+LOCAL[ 	]+DEFAULT[ 	]+[0-9]+[ 	]+\.foo
+#pass
diff --git a/gas/testsuite/gas/elf/group2.s b/gas/testsuite/gas/elf/group2.s
new file mode 100644
index 000000000..58dc83acb
--- /dev/null
+++ b/gas/testsuite/gas/elf/group2.s
@@ -0,0 +1,2 @@ 
+	.section       .foo,"axG",%progbits,.foo,comdat
+	.byte	1