[2/2] s390: Avoid reloc overflows on undefined weak symbols (cont)

Message ID 20240626152033.2567309-3-jremus@linux.ibm.com
State New
Headers
Series s390: Avoid relocation overflows on undefined weak symbols |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_build--master-arm 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 June 26, 2024, 3:20 p.m. UTC
  This complements and reuses logic from Andreas Krebbel's commit
896a639babe2 ("s390: Avoid reloc overflows on undefined weak symbols").

Replace relative long addressing instructions of weak symbols, which
will definitely resolve to zero, with either a load address of 0 or a
a trapping insn.

This prevents the PLT32DBL relocation from overflowing in case the
binary will be loaded at 4GB or more.

bfd/
	* elf64-s390.c (elf_s390_relocate_section): Replace
	instructions using undefined weak symbols with relative
	addressing to avoid relocation overflows.

ld/
	* testsuite/ld-s390/s390.exp: Add new test.
	* testsuite/ld-s390/weakundef-2.s: New test.
	* testsuite/ld-s390/weakundef-2.dd: Likewise.

Reported-by: Alexander Gordeev <agordeev@linux.ibm.com>
Suggested-by: Ilya Leoshkevich <iii@linux.ibm.com>
Suggested-by: Andreas Krebbel <krebbel@linux.ibm.com>
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---
 bfd/elf64-s390.c                    | 37 +++++++++++++++++++++++++++++
 ld/testsuite/ld-s390/s390.exp       |  5 +++-
 ld/testsuite/ld-s390/weakundef-2.dd | 17 +++++++++++++
 ld/testsuite/ld-s390/weakundef-2.s  | 17 +++++++++++++
 4 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 ld/testsuite/ld-s390/weakundef-2.dd
 create mode 100644 ld/testsuite/ld-s390/weakundef-2.s
  

Comments

Andreas Krebbel July 12, 2024, 12:29 p.m. UTC | #1
On 6/26/24 17:20, Jens Remus wrote:
> This complements and reuses logic from Andreas Krebbel's commit
> 896a639babe2 ("s390: Avoid reloc overflows on undefined weak symbols").
>
> Replace relative long addressing instructions of weak symbols, which
> will definitely resolve to zero, with either a load address of 0 or a
> a trapping insn.
>
> This prevents the PLT32DBL relocation from overflowing in case the
> binary will be loaded at 4GB or more.
>
> bfd/
> 	* elf64-s390.c (elf_s390_relocate_section): Replace
> 	instructions using undefined weak symbols with relative
> 	addressing to avoid relocation overflows.
>
> ld/
> 	* testsuite/ld-s390/s390.exp: Add new test.
> 	* testsuite/ld-s390/weakundef-2.s: New test.
> 	* testsuite/ld-s390/weakundef-2.dd: Likewise.
>
> Reported-by: Alexander Gordeev <agordeev@linux.ibm.com>
> Suggested-by: Ilya Leoshkevich <iii@linux.ibm.com>
> Suggested-by: Andreas Krebbel <krebbel@linux.ibm.com>
> Signed-off-by: Jens Remus <jremus@linux.ibm.com>

Ok. Thanks!


Andreas
  

Patch

diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index 2f35da4a6275..f9d9902651bf 100644
--- a/bfd/elf64-s390.c
+++ b/bfd/elf64-s390.c
@@ -2399,6 +2399,43 @@  elf_s390_relocate_section (bfd *output_bfd,
 	      /* We didn't make a PLT entry for this symbol.  This
 		 happens when statically linking PIC code, or when
 		 using -Bsymbolic.  */
+
+	      /* Replace relative long addressing instructions of weak
+		 symbols, which will definitely resolve to zero, with
+		 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
+		  && !h->root.linker_def
+		  && (bfd_link_executable (info)
+		      || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+		  && r_type == R_390_PLT32DBL
+		  && rel->r_offset >= 2)
+		{
+		  void *insn_start = contents + rel->r_offset - 2;
+		  uint16_t op = bfd_get_16 (input_bfd, insn_start) & 0xff0f;
+		  uint8_t reg = bfd_get_8 (input_bfd, insn_start + 1) & 0xf0;
+
+		  /* NOTE: The order of the if's is important!  */
+		  /* Replace load address relative long (larl) with load
+		     address (lay) */
+		  if (op == 0xc000)
+		    {
+		      /* 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);
+		      continue;
+		    }
+		  /* Replace branch relative and save long (brasl) with a trap.  */
+		  else if (op == 0xc005)
+		    {
+		      /* 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);
+		      continue;
+		    }
+		}
+
 	      break;
 	    }
 	  if (s390_is_ifunc_symbol_p (h))
diff --git a/ld/testsuite/ld-s390/s390.exp b/ld/testsuite/ld-s390/s390.exp
index eb9ea35400b2..ac62d7a8a1a5 100644
--- a/ld/testsuite/ld-s390/s390.exp
+++ b/ld/testsuite/ld-s390/s390.exp
@@ -95,9 +95,12 @@  set s390xtests {
      "-m64" {pltoffset-1.s}
      {{objdump "-dzrj.text --stop-address=16" pltoffset-1.dd}}
      "pltoffset-1"}
-    {"WEAKUNDEF1: overflow test"
+    {"WEAKUNDEF1: overflow test (PC32DBL)"
      "-m elf64_s390 -dT 8GB.ld --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}
+     {{objdump "-dzrj.text" weakundef-2.dd}} "weakundef-2"}
 }
 
 if [istarget "s390-*-*"] {
diff --git a/ld/testsuite/ld-s390/weakundef-2.dd b/ld/testsuite/ld-s390/weakundef-2.dd
new file mode 100644
index 000000000000..e7f0e2239b6a
--- /dev/null
+++ b/ld/testsuite/ld-s390/weakundef-2.dd
@@ -0,0 +1,17 @@ 
+tmpdir/weakundef-2:     file format elf64-s390
+
+Disassembly of section .text:
+
+0+200000000 <foo>:
+.*:	c0 10 00 00 00 12 [	 ]*larl	%r1,200000024 <d>
+.*:	c0 10 00 00 00 10 [	 ]*larl	%r1,200000026 <wd>
+.*:	e3 10 00 00 00 71 [	 ]*lay	%r1,0
+.*:	c0 e5 00 00 00 09 [	 ]*brasl	%r14,200000024 <d>
+.*:	c0 e5 00 00 00 07 [	 ]*brasl	%r14,200000026 <wd>
+.*:	c0 f4 00 00 00 01 [	 ]*jg	.*
+
+0+200000024 <d>:
+.*:	07 fe [	 ]*br	%r14
+
+0+200000026 <wd>:
+.*:	07 fe [	 ]*br	%r14
diff --git a/ld/testsuite/ld-s390/weakundef-2.s b/ld/testsuite/ld-s390/weakundef-2.s
new file mode 100644
index 000000000000..d147b53d6dca
--- /dev/null
+++ b/ld/testsuite/ld-s390/weakundef-2.s
@@ -0,0 +1,17 @@ 
+.text
+	.globl foo
+foo:
+	larl	%r1,d@PLT
+	larl	%r1,wd@PLT
+	larl	%r1,wu@PLT
+	brasl	%r14,d@PLT
+	brasl	%r14,wd@PLT
+	brasl	%r14,wu@PLT
+	.weak	wu
+	.type d,@function
+d:
+	br	%r14
+	.weak	wd
+	.type wd,@function
+wd:
+	br	%r14