summaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2005-05-17 13:55:02 +0000
committerAlan Modra <amodra@bigpond.net.au>2005-05-17 13:55:02 +0000
commit27b8f71d5c55b43eb76422c9df92f9da7500ca6a (patch)
tree737e3c3746e2fb406032cd69900f7374ec0cd56c /bfd
parent26617deeb17dfc4e390bbbbbf37bb33844108be9 (diff)
downloadbinutils-redhat-27b8f71d5c55b43eb76422c9df92f9da7500ca6a.tar.gz
* 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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf32-ppc.c131
2 files changed, 100 insertions, 38 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index aefdd42b48..3dd9ed05bd 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+2005-05-17 Alan Modra <amodra@bigpond.net.au>
+
+ * 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 <nickc@redhat.com>
* 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 67e7677c75..c2c3c10864 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;