s390: Add linker tests for references in discarded sections

Message ID 20261002145207.3018803-2-jremus@linux.ibm.com
State New
Headers
Series s390: Add linker tests for references in discarded sections |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Test passed

Commit Message

Jens Remus Oct. 2, 2026, 2:52 p.m. UTC
  Add test cases verifying the behavior when linking with references to
symbols in discarded sections.

Linking as PIE with a discarded section that contains a GOT reference
triggers a BFD assertion ((h->got.offset & 1) != 0) because the GOT
entry is allocated but never initialized.  Mark the PIE test as XFAIL.
The PDE test passes because no dynamic relocations are needed.  The
shared library test passes but documents the spurious R_390_NONE
relocations emitted for GOT and data references in discarded sections.

Inspired by aarch64 relr-discard-* and riscv discard-* tests.

ld/testsuite/
	* ld-s390/s390.exp: Run new discard-* tests.
	* ld-s390/discard.ld: New linker script.
	* ld-s390/discard.s: New test source.
	* ld-s390/discard-pde.d: New test for discarded sections in
	a position-dependent executable (PDE).
	* ld-s390/discard-pie.d: New test for discarded sections in
	a position-independent executable (PIE). (XFAIL)
	* ld-s390/discard-shared.d: New test for discarded sections in
	a shared library.

Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---

Notes (jremus):
    The plan is to address the XFAIL and superfluous R_390_NONE
    relocations with a future patch, implementing x86-64's solution
    using check_relocs and scan_relocs from x86 commit 3747999c6bd4
    ("ld: Extract _bfd_elf_link_iterate_on_relocs").

 ld/testsuite/ld-s390/discard-pde.d    |  6 +++
 ld/testsuite/ld-s390/discard-pie.d    | 13 ++++++
 ld/testsuite/ld-s390/discard-shared.d | 13 ++++++
 ld/testsuite/ld-s390/discard.ld       | 14 ++++++
 ld/testsuite/ld-s390/discard.s        | 61 +++++++++++++++++++++++++++
 ld/testsuite/ld-s390/s390.exp         |  6 +++
 6 files changed, 113 insertions(+)
 create mode 100644 ld/testsuite/ld-s390/discard-pde.d
 create mode 100644 ld/testsuite/ld-s390/discard-pie.d
 create mode 100644 ld/testsuite/ld-s390/discard-shared.d
 create mode 100644 ld/testsuite/ld-s390/discard.ld
 create mode 100644 ld/testsuite/ld-s390/discard.s
  

Patch

