From: Jens Remus Date: Thu, 16 Oct 2025 09:09:06 +0000 (+0200) Subject: s390: Do not rewrite insns and their relocs in linker if --no-relax X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5a7173cd46252fbbac5c7b30efebd2d66aad5eb3;p=thirdparty%2Fbinutils-gdb.git s390: Do not rewrite insns and their relocs in linker if --no-relax 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 --- diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c index ce3faa023f3..0d04663756a 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 af36e192f59..16daf981e1d 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 00000000000..9513e16e113 --- /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: + +.* : +.*: 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 00000000000..5688e4740b7 --- /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: + +.* : +.*: 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 00000000000..344701c0ee1 --- /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: + +.* : +.*: 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 00000000000..2dc84f2efc0 --- /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: + +.* : +.*: 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 00000000000..b8f7f20da7d --- /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: + +.* : +.*: 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 8da0032eb80..eaf74c4c234 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 00000000000..3cba83d4510 --- /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 00000000000..b61f49dd512 --- /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?