diff options
author | Andreas Krebbel <Andreas.Krebbel@de.ibm.com> | 2013-07-05 09:51:00 +0000 |
---|---|---|
committer | Andreas Krebbel <Andreas.Krebbel@de.ibm.com> | 2013-07-05 09:51:00 +0000 |
commit | a63cc5f70ca64f41f5144ac330bc7978e584eed3 (patch) | |
tree | 86e015ed6ddf87602fd28daf5574a4582899dc64 /bfd | |
parent | fb798c50b2c896195fb94af229dfbcc52babdfea (diff) | |
download | gdb-a63cc5f70ca64f41f5144ac330bc7978e584eed3.zip gdb-a63cc5f70ca64f41f5144ac330bc7978e584eed3.tar.gz gdb-a63cc5f70ca64f41f5144ac330bc7978e584eed3.tar.bz2 |
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')
-rw-r--r-- | bfd/elf32-s390.c | 30 | ||||
-rw-r--r-- | bfd/elf64-s390.c | 31 |
2 files changed, 61 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; |