diff --git a/ld/testsuite/ld-s390/discard-pde.d b/ld/testsuite/ld-s390/discard-pde.d
new file mode 100644
index 000000000000..8fc7b005227b
--- /dev/null
+++ b/ld/testsuite/ld-s390/discard-pde.d
@@ -0,0 +1,6 @@ 
+#source: discard.s
+#as: -m64
+#ld: -melf64_s390 -T discard.ld
+#readelf: -rW
+
+There are no relocations in this file.
diff --git a/ld/testsuite/ld-s390/discard-pie.d b/ld/testsuite/ld-s390/discard-pie.d
new file mode 100644
index 000000000000..7c8be9522c77
--- /dev/null
+++ b/ld/testsuite/ld-s390/discard-pie.d
@@ -0,0 +1,13 @@ 
+#source: discard.s
+#as: -m64
+#ld: -pie -melf64_s390 -T discard.ld
+#readelf: -rW
+#xfail: s390x-*-*
+
+# FIXME: Linking as PIE with discarded sections containing GOT references
+# triggers an assertion in elfNN-s390.c (h->got.offset & 1) because the
+# GOT entry for a locally-defined symbol is allocated by check_relocs
+# before /DISCARD/ is applied, but never initialized by relocate_section
+# when its only reference is in a discarded section.
+# The proper fix is to split check_relocs into a pre- and post-/DISCARD/
+# phase as x86-64 does with check_relocs and scan_relocs.
diff --git a/ld/testsuite/ld-s390/discard-shared.d b/ld/testsuite/ld-s390/discard-shared.d
new file mode 100644
index 000000000000..317895e6dd27
--- /dev/null
+++ b/ld/testsuite/ld-s390/discard-shared.d
@@ -0,0 +1,13 @@ 
+#source: discard.s
+#as: -m64
+#ld: -shared -melf64_s390 -T discard.ld
+#readelf: -rW
+
+Relocation section '\.rela\.dyn' at offset 0x[0-9a-f]+ contains 6 entries:
+    Offset             Info             Type               Symbol's Value  Symbol's Name \+ Addend
+0000000000000000  0000000000000000 R_390_NONE                                0
+0000000000000000  0000000000000000 R_390_NONE                                0
+0000000000000000  0000000000000000 R_390_NONE                                0
+0000000000000000  0000000000000000 R_390_NONE                                0
+0000000000000000  0000000000000000 R_390_NONE                                0
+0000000000020020  000000030000000a R_390_GLOB_DAT         000000000001000c sym_global \+ 0
diff --git a/ld/testsuite/ld-s390/discard.ld b/ld/testsuite/ld-s390/discard.ld
new file mode 100644
index 000000000000..471a5aed88f9
--- /dev/null
+++ b/ld/testsuite/ld-s390/discard.ld
@@ -0,0 +1,14 @@ 
+OUTPUT_ARCH(s390:64-bit)
+ENTRY(_start)
+SECTIONS
+{
+  /DISCARD/ : { *(.discard.*) }
+
+  . = 0x10000;
+  .text : { *(.text) }
+  . = 0x20000;
+  .got     : { *(.got) }
+  .got.plt : { *(.got.plt) }
+  . = 0x30000;
+  .data : { *(.data) *(.data.*) }
+}
diff --git a/ld/testsuite/ld-s390/discard.s b/ld/testsuite/ld-s390/discard.s
new file mode 100644
index 000000000000..c9ad385003b0
--- /dev/null
+++ b/ld/testsuite/ld-s390/discard.s
@@ -0,0 +1,61 @@ 
+# Test references in discarded sections.
+
+.text
+.align 8
+.global _start
+_start:
+	nop
+
+sym_local:
+	nop
+
+.global sym_hidden
+.hidden sym_hidden
+sym_hidden:
+	nop
+
+.global sym_global
+sym_global:
+	nop
+
+.global sym_global_abs
+.set sym_global_abs, 42
+
+.global sym_weak_undef
+.weak sym_weak_undef
+
+.section .discard.got_local,"ax"
+	lgrl	%r0, sym_local@GOTENT
+
+.section .discard.got_global,"ax"
+	lgrl	%r0, sym_global@GOTENT
+
+.section .discard.local,"a"
+.align 8
+discard_local:
+	.quad	sym_local
+
+.section .discard.hidden,"a"
+.align 8
+discard_hidden:
+	.quad	sym_hidden
+
+.section .discard.global,"a"
+.align 8
+discard_global:
+	.quad	sym_global
+
+.section .discard.global_abs,"a"
+.align 8
+discard_global_abs:
+	.quad	sym_global_abs
+
+.section .discard.weak_undef,"a"
+.align 8
+discard_weak_undef:
+	.quad	sym_weak_undef
+
+.section .discard._DYNAMIC,"a"
+.align 8
+discard_DYNAMIC:
+	.quad	_DYNAMIC
diff --git a/ld/testsuite/ld-s390/s390.exp b/ld/testsuite/ld-s390/s390.exp
index 80536e2e39a0..ca443673bc5e 100644
--- a/ld/testsuite/ld-s390/s390.exp
+++ b/ld/testsuite/ld-s390/s390.exp
@@ -184,11 +184,17 @@  if { [istarget "s390-*-*"] || [istarget "s390x-*-*"] } {
 }
 
 if [istarget "s390x-*-*"] {
+    global NOPIE_LDFLAGS
+
     run_ld_link_tests $s390xtests
 
     run_dump_test "weakundef-1b"
     run_dump_test "weakundef-2b"
 
+    run_dump_test "discard-pde" [list [list ld $NOPIE_LDFLAGS]]
+    run_dump_test "discard-pie"
+    run_dump_test "discard-shared"
+
     if { ![skip_sframe_tests] } {
 	run_dump_test "sframe-simple-1"
 	run_dump_test "sframe-plt-1"