summaryrefslogtreecommitdiff
path: root/bfd/elf64-s390.c
diff options
context:
space:
mode:
authorAndreas Krebbel <Andreas.Krebbel@de.ibm.com>2013-07-05 09:51:00 +0000
committerAndreas Krebbel <Andreas.Krebbel@de.ibm.com>2013-07-05 09:51:00 +0000
commit5d7b63c30b4b5c98f7873280aed40268be76c217 (patch)
treefb8ffddc8ab9faebf9a8e272dc62459602aeeba5 /bfd/elf64-s390.c
parent34d61b64e28d133b963a517256935c23506f3ba2 (diff)
downloadbinutils-redhat-5d7b63c30b4b5c98f7873280aed40268be76c217.tar.gz
2013-07-05 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
bfd/ * elf32-s390.c: Rewrite GOT accesses using larl if possible. * elf64-s390.c: Likewise. ld/testsuite/ * ld-s390/gotreloc-1.s: New file. * ld-s390/gotreloc-1.ver: New file. * ld-s390/gotreloc_31-1.dd: New file. * ld-s390/gotreloc_64-1.dd: New file. * ld-s390/s390.exp: Run the new tests. Run 31 bit tests also on 64 bit.
Diffstat (limited to 'bfd/elf64-s390.c')
-rw-r--r--bfd/elf64-s390.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index bba6cecd9e..75413e03a9 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;