[PATCH 2/2] s390: Do not rewrite insns and their relocs in linker if --no-relax
Jens Remus
jremus@linux.ibm.com
Wed Oct 15 16:17:31 GMT 2025
Under certain conditions the linker rewrites:
- GOT access using lgrl to larl, changing the GOTENT to a PC32DBL reloc
- GOT access using lg to larl, changing the GOT20 to a PC32DBL reloc
- Relative long addressing instructions of weak symbols, which
definitively resolve to zero to either (1) load address of zero,
(2) a NOP, or (3) a trapping instruction, changing the relocation to
a NONE reloc.
Suppress rewriting of non-TLS instructions and related relocations in
linker if option --no-relax is specified. This aligns with LLVM linker
behavior on s390.
Like x86-64 do not actually enable the linker relaxation option by
default, as other targets would do using ENABLE_RELAXATION or
TARGET_ENABLE_RELAXATION in their linker emulation scripts. Instead
perform linker instruction/relocation rewrites by default unless linker
option --no-relax is explicitly specified by the user. This ensures no
functional change unless --no-relax is used.
bfd/
* elf64-s390.c (elf_s390_relocate_section): Do not rewrite
non-TLS instructions and related relocations if --no-relax.
* elf32-s390.c (elf_s390_relocate_section): Likewise.
ld/testsuite/
* ld-s390/s390.exp: New tests. Same as gotreloc_*-1a and
weakundef-*a, but with linker option --no-relax, to verify
suppression of linker non-TLS insn and reloc rewrites.
* ld-s390/gotreloc_31-1b.dd: Likewise.
* ld-s390/gotreloc_31-no-pie-1b.dd: Likewise.
* ld-s390/gotreloc_64-no-pie-1b.dd: Likewise.
* ld-s390/gotreloc_64-norelro-1b.dd: Likewise.
* ld-s390/gotreloc_64-relro-1b.dd: Likewise.
* ld-s390/weakundef-1b.d: Likewise. Check for expected reloc
overflows.
* ld-s390/weakundef-2b.d: Likewise.
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---
bfd/elf32-s390.c | 11 ++++++--
bfd/elf64-s390.c | 15 ++++++++--
ld/testsuite/ld-s390/gotreloc_31-1b.dd | 20 +++++++++++++
ld/testsuite/ld-s390/gotreloc_31-no-pie-1b.dd | 20 +++++++++++++
ld/testsuite/ld-s390/gotreloc_64-no-pie-1b.dd | 19 +++++++++++++
.../ld-s390/gotreloc_64-norelro-1b.dd | 19 +++++++++++++
ld/testsuite/ld-s390/gotreloc_64-relro-1b.dd | 19 +++++++++++++
ld/testsuite/ld-s390/s390.exp | 28 +++++++++++++++++++
ld/testsuite/ld-s390/weakundef-1b.d | 12 ++++++++
ld/testsuite/ld-s390/weakundef-2b.d | 7 +++++
10 files changed, 165 insertions(+), 5 deletions(-)
create mode 100644 ld/testsuite/ld-s390/gotreloc_31-1b.dd
create mode 100644 ld/testsuite/ld-s390/gotreloc_31-no-pie-1b.dd
create mode 100644 ld/testsuite/ld-s390/gotreloc_64-no-pie-1b.dd
create mode 100644 ld/testsuite/ld-s390/gotreloc_64-norelro-1b.dd
create mode 100644 ld/testsuite/ld-s390/gotreloc_64-relro-1b.dd
create mode 100644 ld/testsuite/ld-s390/weakundef-1b.d
create mode 100644 ld/testsuite/ld-s390/weakundef-2b.d
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
index ce3faa023f33..0d04663756a0 100644
--- a/bfd/elf32-s390.c
+++ b/bfd/elf32-s390.c
@@ -2059,6 +2059,7 @@ elf_s390_relocate_section (bfd *output_bfd,
int tls_type;
asection *base_got = htab->elf.sgot;
bool resolved_to_zero;
+ bool relax;
r_type = ELF32_R_TYPE (rel->r_info);
if (r_type == (int) R_390_GNU_VTINHERIT
@@ -2154,6 +2155,11 @@ elf_s390_relocate_section (bfd *output_bfd,
resolved_to_zero = (h != NULL
&& UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
+ /* Rewrite instructions and related relocations if (1) relaxation
+ disabled by default, (2) enabled by target, or (3) enabled by
+ user. Suppress rewriting if linker option --no-relax is used. */
+ relax = info->disable_target_specific_optimizations <= 1;
+
switch (r_type)
{
case R_390_GOTPLT12:
@@ -2261,8 +2267,9 @@ elf_s390_relocate_section (bfd *output_bfd,
h->got.offset |= 1;
}
- if ((h->def_regular
- && SYMBOL_REFERENCES_LOCAL (info, h))
+ if (relax
+ && h->def_regular
+ && SYMBOL_REFERENCES_LOCAL (info, h)
/* lrl rx,sym@GOTENT -> larl rx, sym */
&& ((r_type == R_390_GOTENT
&& (bfd_get_16 (input_bfd,
diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index af36e192f59d..16daf981e1de 100644
--- a/bfd/elf64-s390.c
+++ b/bfd/elf64-s390.c
@@ -2296,6 +2296,7 @@ elf_s390_relocate_section (bfd *output_bfd,
bfd_reloc_status_type r;
int tls_type;
bool resolved_to_zero;
+ bool relax;
r_type = ELF64_R_TYPE (rel->r_info);
if (r_type == (int) R_390_GNU_VTINHERIT
@@ -2395,6 +2396,11 @@ elf_s390_relocate_section (bfd *output_bfd,
resolved_to_zero = (h != NULL
&& UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
+ /* Rewrite instructions and related relocations if (1) relaxation
+ disabled by default, (2) enabled by target, or (3) enabled by
+ user. Suppress rewriting if linker option --no-relax is used. */
+ relax = info->disable_target_specific_optimizations <= 1;
+
switch (r_type)
{
case R_390_GOTPLT12:
@@ -2517,7 +2523,8 @@ elf_s390_relocate_section (bfd *output_bfd,
reference using larl we have to make sure that
the symbol is 1. properly aligned and 2. it is no
ABS symbol or will become one. */
- if (h->def_regular
+ if (relax
+ && h->def_regular
&& SYMBOL_REFERENCES_LOCAL (info, h)
/* lgrl rx,sym@GOTENT -> larl rx, sym */
&& ((r_type == R_390_GOTENT
@@ -2667,7 +2674,8 @@ elf_s390_relocate_section (bfd *output_bfd,
either a load address of 0 or a trapping insn.
This prevents the PLT32DBL relocation from overflowing in
case the binary will be loaded at 4GB or more. */
- if (h->root.type == bfd_link_hash_undefweak
+ if (relax
+ && h->root.type == bfd_link_hash_undefweak
&& !h->root.linker_def
&& (bfd_link_executable (info)
|| ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
@@ -2782,7 +2790,8 @@ elf_s390_relocate_section (bfd *output_bfd,
either a load address of 0, a NOP, or a trapping insn.
This prevents the PC32DBL relocation from overflowing in
case the binary will be loaded at 4GB or more. */
- if (h != NULL
+ if (relax
+ && h != NULL
&& h->root.type == bfd_link_hash_undefweak
&& !h->root.linker_def
&& (bfd_link_executable (info)
diff --git a/ld/testsuite/ld-s390/gotreloc_31-1b.dd b/ld/testsuite/ld-s390/gotreloc_31-1b.dd
new file mode 100644
index 000000000000..9513e16e113e
--- /dev/null
+++ b/ld/testsuite/ld-s390/gotreloc_31-1b.dd
@@ -0,0 +1,20 @@
+
+tmpdir/gotreloc_31-1b: file format elf32-s390
+
+Disassembly of section .text:
+
+.* <foo>:
+.*: c4 18 00 00 08 56 [ ]*lgrl %r1,11b4 <_GLOBAL_OFFSET_TABLE_\+0x14>
+[ ]*.*: R_390_GOTENT bar\+0x2
+.*: e3 10 c0 14 00 04 [ ]*lg %r1,20\(%r12\)
+[ ]*.*: R_390_GOT20 bar
+.*: c4 1d 00 00 08 50 [ ]*lrl %r1,11b4 <_GLOBAL_OFFSET_TABLE_\+0x14>
+[ ]*.*: R_390_GOTENT bar\+0x2
+.*: 58 10 c0 14 [ ]*l %r1,20\(%r12\)
+[ ]*.*: R_390_GOT12 bar
+.*: e3 10 c0 14 00 58 [ ]*ly %r1,20\(%r12\)
+[ ]*.*: R_390_GOT20 bar
+.*: c4 18 00 00 08 46 [ ]*lgrl %r1,11b0 <_GLOBAL_OFFSET_TABLE_\+0x10>
+[ ]*.*: R_390_GOTENT _GLOBAL_OFFSET_TABLE_\+0x2
+.*: c4 18 00 00 08 41 [ ]*lgrl %r1,11ac <_GLOBAL_OFFSET_TABLE_\+0xc>
+[ ]*.*: R_390_GOTENT misaligned_sym\+0x2
diff --git a/ld/testsuite/ld-s390/gotreloc_31-no-pie-1b.dd b/ld/testsuite/ld-s390/gotreloc_31-no-pie-1b.dd
new file mode 100644
index 000000000000..5688e4740b7a
--- /dev/null
+++ b/ld/testsuite/ld-s390/gotreloc_31-no-pie-1b.dd
@@ -0,0 +1,20 @@
+
+tmpdir/gotreloc_31-1b: file format elf32-s390
+
+Disassembly of section .text:
+
+.* <foo>:
+.*: c4 18 00 00 08 1e [ ]*lgrl %r1,4010b0 <_GLOBAL_OFFSET_TABLE_\+0x14>
+[ ]*.*: R_390_GOTENT bar\+0x2
+.*: e3 10 c0 14 00 04 [ ]*lg %r1,20\(%r12\)
+[ ]*.*: R_390_GOT20 bar
+.*: c4 1d 00 00 08 18 [ ]*lrl %r1,4010b0 <_GLOBAL_OFFSET_TABLE_\+0x14>
+[ ]*.*: R_390_GOTENT bar\+0x2
+.*: 58 10 c0 14 [ ]*l %r1,20\(%r12\)
+[ ]*.*: R_390_GOT12 bar
+.*: e3 10 c0 14 00 58 [ ]*ly %r1,20\(%r12\)
+[ ]*.*: R_390_GOT20 bar
+.*: c4 18 00 00 08 0e [ ]*lgrl %r1,4010ac <_GLOBAL_OFFSET_TABLE_\+0x10>
+[ ]*.*: R_390_GOTENT _GLOBAL_OFFSET_TABLE_\+0x2
+.*: c4 18 00 00 08 09 [ ]*lgrl %r1,4010a8 <_GLOBAL_OFFSET_TABLE_\+0xc>
+[ ]*.*: R_390_GOTENT misaligned_sym\+0x2
diff --git a/ld/testsuite/ld-s390/gotreloc_64-no-pie-1b.dd b/ld/testsuite/ld-s390/gotreloc_64-no-pie-1b.dd
new file mode 100644
index 000000000000..344701c0ee17
--- /dev/null
+++ b/ld/testsuite/ld-s390/gotreloc_64-no-pie-1b.dd
@@ -0,0 +1,19 @@
+tmpdir/gotreloc_64-1b: file format elf64-s390
+
+Disassembly of section .text:
+
+.* <foo>:
+.*: c4 18 00 00 08 28 [ ]*lgrl %r1,1001100 <_GLOBAL_OFFSET_TABLE_\+0x28>
+[ ]*.*: R_390_GOTENT bar\+0x2
+.*: e3 10 c0 28 00 04 [ ]*lg %r1,40\(%r12\)
+[ ]*.*: R_390_GOT20 bar
+.*: c4 1d 00 00 08 22 [ ]*lrl %r1,1001100 <_GLOBAL_OFFSET_TABLE_\+0x28>
+[ ]*.*: R_390_GOTENT bar\+0x2
+.*: 58 10 c0 28 [ ]*l %r1,40\(%r12\)
+[ ]*.*: R_390_GOT12 bar
+.*: e3 10 c0 28 00 58 [ ]*ly %r1,40\(%r12\)
+[ ]*.*: R_390_GOT20 bar
+.*: c4 18 00 00 08 16 [ ]*lgrl %r1,10010f8 <_GLOBAL_OFFSET_TABLE_\+0x20>
+[ ]*.*: R_390_GOTENT _GLOBAL_OFFSET_TABLE_\+0x2
+.*: c4 18 00 00 08 0f [ ]*lgrl %r1,10010f0 <_GLOBAL_OFFSET_TABLE_\+0x18>
+[ ]*.*: R_390_GOTENT misaligned_sym\+0x2
diff --git a/ld/testsuite/ld-s390/gotreloc_64-norelro-1b.dd b/ld/testsuite/ld-s390/gotreloc_64-norelro-1b.dd
new file mode 100644
index 000000000000..2dc84f2efc0f
--- /dev/null
+++ b/ld/testsuite/ld-s390/gotreloc_64-norelro-1b.dd
@@ -0,0 +1,19 @@
+tmpdir/gotreloc_64-1b: file format elf64-s390
+
+Disassembly of section .text:
+
+.* <foo>:
+.*: c4 18 00 00 08 98 [ ]*lgrl %r1,12e0 <_GLOBAL_OFFSET_TABLE_\+0x28>
+[ ]*.*: R_390_GOTENT bar\+0x2
+.*: e3 10 c0 28 00 04 [ ]*lg %r1,40\(%r12\)
+[ ]*.*: R_390_GOT20 bar
+.*: c4 1d 00 00 08 92 [ ]*lrl %r1,12e0 <_GLOBAL_OFFSET_TABLE_\+0x28>
+[ ]*.*: R_390_GOTENT bar\+0x2
+.*: 58 10 c0 28 [ ]*l %r1,40\(%r12\)
+[ ]*.*: R_390_GOT12 bar
+.*: e3 10 c0 28 00 58 [ ]*ly %r1,40\(%r12\)
+[ ]*.*: R_390_GOT20 bar
+.*: c4 18 00 00 08 86 [ ]*lgrl %r1,12d8 <_GLOBAL_OFFSET_TABLE_\+0x20>
+[ ]*.*: R_390_GOTENT _GLOBAL_OFFSET_TABLE_\+0x2
+.*: c4 18 00 00 08 7f [ ]*lgrl %r1,12d0 <_GLOBAL_OFFSET_TABLE_\+0x18>
+[ ]*.*: R_390_GOTENT misaligned_sym\+0x2
diff --git a/ld/testsuite/ld-s390/gotreloc_64-relro-1b.dd b/ld/testsuite/ld-s390/gotreloc_64-relro-1b.dd
new file mode 100644
index 000000000000..b8f7f20da7d2
--- /dev/null
+++ b/ld/testsuite/ld-s390/gotreloc_64-relro-1b.dd
@@ -0,0 +1,19 @@
+tmpdir/gotreloc_64-1b: file format elf64-s390
+
+Disassembly of section .text:
+
+.* <foo>:
+.*: c4 18 00 00 0f 08 [ ]*lgrl %r1,1ff8 <_GLOBAL_OFFSET_TABLE_\+0x28>
+[ ]*.*: R_390_GOTENT bar\+0x2
+.*: e3 10 c0 28 00 04 [ ]*lg %r1,40\(%r12\)
+[ ]*.*: R_390_GOT20 bar
+.*: c4 1d 00 00 0f 02 [ ]*lrl %r1,1ff8 <_GLOBAL_OFFSET_TABLE_\+0x28>
+[ ]*.*: R_390_GOTENT bar\+0x2
+.*: 58 10 c0 28 [ ]*l %r1,40\(%r12\)
+[ ]*.*: R_390_GOT12 bar
+.*: e3 10 c0 28 00 58 [ ]*ly %r1,40\(%r12\)
+[ ]*.*: R_390_GOT20 bar
+.*: c4 18 00 00 0e f6 [ ]*lgrl %r1,1ff0 <_GLOBAL_OFFSET_TABLE_\+0x20>
+[ ]*.*: R_390_GOTENT _GLOBAL_OFFSET_TABLE_\+0x2
+.*: c4 18 00 00 0e ef [ ]*lgrl %r1,1fe8 <_GLOBAL_OFFSET_TABLE_\+0x18>
+[ ]*.*: R_390_GOTENT misaligned_sym\+0x2
diff --git a/ld/testsuite/ld-s390/s390.exp b/ld/testsuite/ld-s390/s390.exp
index 8da0032eb803..eaf74c4c2347 100644
--- a/ld/testsuite/ld-s390/s390.exp
+++ b/ld/testsuite/ld-s390/s390.exp
@@ -54,11 +54,21 @@ set s390tests {
"-m31" {gotreloc-1.s}
{{objdump -dzrj.text gotreloc_31-1a.dd}}
"gotreloc_31-1a"}
+ {"GOT: no symbol address load from got to larl (--no-relax)"
+ "-shared -melf_s390 --hash-style=sysv --version-script=gotreloc-1.ver --emit-relocs --no-relax" ""
+ "-m31" {gotreloc-1.s}
+ {{objdump -dzrj.text gotreloc_31-1b.dd}}
+ "gotreloc_31-1b"}
{"GOT: no-pie symbol address load from got to larl"
"-shared -melf_s390 --no-pie --hash-style=sysv --version-script=gotreloc-1.ver --emit-relocs" ""
"-m31" {gotreloc-1.s}
{{objdump -dzrj.text gotreloc_31-no-pie-1a.dd}}
"gotreloc_31-1a"}
+ {"GOT: no no-pie symbol address load from got to larl (--no-relax)"
+ "-shared -melf_s390 --no-pie --hash-style=sysv --version-script=gotreloc-1.ver --emit-relocs --no-relax" ""
+ "-m31" {gotreloc-1.s}
+ {{objdump -dzrj.text gotreloc_31-no-pie-1b.dd}}
+ "gotreloc_31-1b"}
{"Helper shared library (PLT test)"
"-shared -m elf_s390" "" "-m31" {pltlib.s}
{}
@@ -92,16 +102,31 @@ set s390xtests {
"-m64" {gotreloc-1.s}
{{objdump -dzrj.text gotreloc_64-norelro-1a.dd}}
"gotreloc_64-1a"}
+ {"GOT: no norelro symbol address load from got (--no-relax)"
+ "-shared -melf64_s390 -z norelro --hash-style=sysv --version-script=gotreloc-1.ver --emit-relocs --no-relax" ""
+ "-m64" {gotreloc-1.s}
+ {{objdump -dzrj.text gotreloc_64-norelro-1b.dd}}
+ "gotreloc_64-1b"}
{"GOT: relro symbol address load from got to larl"
"-shared -melf64_s390 -z relro --hash-style=sysv --version-script=gotreloc-1.ver --emit-relocs" ""
"-m64" {gotreloc-1.s}
{{objdump -dzrj.text gotreloc_64-relro-1a.dd}}
"gotreloc_64-1a"}
+ {"GOT: relro symbol address load from got (--no-relax)"
+ "-shared -melf64_s390 -z relro --hash-style=sysv --version-script=gotreloc-1.ver --emit-relocs --no-relax" ""
+ "-m64" {gotreloc-1.s}
+ {{objdump -dzrj.text gotreloc_64-relro-1b.dd}}
+ "gotreloc_64-1b"}
{"GOT: no-pie symbol address load from got to larl"
"-shared -melf64_s390 --no-pie --hash-style=sysv --version-script=gotreloc-1.ver --emit-relocs" ""
"-m64" {gotreloc-1.s}
{{objdump -dzrj.text gotreloc_64-no-pie-1a.dd}}
"gotreloc_64-1a"}
+ {"GOT: no-pie symbol address load from got (--no-relax)"
+ "-shared -melf64_s390 --no-pie --hash-style=sysv --version-script=gotreloc-1.ver --emit-relocs --no-relax" ""
+ "-m64" {gotreloc-1.s}
+ {{objdump -dzrj.text gotreloc_64-no-pie-1b.dd}}
+ "gotreloc_64-1b"}
{"PLT: offset test"
"-shared -m elf64_s390 -dT pltoffset-1.ld --no-error-rwx-segments" ""
"-m64" {pltoffset-1.s}
@@ -147,6 +172,9 @@ if { [istarget "s390-*-*"] || [istarget "s390x-*-*"] } {
if [istarget "s390x-*-*"] {
run_ld_link_tests $s390xtests
+ run_dump_test "weakundef-1b"
+ run_dump_test "weakundef-2b"
+
if { ![skip_sframe_tests] } {
run_dump_test "sframe-simple-1"
run_dump_test "sframe-plt-1"
diff --git a/ld/testsuite/ld-s390/weakundef-1b.d b/ld/testsuite/ld-s390/weakundef-1b.d
new file mode 100644
index 000000000000..3cba83d45101
--- /dev/null
+++ b/ld/testsuite/ld-s390/weakundef-1b.d
@@ -0,0 +1,12 @@
+#source: weakundef-1.s
+#as: -m64
+#ld: -m elf64_s390 -dT 8GB.ld --emit-relocs --no-error-rwx-segments --no-relax
+#objdump: -dzrj.text
+#error: tmpdir/weakundef-1.o: in function `foo':\n
+#error: \(\.text\+0xe\): relocation truncated to fit: R_390_PC32DBL against undefined symbol `wu'\n?
+#error: \(\.text\+0x14\): relocation truncated to fit: R_390_PC32DBL against undefined symbol `wu'\n?
+#error: \(\.text\+0x1a\): relocation truncated to fit: R_390_PC32DBL against undefined symbol `wu'\n?
+#error: \(\.text\+0x20\): relocation truncated to fit: R_390_PC32DBL against undefined symbol `wu'\n?
+#error: \(\.text\+0x26\): relocation truncated to fit: R_390_PC32DBL against undefined symbol `wu'\n?
+#error: \(\.text\+0x2c\): relocation truncated to fit: R_390_PC32DBL against undefined symbol `wu'\n?
+#error: \(\.text\+0x32\): relocation truncated to fit: R_390_PC32DBL against undefined symbol `wu'\n?
diff --git a/ld/testsuite/ld-s390/weakundef-2b.d b/ld/testsuite/ld-s390/weakundef-2b.d
new file mode 100644
index 000000000000..b61f49dd5127
--- /dev/null
+++ b/ld/testsuite/ld-s390/weakundef-2b.d
@@ -0,0 +1,7 @@
+#source: weakundef-2.s
+#as: -m64
+#ld: -m elf64_s390 -dT 8GB.ld --no-pie --emit-relocs --no-error-rwx-segments --no-relax
+#objdump: -dzrj.text
+#error: tmpdir/weakundef-2.o: in function `foo':\n
+#error: \(\.text\+0xe\): relocation truncated to fit: R_390_PLT32DBL against undefined symbol `wu'\n?
+#error: \(\.text\+0x20\): relocation truncated to fit: R_390_PLT32DBL against undefined symbol `wu'\n?
--
2.48.1
More information about the Binutils
mailing list