From 006589cfa144fc1efeea1d114943c0bd1624e930 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Mon, 7 Dec 2015 13:14:53 +1030 Subject: [PATCH] R_PPC64_ENTRY Add a new relocation that marks large-model entry code, for edit back to medium-model. include/elf/ * ppc64.h (R_PPC64_ENTRY): Define. bfd/ * reloc.c (BFD_RELOC_PPC64_ENTRY): New. * elf64-ppc.c (reloc_howto_type ppc64_elf_howto_raw): Add entry for R_PPC64_ENTRY. (LD_R2_0R12, ADD_R2_R2_R12, LIS_R2, ADDIS_R2_R12): Define. (ppc64_elf_reloc_type_lookup): Handle R_PPC64_ENTRY. (ppc64_elf_relocate_section): Edit code at R_PPC64_ENTTY. Use new insn defines. * libbfd.h: Regenerate. * bfd-in2.h: Regenerate. --- bfd/ChangeLog | 12 +++++++ bfd/bfd-in2.h | 1 + bfd/elf64-ppc.c | 81 ++++++++++++++++++++++++++++++++++++++++--- bfd/libbfd.h | 1 + bfd/reloc.c | 2 ++ include/elf/ChangeLog | 4 +++ include/elf/ppc64.h | 1 + 7 files changed, 98 insertions(+), 4 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 8c0336d2fdd..0a92044f3bf 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2015-12-07 Alan Modra + + * reloc.c (BFD_RELOC_PPC64_ENTRY): New. + * elf64-ppc.c (reloc_howto_type ppc64_elf_howto_raw): Add + entry for R_PPC64_ENTRY. + (LD_R2_0R12, ADD_R2_R2_R12, LIS_R2, ADDIS_R2_R12): Define. + (ppc64_elf_reloc_type_lookup): Handle R_PPC64_ENTRY. + (ppc64_elf_relocate_section): Edit code at R_PPC64_ENTTY. Use + new insn defines. + * libbfd.h: Regenerate. + * bfd-in2.h: Regenerate. + 2015-12-07 Kaz Kojima * config.bfd: Mark sh5*-*-* and sh64*-*-* as obsolete. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index db54efec78f..606d11b73c7 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -3330,6 +3330,7 @@ instruction. */ BFD_RELOC_PPC64_ADDR16_HIGH, BFD_RELOC_PPC64_ADDR16_HIGHA, BFD_RELOC_PPC64_ADDR64_LOCAL, + BFD_RELOC_PPC64_ENTRY, /* PowerPC and PowerPC64 thread-local storage relocations. */ BFD_RELOC_PPC_TLS, diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 9b5ebcdaffb..17b7a134a0c 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -173,8 +173,12 @@ static bfd_vma opd_entry_value #define LD_R2_0R2 0xe8420000 /* ld %r2,xxx+0(%r2) */ #define LD_R2_0R1 0xe8410000 /* ld %r2,0(%r1) */ +#define LD_R2_0R12 0xe84c0000 /* ld %r2,0(%r12) */ +#define ADD_R2_R2_R12 0x7c426214 /* add %r2,%r2,%r12 */ -#define ADDIS_R12_R2 0x3d820000 /* addis %r12,%r2,xxx@ha */ +#define LIS_R2 0x3c400000 /* lis %r2,xxx@ha */ +#define ADDIS_R2_R12 0x3c4c0000 /* addis %r2,%r12,xxx@ha */ +#define ADDIS_R12_R2 0x3d820000 /* addis %r12,%r2,xxx@ha */ #define ADDIS_R12_R12 0x3d8c0000 /* addis %r12,%r12,xxx@ha */ #define LD_R12_0R12 0xe98c0000 /* ld %r12,xxx@l(%r12) */ @@ -2127,6 +2131,21 @@ static reloc_howto_type ppc64_elf_howto_raw[] = { 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ + /* Marker reloc on ELFv2 large-model function entry. */ + HOWTO (R_PPC64_ENTRY, + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC64_ENTRY", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* Like ADDR64, but use local entry point of function. */ HOWTO (R_PPC64_ADDR64_LOCAL, /* type */ 0, /* rightshift */ @@ -2429,6 +2448,8 @@ ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, break; case BFD_RELOC_PPC_REL16DX_HA: r = R_PPC64_REL16DX_HA; break; + case BFD_RELOC_PPC64_ENTRY: r = R_PPC64_ENTRY; + break; case BFD_RELOC_PPC64_ADDR64_LOCAL: r = R_PPC64_ADDR64_LOCAL; break; case BFD_RELOC_VTABLE_INHERIT: r = R_PPC64_GNU_VTINHERIT; @@ -5575,6 +5596,10 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, sec->has_toc_reloc = 1; break; + /* Marker reloc. */ + case R_PPC64_ENTRY: + break; + /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_PPC64_GNU_VTINHERIT: @@ -13852,6 +13877,52 @@ ppc64_elf_relocate_section (bfd *output_bfd, } break; + case R_PPC64_ENTRY: + relocation = TOCstart + htab->sec_info[input_section->id].toc_off; + if (!bfd_link_pic (info) + && !info->traditional_format + && relocation + 0x80008000 <= 0xffffffff) + { + unsigned int insn1, insn2; + + insn1 = bfd_get_32 (input_bfd, contents + rel->r_offset); + insn2 = bfd_get_32 (input_bfd, contents + rel->r_offset + 4); + if ((insn1 & ~0xfffc) == LD_R2_0R12 + && insn2 == ADD_R2_R2_R12) + { + bfd_put_32 (output_bfd, + LIS_R2 + PPC_HA (relocation), + contents + rel->r_offset); + bfd_put_32 (output_bfd, + ADDI_R2_R2 + PPC_LO (relocation), + contents + rel->r_offset + 4); + } + } + else + { + relocation -= (rel->r_offset + + input_section->output_offset + + input_section->output_section->vma); + if (relocation + 0x80008000 <= 0xffffffff) + { + unsigned int insn1, insn2; + + insn1 = bfd_get_32 (input_bfd, contents + rel->r_offset); + insn2 = bfd_get_32 (input_bfd, contents + rel->r_offset + 4); + if ((insn1 & ~0xfffc) == LD_R2_0R12 + && insn2 == ADD_R2_R2_R12) + { + bfd_put_32 (output_bfd, + ADDIS_R2_R12 + PPC_HA (relocation), + contents + rel->r_offset); + bfd_put_32 (output_bfd, + ADDI_R2_R2 + PPC_LO (relocation), + contents + rel->r_offset + 4); + } + } + } + break; + case R_PPC64_REL16_HA: /* If we are generating a non-PIC executable, edit . 0: addis 2,12,.TOC.-0b@ha @@ -13862,6 +13933,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, if .TOC. is in range. */ if (!bfd_link_pic (info) && !info->traditional_format + && !htab->opd_abi && h != NULL && &h->elf == htab->elf.hgot && rel + 1 < relend && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_REL16_LO) @@ -13873,15 +13945,15 @@ ppc64_elf_relocate_section (bfd *output_bfd, 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 */) + if ((insn1 & 0xffff0000) == ADDIS_R2_R12 + && (insn2 & 0xffff0000) == ADDI_R2_R2) { 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); + bfd_put_32 (output_bfd, LIS_R2, contents + offset); } } break; @@ -14178,6 +14250,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, case R_PPC64_TOCSAVE: case R_PPC64_GNU_VTINHERIT: case R_PPC64_GNU_VTENTRY: + case R_PPC64_ENTRY: goto copy_reloc; /* GOT16 relocations. Like an ADDR16 using the symbol's diff --git a/bfd/libbfd.h b/bfd/libbfd.h index a6ed64e1f62..1c93c91c656 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1418,6 +1418,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_PPC64_ADDR16_HIGH", "BFD_RELOC_PPC64_ADDR16_HIGHA", "BFD_RELOC_PPC64_ADDR64_LOCAL", + "BFD_RELOC_PPC64_ENTRY", "BFD_RELOC_PPC_TLS", "BFD_RELOC_PPC_TLSGD", "BFD_RELOC_PPC_TLSLD", diff --git a/bfd/reloc.c b/bfd/reloc.c index 17c470e909d..593e7c71011 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2943,6 +2943,8 @@ ENUMX BFD_RELOC_PPC64_ADDR16_HIGHA ENUMX BFD_RELOC_PPC64_ADDR64_LOCAL +ENUMX + BFD_RELOC_PPC64_ENTRY ENUMDOC Power(rs6000) and PowerPC relocations. diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index 22a25cb752f..e6e7af954f1 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,7 @@ +2015-12-07 Alan Modra + + * ppc64.h (R_PPC64_ENTRY): Define. + 2015-11-11 Alan Modra Peter Bergner diff --git a/include/elf/ppc64.h b/include/elf/ppc64.h index 2cc24cc36a9..9b47b522818 100644 --- a/include/elf/ppc64.h +++ b/include/elf/ppc64.h @@ -152,6 +152,7 @@ START_RELOC_NUMBERS (elf_ppc64_reloc_type) /* Added for ELFv2. */ RELOC_NUMBER (R_PPC64_REL24_NOTOC, 116) RELOC_NUMBER (R_PPC64_ADDR64_LOCAL, 117) + RELOC_NUMBER (R_PPC64_ENTRY, 118) #ifndef RELOC_MACROS_GEN_FUNC /* Fake relocation only used internally by ld. */ -- 2.30.2