diff options
-rw-r--r-- | bfd/elf32-s390.c | 30 | ||||
-rw-r--r-- | bfd/elf64-s390.c | 31 | ||||
-rw-r--r-- | ld/testsuite/ld-s390/gotreloc-1.s | 11 | ||||
-rw-r--r-- | ld/testsuite/ld-s390/gotreloc-1.ver | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-s390/gotreloc_31-1.dd | 14 | ||||
-rw-r--r-- | ld/testsuite/ld-s390/gotreloc_64-1.dd | 12 | ||||
-rw-r--r-- | ld/testsuite/ld-s390/s390.exp | 11 |
7 files changed, 110 insertions, 0 deletions
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c index bee532d..6467b03 100644 --- a/bfd/elf32-s390.c +++ b/bfd/elf32-s390.c @@ -2536,6 +2536,36 @@ elf_s390_relocate_section (bfd *output_bfd, base_got->contents + off); h->got.offset |= 1; } + + if ((h->def_regular + && info->shared + && SYMBOL_REFERENCES_LOCAL (info, h)) + /* lrl rx,sym@GOTENT -> larl rx, sym */ + && ((r_type == R_390_GOTENT + && (bfd_get_16 (input_bfd, + contents + rel->r_offset - 2) + & 0xff0f) == 0xc40d) + /* ly rx, sym@GOT(r12) -> larl rx, sym */ + || (r_type == R_390_GOT20 + && (bfd_get_32 (input_bfd, + contents + rel->r_offset - 2) + & 0xff00f000) == 0xe300c000 + && bfd_get_8 (input_bfd, + contents + rel->r_offset + 3) == 0x58))) + { + unsigned short new_insn = + (0xc000 | (bfd_get_8 (input_bfd, + contents + rel->r_offset - 1) & 0xf0)); + bfd_put_16 (output_bfd, new_insn, + contents + rel->r_offset - 2); + r_type = R_390_PC32DBL; + rel->r_addend = 2; + howto = elf_howto_table + r_type; + relocation = h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset; + goto do_relocation; + } } else unresolved_reloc = FALSE; diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c index bba6cec..75413e0 100644 --- a/bfd/elf64-s390.c +++ b/bfd/elf64-s390.c @@ -2496,6 +2496,37 @@ elf_s390_relocate_section (bfd *output_bfd, base_got->contents + off); h->got.offset |= 1; } + + if ((h->def_regular + && info->shared + && SYMBOL_REFERENCES_LOCAL (info, h)) + /* lgrl rx,sym@GOTENT -> larl rx, sym */ + && ((r_type == R_390_GOTENT + && (bfd_get_16 (input_bfd, + contents + rel->r_offset - 2) + & 0xff0f) == 0xc408) + /* lg rx, sym@GOT(r12) -> larl rx, sym */ + || (r_type == R_390_GOT20 + && (bfd_get_32 (input_bfd, + contents + rel->r_offset - 2) + & 0xff00f000) == 0xe300c000 + && bfd_get_8 (input_bfd, + contents + rel->r_offset + 3) == 0x04))) + + { + unsigned short new_insn = + (0xc000 | (bfd_get_8 (input_bfd, + contents + rel->r_offset - 1) & 0xf0)); + bfd_put_16 (output_bfd, new_insn, + contents + rel->r_offset - 2); + r_type = R_390_PC32DBL; + rel->r_addend = 2; + howto = elf_howto_table + r_type; + relocation = h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset; + goto do_relocation; + } } else unresolved_reloc = FALSE; diff --git a/ld/testsuite/ld-s390/gotreloc-1.s b/ld/testsuite/ld-s390/gotreloc-1.s new file mode 100644 index 0000000..b60d6c1 --- /dev/null +++ b/ld/testsuite/ld-s390/gotreloc-1.s @@ -0,0 +1,11 @@ + .text + .globl foo +foo: + lgrl %r1,bar@GOTENT + lg %r1,bar@GOT(%r12) + lrl %r1,bar@GOTENT + l %r1,bar@GOT(%r12) + ly %r1,bar@GOT(%r12) + +.globl bar +bar: .long 0x123 diff --git a/ld/testsuite/ld-s390/gotreloc-1.ver b/ld/testsuite/ld-s390/gotreloc-1.ver new file mode 100644 index 0000000..1cb06d6 --- /dev/null +++ b/ld/testsuite/ld-s390/gotreloc-1.ver @@ -0,0 +1 @@ +{ local: bar; }; diff --git a/ld/testsuite/ld-s390/gotreloc_31-1.dd b/ld/testsuite/ld-s390/gotreloc_31-1.dd new file mode 100644 index 0000000..4df4aa5 --- /dev/null +++ b/ld/testsuite/ld-s390/gotreloc_31-1.dd @@ -0,0 +1,14 @@ + +tmpdir/gotreloc_31-1: file format elf32-s390 + +Disassembly of section .text: + +.* <foo>: +.*: c4 18 00 00 .long 0xc4180000 +.*: 08 4e e3 10 .long 0x084ee310 +.*: c0 0c 00 04 .long 0xc00c0004 +.*: c0 10 00 00 00 08 [ ]*larl %r1,168 <bar> +.*: 58 10 c0 0c [ ]*l %r1,12\(%r12\) +.*: c0 10 00 00 00 03 [ ]*larl %r1,168 <bar> +.* <bar>: +.*: 00 00 01 23 .long 0x00000123 diff --git a/ld/testsuite/ld-s390/gotreloc_64-1.dd b/ld/testsuite/ld-s390/gotreloc_64-1.dd new file mode 100644 index 0000000..8c8c619 --- /dev/null +++ b/ld/testsuite/ld-s390/gotreloc_64-1.dd @@ -0,0 +1,12 @@ +tmpdir/gotreloc_64-1: file format elf64-s390 + +Disassembly of section .text: + +.* <foo>: +.*: c0 10 00 00 00 0e [ ]*larl %r1,.* <bar> +.*: c0 10 00 00 00 0b [ ]*larl %r1,.* <bar> +.*: c4 1d 00 00 08 86 [ ]*lrl %r1,.* <_GLOBAL_OFFSET_TABLE_\+0x18> +.*: 58 10 c0 18 [ ]*l %r1,24\(%r12\) +.*: e3 10 c0 18 00 58 [ ]*ly %r1,24\(%r12\) +.* <bar>: +.*: 00 00 01 23 .long 0x00000123 diff --git a/ld/testsuite/ld-s390/s390.exp b/ld/testsuite/ld-s390/s390.exp index 34c5b33..1ac11c7 100644 --- a/ld/testsuite/ld-s390/s390.exp +++ b/ld/testsuite/ld-s390/s390.exp @@ -48,6 +48,11 @@ set s390tests { {{readelf -Ssrl tlsbin.rd} {objdump -dzrj.text tlsbin.dd} {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}} "tlsbin"} + {"GOT: symbol address load from got to larl" + "-shared -melf_s390 --version-script=gotreloc-1.ver" "" + "-m31" {gotreloc-1.s} + {{objdump -dzrj.text gotreloc_31-1.dd}} + "gotreloc_31-1"} } set s390xtests { @@ -64,6 +69,11 @@ set s390xtests { {{readelf -WSsrl tlsbin_64.rd} {objdump -dzrj.text tlsbin_64.dd} {objdump -sj.got tlsbin_64.sd} {objdump -sj.tdata tlsbin_64.td}} "tlsbin_64"} + {"GOT: symbol address load from got to larl" + "-shared -melf64_s390 --version-script=gotreloc-1.ver" "" + "-m64" {gotreloc-1.s} + {{objdump -dzrj.text gotreloc_64-1.dd}} + "gotreloc_64-1"} } if [istarget "s390-*-*"] { @@ -71,5 +81,6 @@ if [istarget "s390-*-*"] { } if [istarget "s390x-*-*"] { + run_ld_link_tests $s390tests run_ld_link_tests $s390xtests } |