From 7e8aeb9a48ea79d386d9981ccc42f0fda6b6a3ed Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 17 May 2005 13:55:02 +0000 Subject: [PATCH] * elf32-ppc.c (LIS_11. LIS_12): Define. (LWZU_0_X_12, LWZ_0_X_12, LWZ_12_4_12, LWZ_12_X_12): Define. (ppc_elf_finish_dynamic_sections): Provide non-pic plt call stub for --data-plt when building non-pie executables. --- bfd/ChangeLog | 7 +++ bfd/elf32-ppc.c | 131 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 100 insertions(+), 38 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index aefdd42b488..3dd9ed05bd9 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2005-05-17 Alan Modra + + * elf32-ppc.c (LIS_11. LIS_12): Define. + (LWZU_0_X_12, LWZ_0_X_12, LWZ_12_4_12, LWZ_12_X_12): Define. + (ppc_elf_finish_dynamic_sections): Provide non-pic plt call stub + for --data-plt when building non-pie executables. + 2005-05-17 Nick Clifton * elf32-v850.c (v850_elf_relocate_section): Move code to test for diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 67e7677c75f..c2c3c108647 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -81,6 +81,12 @@ static bfd_reloc_status_type ppc_elf_unhandled_reloc #define LWZ_11_X_11 0x816b0000 #define LWZ_11_X_30 0x817e0000 #define MTCTR_11 0x7d6903a6 +#define LIS_11 0x3d600000 +#define LIS_12 0x3d800000 +#define LWZU_0_X_12 0x840c0000 +#define LWZ_0_X_12 0x800c0000 +#define LWZ_12_4_12 0x818c0004 +#define LWZ_12_X_12 0x818c0000 /* Offset of tp and dtp pointers from start of TLS block. */ #define TP_OFFSET 0x7000 @@ -6394,59 +6400,78 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, { unsigned char *p; unsigned char *endp; - bfd_vma pltgot; + bfd_vma pltgot, res0; unsigned int i; static const unsigned int plt_resolve[] = { - SUB_11_11_30, - ADD_0_11_11, - ADD_11_0_11, LWZ_0_4_30, + SUB_11_11_30, MTCTR_0, + ADD_0_11_11, LWZ_12_8_30, + ADD_11_0_11, BCTR, NOP, NOP, NOP }; + if (ARRAY_SIZE (plt_resolve) + 2 != GLINK_PLTRESOLVE / 4) + abort (); + #define PPC_LO(v) ((v) & 0xffff) #define PPC_HI(v) (((v) >> 16) & 0xffff) #define PPC_HA(v) PPC_HI ((v) + 0x8000) - pltgot = (htab->plt->output_section->vma - + htab->plt->output_offset - - got); + pltgot = htab->plt->output_section->vma + htab->plt->output_offset; /* Write the plt call stubs. */ p = htab->glink->contents; endp = p + htab->glink_pltresolve; - while (p < endp) + if (info->shared || info->pie) { - if (pltgot < 0x8000) - { - bfd_put_32 (output_bfd, LWZ_11_X_30 + pltgot, p); - p += 4; - bfd_put_32 (output_bfd, MTCTR_11, p); - p += 4; - bfd_put_32 (output_bfd, BCTR, p); - p += 4; - bfd_put_32 (output_bfd, NOP, p); - p += 4; - } - else + pltgot -= got; + + while (p < endp) { - bfd_put_32 (output_bfd, ADDIS_11_30 + PPC_HA (pltgot), p); - p += 4; - bfd_put_32 (output_bfd, LWZ_11_X_11 + PPC_LO (pltgot), p); - p += 4; - bfd_put_32 (output_bfd, MTCTR_11, p); - p += 4; - bfd_put_32 (output_bfd, BCTR, p); - p += 4; + if (pltgot < 0x8000) + { + bfd_put_32 (output_bfd, LWZ_11_X_30 + pltgot, p); + p += 4; + bfd_put_32 (output_bfd, MTCTR_11, p); + p += 4; + bfd_put_32 (output_bfd, BCTR, p); + p += 4; + bfd_put_32 (output_bfd, NOP, p); + p += 4; + } + else + { + bfd_put_32 (output_bfd, ADDIS_11_30 + PPC_HA (pltgot), p); + p += 4; + bfd_put_32 (output_bfd, LWZ_11_X_11 + PPC_LO (pltgot), p); + p += 4; + bfd_put_32 (output_bfd, MTCTR_11, p); + p += 4; + bfd_put_32 (output_bfd, BCTR, p); + p += 4; + } + pltgot += 4; } - pltgot += 4; } + else + while (p < endp) + { + bfd_put_32 (output_bfd, LIS_11 + PPC_HA (pltgot), p); + p += 4; + bfd_put_32 (output_bfd, LWZ_11_X_11 + PPC_LO (pltgot), p); + p += 4; + bfd_put_32 (output_bfd, MTCTR_11, p); + p += 4; + bfd_put_32 (output_bfd, BCTR, p); + p += 4; + pltgot += 4; + } /* Now build the branch table, one for each plt entry (less one), and perhaps some padding. */ @@ -6463,23 +6488,53 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd, p += 4; } - got -= (htab->glink_pltresolve + res0 = (htab->glink_pltresolve + htab->glink->output_section->vma + htab->glink->output_offset); /* Last comes the PLTresolve stub. */ - bfd_put_32 (output_bfd, ADDIS_11_11 + PPC_HA (got), p); - p += 4; - bfd_put_32 (output_bfd, ADDI_11_11 + PPC_LO (got), p); - p += 4; + if (info->shared || info->pie) + { + bfd_put_32 (output_bfd, ADDIS_11_11 + PPC_HA (got - res0), p); + p += 4; + bfd_put_32 (output_bfd, ADDI_11_11 + PPC_LO (got - res0), p); + p += 4; - for (i = 0; i < ARRAY_SIZE (plt_resolve); i++) + for (i = 0; i < ARRAY_SIZE (plt_resolve); i++) + { + bfd_put_32 (output_bfd, plt_resolve[i], p); + p += 4; + } + } + else { - bfd_put_32 (output_bfd, plt_resolve[i], p); + bfd_put_32 (output_bfd, LIS_12 + PPC_HA (got + 4), p); + p += 4; + bfd_put_32 (output_bfd, ADDIS_11_11 + PPC_HA (-res0), p); p += 4; + if (PPC_HA (got + 4) != PPC_HA (got + 8)) + bfd_put_32 (output_bfd, LWZU_0_X_12 + PPC_LO (got + 4), p); + else + bfd_put_32 (output_bfd, LWZ_0_X_12 + PPC_LO (got + 4), p); + p += 4; + bfd_put_32 (output_bfd, ADDI_11_11 + PPC_LO (-res0), p); + p += 4; + bfd_put_32 (output_bfd, MTCTR_0, p); + p += 4; + bfd_put_32 (output_bfd, ADD_0_11_11, p); + p += 4; + if (PPC_HA (got + 4) != PPC_HA (got + 8)) + bfd_put_32 (output_bfd, LWZ_12_4_12, p); + else + bfd_put_32 (output_bfd, LWZ_12_X_12 + PPC_LO (got + 8), p); + p += 4; + + for (i = 5; i < ARRAY_SIZE (plt_resolve); i++) + { + bfd_put_32 (output_bfd, plt_resolve[i], p); + p += 4; + } } - if (ARRAY_SIZE (plt_resolve) + 2 != GLINK_PLTRESOLVE / 4) - abort (); } return TRUE; -- 2.30.2