aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorJens Remus <jremus@linux.ibm.com>2024-07-12 16:53:47 +0200
committerJens Remus <jremus@linux.ibm.com>2024-07-12 16:53:47 +0200
commit6f8b365b653dc9a7370b3bb906a945b5bf5f867c (patch)
treeb4b64b1751dbe4e3b61ed9d9fc1197821f8b799e /bfd
parent83511d2679bbcc4b8d6ac42fb71cfbc35e77107e (diff)
downloadgdb-6f8b365b653dc9a7370b3bb906a945b5bf5f867c.zip
gdb-6f8b365b653dc9a7370b3bb906a945b5bf5f867c.tar.gz
gdb-6f8b365b653dc9a7370b3bb906a945b5bf5f867c.tar.bz2
s390: Avoid reloc overflows on undefined weak symbols (cont)
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>
Diffstat (limited to 'bfd')
-rw-r--r--bfd/elf64-s390.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index 2f35da4..f9d9902 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))