From: Jens Remus Date: Thu, 16 Oct 2025 09:06:17 +0000 (+0200) Subject: s390: Rewrite emitted relocations when rewriting instructions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ad8434760ee1124a402705c8e815a9ba30eb7533;p=thirdparty%2Fbinutils-gdb.git s390: Rewrite emitted relocations when rewriting instructions When the linker rewrites instructions it may need to rewrite the associated relocations, so that when emitted with option --emit-relocs, they make sense with the rewritten instructions. Otherwise post link analysis and optimization tools may not be able to perform correct modifications of executables. 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. In case of a rewrite of GOT access using lgrl/lg to larl emit the PC32DBL relocation. In case of a rewrite of relative long addressing instructions of weak symbols, which definitively resolve to zero, emit a NONE relocation and reset the symbol table index and addend. Update the gotreloc* and weakundef* tests to check for the respective relocations. This aligns with how GNU linker behaves on x86-64, when rewriting instructions/relocations in elf_x86_64_convert_load_reloc(). bfd/ * elf64-s390.c (elf_s390_relocate_section): Rewrite emitted relocations when rewriting instructions. * elf32-s390.c (elf_s390_relocate_section): Likewise. ld/testsuite/ * ld-s390/s390.exp: Link gotreloc* and weakundef* tests with option --emit-relocs. * ld-s390/gotreloc_31-1.dd: Expect rewritten instructions to be accompanied by a PC32DBL or NONE relocation respectively. * ld-s390/gotreloc_31-no-pie-1.dd: Likewise. * ld-s390/gotreloc_64-no-pie-1.dd: Likewise. * ld-s390/gotreloc_64-norelro-1.dd: Likewise. * ld-s390/gotreloc_64-relro-1.dd: Likewise. * ld-s390/weakundef-1.dd: Likewise. * ld-s390/weakundef-2.dd: Likewise. Fixes: a63cc5f70ca6 ("Rewrite GOT accesses using larl if possible") Fixes: 896a639babe2 ("s390: Avoid reloc overflows on undefined weak symbols") Fixes: 6f8b365b653d ("s390: Avoid reloc overflows on undefined weak symbols (cont)") Signed-off-by: Jens Remus --- diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c index 56c613dd7d7..ce3faa023f3 100644 --- a/bfd/elf32-s390.c +++ b/bfd/elf32-s390.c @@ -2282,6 +2282,7 @@ elf_s390_relocate_section (bfd *output_bfd, bfd_put_16 (output_bfd, new_insn, contents + rel->r_offset - 2); r_type = R_390_PC32DBL; + rel->r_info = ELF32_R_INFO (r_symndx, r_type); rel->r_addend = 2; howto = elf_howto_table + r_type; relocation = h->root.u.def.value diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c index 555395ca5ad..af36e192f59 100644 --- a/bfd/elf64-s390.c +++ b/bfd/elf64-s390.c @@ -2545,6 +2545,7 @@ elf_s390_relocate_section (bfd *output_bfd, bfd_put_16 (output_bfd, new_insn, contents + rel->r_offset - 2); r_type = R_390_PC32DBL; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); rel->r_addend = 2; howto = elf_howto_table + r_type; relocation = h->root.u.def.value @@ -2685,6 +2686,8 @@ elf_s390_relocate_section (bfd *output_bfd, /* larl rX, -> lay rX,0(0) */ bfd_put_16 (output_bfd, 0xe300 | reg, insn_start); bfd_put_32 (output_bfd, 0x71, insn_start + 2); + rel->r_info = ELF64_R_INFO (0, R_390_NONE); + rel->r_addend = 0; continue; } /* Replace branch relative and save long (brasl) with a trap. */ @@ -2693,6 +2696,8 @@ elf_s390_relocate_section (bfd *output_bfd, /* brasl rX, -> jg .+2 (6-byte trap) */ bfd_put_16 (output_bfd, 0xc0f4, insn_start); bfd_put_32 (output_bfd, 0x1, insn_start + 2); + rel->r_info = ELF64_R_INFO (0, R_390_NONE); + rel->r_addend = 0; continue; } } @@ -2797,6 +2802,8 @@ elf_s390_relocate_section (bfd *output_bfd, /* larl rX, -> lay rX,0(0) */ bfd_put_16 (output_bfd, 0xe300 | reg, insn_start); bfd_put_32 (output_bfd, 0x71, insn_start + 2); + rel->r_info = ELF64_R_INFO (0, R_390_NONE); + rel->r_addend = 0; continue; } /* Replace prefetch data relative long (pfdrl) with a NOP */ @@ -2805,6 +2812,8 @@ elf_s390_relocate_section (bfd *output_bfd, /* Emit a 6-byte NOP: jgnop . */ bfd_put_16 (output_bfd, 0xc004, insn_start); bfd_put_32 (output_bfd, 0x0, insn_start + 2); + rel->r_info = ELF64_R_INFO (0, R_390_NONE); + rel->r_addend = 0; continue; } /* Replace the following instructions with a trap: @@ -2822,6 +2831,8 @@ elf_s390_relocate_section (bfd *output_bfd, /* Emit a 6-byte trap: jg .+2 */ bfd_put_16 (output_bfd, 0xc0f4, insn_start); bfd_put_32 (output_bfd, 0x1, insn_start + 2); + rel->r_info = ELF64_R_INFO (0, R_390_NONE); + rel->r_addend = 0; continue; } } diff --git a/ld/testsuite/ld-s390/gotreloc_31-1.dd b/ld/testsuite/ld-s390/gotreloc_31-1.dd index b1cf37c54d6..d04e1e50091 100644 --- a/ld/testsuite/ld-s390/gotreloc_31-1.dd +++ b/ld/testsuite/ld-s390/gotreloc_31-1.dd @@ -5,9 +5,16 @@ 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 .*: c0 10 00 00 08 52 [ ]*larl %r1,11b8 +[ ]*.*: R_390_PC32DBL bar\+0x2 .*: 58 10 c0 14 [ ]*l %r1,20\(%r12\) +[ ]*.*: R_390_GOT12 bar .*: c0 10 00 00 08 4d [ ]*larl %r1,11b8 +[ ]*.*: R_390_PC32DBL bar\+0x2 .*: 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-1.dd b/ld/testsuite/ld-s390/gotreloc_31-no-pie-1.dd index 2e0d2cda87b..dd2c474b755 100644 --- a/ld/testsuite/ld-s390/gotreloc_31-no-pie-1.dd +++ b/ld/testsuite/ld-s390/gotreloc_31-no-pie-1.dd @@ -5,9 +5,16 @@ 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 .*: c0 10 00 00 08 1a [ ]*larl %r1,4010b4 +[ ]*.*: R_390_PC32DBL bar\+0x2 .*: 58 10 c0 14 [ ]*l %r1,20\(%r12\) +[ ]*.*: R_390_GOT12 bar .*: c0 10 00 00 08 15 [ ]*larl %r1,4010b4 +[ ]*.*: R_390_PC32DBL bar\+0x2 .*: 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-1.dd b/ld/testsuite/ld-s390/gotreloc_64-no-pie-1.dd index 751b7a8de6d..57537aeecd8 100644 --- a/ld/testsuite/ld-s390/gotreloc_64-no-pie-1.dd +++ b/ld/testsuite/ld-s390/gotreloc_64-no-pie-1.dd @@ -4,9 +4,16 @@ Disassembly of section .text: .* : .*: c0 10 00 00 08 2c [ ]*larl %r1,1001108 +[ ]*.*: R_390_PC32DBL bar\+0x2 .*: c0 10 00 00 08 29 [ ]*larl %r1,1001108 +[ ]*.*: R_390_PC32DBL bar\+0x2 .*: 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-1.dd b/ld/testsuite/ld-s390/gotreloc_64-norelro-1.dd index 8debd975d07..eece724d217 100644 --- a/ld/testsuite/ld-s390/gotreloc_64-norelro-1.dd +++ b/ld/testsuite/ld-s390/gotreloc_64-norelro-1.dd @@ -4,9 +4,16 @@ Disassembly of section .text: .* : .*: c0 10 00 00 08 9c [ ]*larl %r1,12e8 +[ ]*.*: R_390_PC32DBL bar\+0x2 .*: c0 10 00 00 08 99 [ ]*larl %r1,12e8 +[ ]*.*: R_390_PC32DBL bar\+0x2 .*: 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-1.dd b/ld/testsuite/ld-s390/gotreloc_64-relro-1.dd index 64151d10a7c..7cb11940f8e 100644 --- a/ld/testsuite/ld-s390/gotreloc_64-relro-1.dd +++ b/ld/testsuite/ld-s390/gotreloc_64-relro-1.dd @@ -4,9 +4,16 @@ Disassembly of section .text: .* : .*: c0 10 00 00 0f 0c [ ]*larl %r1,2000 +[ ]*.*: R_390_PC32DBL bar\+0x2 .*: c0 10 00 00 0f 09 [ ]*larl %r1,2000 +[ ]*.*: R_390_PC32DBL bar\+0x2 .*: 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 452811dcb2b..27a1b346fe7 100644 --- a/ld/testsuite/ld-s390/s390.exp +++ b/ld/testsuite/ld-s390/s390.exp @@ -50,12 +50,12 @@ set s390tests { {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}} "tlsbin"} {"GOT: symbol address load from got to larl" - "-shared -melf_s390 --hash-style=sysv --version-script=gotreloc-1.ver" "" + "-shared -melf_s390 --hash-style=sysv --version-script=gotreloc-1.ver --emit-relocs" "" "-m31" {gotreloc-1.s} {{objdump -dzrj.text gotreloc_31-1.dd}} "gotreloc_31-1"} {"GOT: no-pie symbol address load from got to larl" - "-shared -melf_s390 --no-pie --hash-style=sysv --version-script=gotreloc-1.ver" "" + "-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-1.dd}} "gotreloc_31-1"} @@ -88,17 +88,17 @@ set s390xtests { {objdump -sj.got tlsbin_64.sd} {objdump -sj.tdata tlsbin_64.td}} "tlsbin_64"} {"GOT: norelro symbol address load from got to larl" - "-shared -melf64_s390 -z norelro --hash-style=sysv --version-script=gotreloc-1.ver" "" + "-shared -melf64_s390 -z norelro --hash-style=sysv --version-script=gotreloc-1.ver --emit-relocs" "" "-m64" {gotreloc-1.s} {{objdump -dzrj.text gotreloc_64-norelro-1.dd}} "gotreloc_64-1"} {"GOT: relro symbol address load from got to larl" - "-shared -melf64_s390 -z relro --hash-style=sysv --version-script=gotreloc-1.ver" "" + "-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-1.dd}} "gotreloc_64-1"} {"GOT: no-pie symbol address load from got to larl" - "-shared -melf64_s390 --no-pie --hash-style=sysv --version-script=gotreloc-1.ver" "" + "-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-1.dd}} "gotreloc_64-1"} @@ -108,10 +108,10 @@ set s390xtests { {{objdump "-dzrj.text --stop-address=16" pltoffset-1.dd}} "pltoffset-1"} {"WEAKUNDEF1: overflow test (PC32DBL)" - "-m elf64_s390 -dT 8GB.ld --no-error-rwx-segments" "" "-m64" {weakundef-1.s} + "-m elf64_s390 -dT 8GB.ld --emit-relocs --no-error-rwx-segments" "" "-m64" {weakundef-1.s} {{objdump "-dzrj.text" weakundef-1.dd}} "weakundef-1"} {"WEAKUNDEF2: overflow test (PLT32DBL)" - "-m elf64_s390 -dT 8GB.ld --no-error-rwx-segments -no-pie" "" "-m64" {weakundef-2.s} + "-m elf64_s390 -dT 8GB.ld --emit-relocs --no-error-rwx-segments -no-pie" "" "-m64" {weakundef-2.s} {{objdump "-dzrj.text" weakundef-2.dd}} "weakundef-2"} {"Helper shared library (PLT test)" "-shared -m elf64_s390" "" "-m64" {pltlib.s} diff --git a/ld/testsuite/ld-s390/weakundef-1.dd b/ld/testsuite/ld-s390/weakundef-1.dd index 04d53c91d58..3dd25c7d284 100644 --- a/ld/testsuite/ld-s390/weakundef-1.dd +++ b/ld/testsuite/ld-s390/weakundef-1.dd @@ -4,12 +4,21 @@ Disassembly of section .text: .* : .*: c0 10 00 00 00 1c [ ]*larl %r1,200000038 +[ ]*.*: R_390_PC32DBL \.data\+0x2 .*: c0 10 00 00 00 1d [ ]*larl %r1,200000040 +[ ]*.*: R_390_PC32DBL wd\+0x2 .*: e3 10 00 00 00 71 [ ]*lay %r1,0 +[ ]*.*: R_390_NONE \*ABS\* .*: c0 f4 00 00 00 01 [ ]*jg .* +[ ]*.*: R_390_NONE \*ABS\* .*: c0 f4 00 00 00 01 [ ]*jg .* +[ ]*.*: R_390_NONE \*ABS\* .*: c0 f4 00 00 00 01 [ ]*jg .* +[ ]*.*: R_390_NONE \*ABS\* .*: c0 f4 00 00 00 01 [ ]*jg .* +[ ]*.*: R_390_NONE \*ABS\* .*: c0 f4 00 00 00 01 [ ]*jg .* +[ ]*.*: R_390_NONE \*ABS\* .*: c0 04 00 00 00 00 [ ]*jgnop .* +[ ]*.*: R_390_NONE \*ABS\* .*: 07 07 [ ]*nopr %r7 diff --git a/ld/testsuite/ld-s390/weakundef-2.dd b/ld/testsuite/ld-s390/weakundef-2.dd index e7f0e2239b6..e586ff2e28c 100644 --- a/ld/testsuite/ld-s390/weakundef-2.dd +++ b/ld/testsuite/ld-s390/weakundef-2.dd @@ -4,11 +4,17 @@ Disassembly of section .text: 0+200000000 : .*: c0 10 00 00 00 12 [ ]*larl %r1,200000024 +[ ]*.*: R_390_PLT32DBL d\+0x2 .*: c0 10 00 00 00 10 [ ]*larl %r1,200000026 +[ ]*.*: R_390_PLT32DBL wd\+0x2 .*: e3 10 00 00 00 71 [ ]*lay %r1,0 +[ ]*.*: R_390_NONE \*ABS\* .*: c0 e5 00 00 00 09 [ ]*brasl %r14,200000024 +[ ]*.*: R_390_PLT32DBL d\+0x2 .*: c0 e5 00 00 00 07 [ ]*brasl %r14,200000026 +[ ]*.*: R_390_PLT32DBL wd\+0x2 .*: c0 f4 00 00 00 01 [ ]*jg .* +[ ]*.*: R_390_NONE \*ABS\* 0+200000024 : .*: 07 fe [ ]*br %r14