diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-05-05 13:21:34 +0000 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-05-05 13:21:34 +0000 |
commit | 77df29685b94bf65d393172abf0a8755205d3426 (patch) | |
tree | 8bdd3507945c81c617a2177512b31d272350bca0 /bfd/elf32-s390.c | |
parent | d1b46e8025d11e7120fe71c7cee304ddaa2cd4a2 (diff) | |
download | fsf-binutils-gdb-77df29685b94bf65d393172abf0a8755205d3426.zip fsf-binutils-gdb-77df29685b94bf65d393172abf0a8755205d3426.tar.gz fsf-binutils-gdb-77df29685b94bf65d393172abf0a8755205d3426.tar.bz2 |
* elf32-s390.c (invalid_tls_insn): Call bfd_set_error.
(elf_s390_relocate_section): Add code to do the GD->LE and
LD->LE TLS linker optimizations if a brasl instruction is used
for the __tls_get_offset function call.
* elf64-s390.c (invalid_tls_insn): Call bfd_set_error.
Diffstat (limited to 'bfd/elf32-s390.c')
-rw-r--r-- | bfd/elf32-s390.c | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c index eb8e172..9d7004e 100644 --- a/bfd/elf32-s390.c +++ b/bfd/elf32-s390.c @@ -2268,6 +2268,7 @@ invalid_tls_insn (input_bfd, input_section, rel) input_section, (long) rel->r_offset, howto->name); + bfd_set_error (bfd_error_bad_value); } /* Relocate a 390 ELF section. */ @@ -2982,16 +2983,44 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, unsigned int insn; insn = bfd_get_32 (input_bfd, contents + rel->r_offset); - if ((insn & 0xff000fff) != 0x4d000000) + if ((insn & 0xff000fff) != 0x4d000000 && + (insn & 0xffff0000) != 0xc0e50000) invalid_tls_insn (input_bfd, input_section, rel); if (!info->shared && (h == NULL || h->dynindx == -1)) - /* GD->LE transition. - bas %r14,0(%rx,%r13) -> bc 0,0 */ - insn = 0x47000000; + { + if ((insn & 0xff000000) == 0x4d000000) + { + /* GD->LE transition. + bas %r14,0(%rx,%r13) -> bc 0,0 */ + insn = 0x47000000; + } + else + { + /* GD->LE transition. + brasl %r14,_tls_get_addr@plt -> brcl 0,. */ + insn = 0xc0040000; + bfd_put_16 (output_bfd, 0x0000, + contents + rel->r_offset + 4); + } + } else - /* GD->IE transition. - bas %r14,0(%rx,%r13) -> l %r2,0(%r2,%r12) */ - insn = 0x5822c000; + { + if ((insn & 0xff000000) == 0x4d000000) + { + /* GD->IE transition. + bas %r14,0(%rx,%r13) -> l %r2,0(%r2,%r12) */ + insn = 0x5822c000; + } + else + { + /* GD->IE transition. + brasl %r14,__tls_get_addr@plt -> + l %r2,0(%r2,%r12) ; bcr 0,0 */ + insn = 0x5822c000; + bfd_put_16 (output_bfd, 0x0700, + contents + rel->r_offset + 4); + } + } bfd_put_32 (output_bfd, insn, contents + rel->r_offset); } else if (r_type == R_390_TLS_LDCALL) @@ -3001,11 +3030,23 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, unsigned int insn; insn = bfd_get_32 (input_bfd, contents + rel->r_offset); - if ((insn & 0xff000fff) != 0x4d000000) + if ((insn & 0xff000fff) != 0x4d000000 && + (insn & 0xffff0000) != 0xc0e50000) invalid_tls_insn (input_bfd, input_section, rel); - /* LD->LE transition. - bas %r14,0(%rx,%r13) -> bc 0,0 */ - insn = 0x47000000; + if ((insn & 0xff000000) == 0x4d000000) + { + /* LD->LE transition. + bas %r14,0(%rx,%r13) -> bc 0,0 */ + insn = 0x47000000; + } + else + { + /* LD->LE transition. + brasl %r14,__tls_get_addr@plt -> brcl 0,. */ + insn = 0xc0040000; + bfd_put_16 (output_bfd, 0x0000, + contents + rel->r_offset + 4); + } bfd_put_32 (output_bfd, insn, contents + rel->r_offset); } } |