[PATCH] s390: Rewrite emitted relocations when rewriting instructions

Jens Remus jremus@linux.ibm.com
Wed Oct 1 13:28:23 GMT 2025
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.

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 <jremus@linux.ibm.com>
---
 bfd/elf32-s390.c                              |  1 +
 bfd/elf64-s390.c                              | 11 +++++++++++
 ld/testsuite/ld-s390/gotreloc_31-1.dd         |  7 +++++++
 ld/testsuite/ld-s390/gotreloc_31-no-pie-1.dd  |  7 +++++++
 ld/testsuite/ld-s390/gotreloc_64-no-pie-1.dd  |  7 +++++++
 ld/testsuite/ld-s390/gotreloc_64-norelro-1.dd |  7 +++++++
 ld/testsuite/ld-s390/gotreloc_64-relro-1.dd   |  7 +++++++
 ld/testsuite/ld-s390/s390.exp                 | 14 +++++++-------
 ld/testsuite/ld-s390/weakundef-1.dd           |  9 +++++++++
 ld/testsuite/ld-s390/weakundef-2.dd           |  6 ++++++
 10 files changed, 69 insertions(+), 7 deletions(-)

diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
index 56c613dd7d7f..ce3faa023f33 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 555395ca5ad5..af36e192f59d 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,<weak sym> -> 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,<weak sym> -> 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,<weak sym> -> 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 b1cf37c54d62..d04e1e500915 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:
 
 .* <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
 .*:	c0 10 00 00 08 52 [	 ]*larl	%r1,11b8 <bar>
+[	 ]*.*: 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 <bar>
+[	 ]*.*: 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 2e0d2cda87b4..dd2c474b755a 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:
 
 .* <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
 .*:	c0 10 00 00 08 1a [	 ]*larl	%r1,4010b4 <bar>
+[	 ]*.*: 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 <bar>
+[	 ]*.*: 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 751b7a8de6d6..57537aeecd88 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:
 
 .* <foo>:
 .*:	c0 10 00 00 08 2c [	 ]*larl	%r1,1001108 <bar>
+[	 ]*.*: R_390_PC32DBL	bar\+0x2
 .*:	c0 10 00 00 08 29 [	 ]*larl	%r1,1001108 <bar>
+[	 ]*.*: 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 8debd975d07d..eece724d217c 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:
 
 .* <foo>:
 .*:	c0 10 00 00 08 9c [	 ]*larl	%r1,12e8 <bar>
+[	 ]*.*: R_390_PC32DBL	bar\+0x2
 .*:	c0 10 00 00 08 99 [	 ]*larl	%r1,12e8 <bar>
+[	 ]*.*: 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 64151d10a7c8..7cb11940f8e3 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:
 
 .* <foo>:
 .*:	c0 10 00 00 0f 0c [	 ]*larl	%r1,2000 <bar>
+[	 ]*.*: R_390_PC32DBL	bar\+0x2
 .*:	c0 10 00 00 0f 09 [	 ]*larl	%r1,2000 <bar>
+[	 ]*.*: 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 452811dcb2ba..27a1b346fe7c 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 04d53c91d58e..3dd25c7d284e 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:
 
 .* <foo>:
 .*:	c0 10 00 00 00 1c [	 ]*larl	%r1,200000038 <d>
+[	 ]*.*: R_390_PC32DBL	\.data\+0x2
 .*:	c0 10 00 00 00 1d [	 ]*larl	%r1,200000040 <wd>
+[	 ]*.*: 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 e7f0e2239b6a..e586ff2e28c9 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 <foo>:
 .*:	c0 10 00 00 00 12 [	 ]*larl	%r1,200000024 <d>
+[	 ]*.*: R_390_PLT32DBL	d\+0x2
 .*:	c0 10 00 00 00 10 [	 ]*larl	%r1,200000026 <wd>
+[	 ]*.*: 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 <d>
+[	 ]*.*: R_390_PLT32DBL	d\+0x2
 .*:	c0 e5 00 00 00 07 [	 ]*brasl	%r14,200000026 <wd>
+[	 ]*.*: R_390_PLT32DBL	wd\+0x2
 .*:	c0 f4 00 00 00 01 [	 ]*jg	.*
+[	 ]*.*: R_390_NONE	\*ABS\*
 
 0+200000024 <d>:
 .*:	07 fe [	 ]*br	%r14
-- 
2.48.1



More information about the Binutils mailing list