]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
s390: Avoid reloc overflows on undefined weak symbols (cont)
authorJens Remus <jremus@linux.ibm.com>
Fri, 12 Jul 2024 14:53:47 +0000 (16:53 +0200)
committerJens Remus <jremus@linux.ibm.com>
Fri, 12 Jul 2024 14:53:47 +0000 (16:53 +0200)
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
ld/testsuite/ld-s390/s390.exp
ld/testsuite/ld-s390/weakundef-2.dd [new file with mode: 0644]
ld/testsuite/ld-s390/weakundef-2.s [new file with mode: 0644]

index 2f35da4a6275128008c183ca5401060f54e7c5cb..f9d9902651bfe6e4905abd48074d66f79100843c 100644 (file)
@@ -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))
index eb9ea35400b26f8d06b9ab235f9955b2a77c2005..ac62d7a8a1a5675aaed16aca1e47969f063d8fa7 100644 (file)
@@ -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 (file)
index 0000000..e7f0e22
--- /dev/null
@@ -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 (file)
index 0000000..d147b53
--- /dev/null
@@ -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