diff options
author | Alan Modra <amodra@gmail.com> | 2013-11-01 19:25:56 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2013-11-04 10:21:32 +1030 |
commit | 52a82034ac9a288d2d8e60efa880623288b5d228 (patch) | |
tree | a1563eb868c979d4a8885798d64a36a9f7bb187a /bfd/elf64-ppc.c | |
parent | a345bc8d317a159e3e887632d80c5a8282d34f07 (diff) | |
download | gdb-52a82034ac9a288d2d8e60efa880623288b5d228.zip gdb-52a82034ac9a288d2d8e60efa880623288b5d228.tar.gz gdb-52a82034ac9a288d2d8e60efa880623288b5d228.tar.bz2 |
Edit ELFv2 global entry prologue to non-PIC
Changing addis r2,r12,..; addi r2,r2,.. to lis r2,..; addi r2,r2..
in non-PIC executables has the benefit of removing a dependency on r12.
bfd/
* elf64-ppc.c (ppc64_elf_relocate_section): Edit global entry
prologue to non-PIC in non-PIC executables.
ld/testsuite/
* ld-powerpc/elfv2exe.d: Adjust for non-PIC global entry.
Diffstat (limited to 'bfd/elf64-ppc.c')
-rw-r--r-- | bfd/elf64-ppc.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index f9177a7..249b6f3 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -13486,6 +13486,39 @@ ppc64_elf_relocate_section (bfd *output_bfd, rel->r_info = ELF64_R_INFO (r_symndx, r_type); } break; + + case R_PPC64_REL16_HA: + /* If we are generating a non-PIC executable, edit + . 0: addis 2,12,.TOC.-0b@ha + . addi 2,2,.TOC.-0b@l + used by ELFv2 global entry points to set up r2, to + . lis 2,.TOC.@ha + . addi 2,2,.TOC.@l + if .TOC. is in range. */ + if (!info->shared + && h != NULL && &h->elf == htab->elf.hgot + && rel + 1 < relend + && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_REL16_LO) + && rel[1].r_offset == rel->r_offset + 4 + && rel[1].r_addend == rel->r_addend + 4 + && relocation + 0x80008000 <= 0xffffffff) + { + unsigned int insn1, insn2; + bfd_vma offset = rel->r_offset - d_offset; + insn1 = bfd_get_32 (output_bfd, contents + offset); + insn2 = bfd_get_32 (output_bfd, contents + offset + 4); + if ((insn1 & 0xffff0000) == 0x3c4c0000 /* addis 2,12 */ + && (insn2 & 0xffff0000) == 0x38420000 /* addi 2,2 */) + { + r_type = R_PPC64_ADDR16_HA; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + rel->r_addend -= d_offset; + rel[1].r_info = ELF64_R_INFO (r_symndx, R_PPC64_ADDR16_LO); + rel[1].r_addend -= d_offset + 4; + bfd_put_32 (output_bfd, 0x3c400000, contents + offset); + } + } + break; } /* Handle other relocations that tweak non-addend part of insn. */ |