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, a NOP, or a trapping insn. This prevents the PC32DBL relocation from overflowing in case the binary will be loaded at 4GB or more. bfd/ChangeLog: * bfd/elf64-s390.c (elf_s390_relocate_section): Replace instructions using undefined weak symbols with relative addressing to avoid relocation overflows. ld/ChangeLog: * ld/testsuite/ld-s390/s390.exp: * ld/testsuite/ld-s390/8GB.ld: New test. * ld/testsuite/ld-s390/weakundef-1.dd: New test. * ld/testsuite/ld-s390/weakundef-1.s: New test.
This commit is contained in:
parent
d6a14e4138
commit
896a639bab
5 changed files with 91 additions and 0 deletions
|
@ -2475,6 +2475,60 @@ elf_s390_relocate_section (bfd *output_bfd,
|
||||||
+ h->plt.offset);
|
+ h->plt.offset);
|
||||||
goto do_relocation;
|
goto do_relocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Replace relative long addressing instructions of weak
|
||||||
|
symbols, which will definitely resolve to zero, with
|
||||||
|
either a load address of 0, a NOP, or a trapping insn.
|
||||||
|
This prevents the PC32DBL relocation from overflowing in
|
||||||
|
case the binary will be loaded at 4GB or more. */
|
||||||
|
if (h != NULL
|
||||||
|
&& 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_PC32DBL)
|
||||||
|
{
|
||||||
|
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 prefetch data relative long (pfdrl) with a NOP */
|
||||||
|
else if (op == 0xc602)
|
||||||
|
{
|
||||||
|
/* Emit a 6-byte NOP: jgnop . */
|
||||||
|
bfd_put_16 (output_bfd, 0xc004, insn_start);
|
||||||
|
bfd_put_32 (output_bfd, 0x0, insn_start + 2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Replace the following instructions with a trap:
|
||||||
|
- branch relative and save long (brasl)
|
||||||
|
- load (logical) relative long (lrl, lgrl, lgfrl, llgfrl)
|
||||||
|
- load (logical) halfword relative long (lhrl, lghrl, llhrl, llghrl)
|
||||||
|
- store relative long (strl, stgrl)
|
||||||
|
- store halfword relative long (sthrl)
|
||||||
|
- execute relative long (exrl)
|
||||||
|
- compare (logical) relative long (crl, clrl, cgrl, clgrl, cgfrl, clgfrl)
|
||||||
|
- compare (logical) halfword relative long (chrl, cghrl, clhrl, clghrl)
|
||||||
|
- branch relative on count high (brcth) */
|
||||||
|
else if (op == 0xc005 || (op & 0xff00) == 0xc400
|
||||||
|
|| (op & 0xff00) == 0xc600 || op == 0xcc06)
|
||||||
|
{
|
||||||
|
/* Emit a 6-byte trap: jg .+2 */
|
||||||
|
bfd_put_16 (output_bfd, 0xc0f4, insn_start);
|
||||||
|
bfd_put_32 (output_bfd, 0x1, insn_start + 2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
|
|
||||||
case R_390_8:
|
case R_390_8:
|
||||||
|
|
1
ld/testsuite/ld-s390/8GB.ld
Normal file
1
ld/testsuite/ld-s390/8GB.ld
Normal file
|
@ -0,0 +1 @@
|
||||||
|
SECTIONS { . = 0x200000000; }
|
|
@ -85,6 +85,9 @@ set s390xtests {
|
||||||
"-m64" {pltoffset-1.s}
|
"-m64" {pltoffset-1.s}
|
||||||
{{objdump "-dzrj.text --stop-address=16" pltoffset-1.dd}}
|
{{objdump "-dzrj.text --stop-address=16" pltoffset-1.dd}}
|
||||||
"pltoffset-1"}
|
"pltoffset-1"}
|
||||||
|
{"WEAKUNDEF1: overflow test"
|
||||||
|
"-m elf64_s390 -dT 8GB.ld --no-error-rwx-segments" "" "-m64" {weakundef-1.s}
|
||||||
|
{{objdump "-dzrj.text" weakundef-1.dd}} "weakundef-1"}
|
||||||
}
|
}
|
||||||
|
|
||||||
if [istarget "s390-*-*"] {
|
if [istarget "s390-*-*"] {
|
||||||
|
|
15
ld/testsuite/ld-s390/weakundef-1.dd
Normal file
15
ld/testsuite/ld-s390/weakundef-1.dd
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
tmpdir/weakundef-1: file format elf64-s390
|
||||||
|
|
||||||
|
Disassembly of section .text:
|
||||||
|
|
||||||
|
.* <foo>:
|
||||||
|
.*: c0 10 00 00 00 1e [ ]*larl %r1,20000003c <d>
|
||||||
|
.*: c0 10 00 00 00 1f [ ]*larl %r1,200000044 <wd>
|
||||||
|
.*: e3 10 00 00 00 71 [ ]*lay %r1,0
|
||||||
|
.*: c0 f4 00 00 00 01 [ ]*jg .*
|
||||||
|
.*: c0 f4 00 00 00 01 [ ]*jg .*
|
||||||
|
.*: c0 f4 00 00 00 01 [ ]*jg .*
|
||||||
|
.*: c0 f4 00 00 00 01 [ ]*jg .*
|
||||||
|
.*: c0 f4 00 00 00 01 [ ]*jg .*
|
||||||
|
.*: c0 f4 00 00 00 01 [ ]*jg .*
|
||||||
|
.*: c0 04 00 00 00 00 [ ]*jgnop .*
|
18
ld/testsuite/ld-s390/weakundef-1.s
Normal file
18
ld/testsuite/ld-s390/weakundef-1.s
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
.text
|
||||||
|
.globl foo
|
||||||
|
foo:
|
||||||
|
larl %r1,d
|
||||||
|
larl %r1,wd
|
||||||
|
larl %r1,wu
|
||||||
|
brasl %r1,wu
|
||||||
|
crl %r1,wu
|
||||||
|
lrl %r1,wu
|
||||||
|
strl %r1,wu
|
||||||
|
exrl %r1,wu
|
||||||
|
brcth %r1,wu
|
||||||
|
pfdrl %r1,wu
|
||||||
|
.weak wd
|
||||||
|
.weak wu
|
||||||
|
.data
|
||||||
|
d: .quad 0x123
|
||||||
|
wd: .quad 0x123
|
Loading…
Add table
Add a link
Reference in a new issue