summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2003-08-19 04:15:55 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2003-08-19 04:15:55 +0000
commit9866a4b6d58ce8a0385b91596f9fcc1468056032 (patch)
treee9485860bec8fd4fa09087f3494e3fa70f8f551d
parentbc0dffd272dfdfd568d260b38405f3e822fe0466 (diff)
Fix PowerPC PLT generation. After 2^12 entries (2^14 offset), only every
other slot in the PLT is used, this is because it takes more than one instruction to generate a constant > 2^14. Normal PLT entry < 2^12 li r11, <n> # where n is PLT index*4 (offset used for plttable). b .pltresolve | .pltcall | target PLT entry after 2^12 lis r11, <n>@ha addi r11, r11, <n>@l # where n is PLT index*4 (offset used for plttable). b .pltresolve | .pltcall | target nop # unused This is all specified by the PowerPC SVID. The PLT table generation code was never tested for entries > 2^12 before and was broken. This fixes the indexing, the constant checking 12 vs 14, ... This code has been tested with up to 128000+ functions.
-rw-r--r--libexec/ld.so/powerpc/rtld_machine.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/libexec/ld.so/powerpc/rtld_machine.c b/libexec/ld.so/powerpc/rtld_machine.c
index 2e9f83c42f0..648b49efbad 100644
--- a/libexec/ld.so/powerpc/rtld_machine.c
+++ b/libexec/ld.so/powerpc/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.28 2003/07/28 03:11:00 drahn Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.29 2003/08/19 04:15:54 drahn Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -118,6 +118,7 @@ _dl_printf("object relocation size %x, numrela %x\n",
/* for plt relocation usage */
if (object->Dyn.info[DT_JMPREL] != 0) {
/* resolver stub not set up */
+ int nplt;
/* Need to construct table to do jumps */
pltresolve = (Elf32_Addr *)(object->Dyn.info[DT_PLTGOT]);
@@ -125,10 +126,15 @@ _dl_printf("object relocation size %x, numrela %x\n",
pltinfo = (Elf32_Addr *)(pltresolve) + PLT_INFO_OFFSET;
first_rela = (Elf32_Addr *)(pltresolve) + PLT_1STRELA_OFFSET;
- plttable = (Elf32_Addr *)
- ((Elf32_Addr)first_rela) + (2 *
- (object->Dyn.info[DT_PLTRELSZ]/sizeof(Elf32_Rela)));
+ nplt = object->Dyn.info[DT_PLTRELSZ]/sizeof(Elf32_Rela);
+ if (nplt >= (2<<12)) {
+ plttable = (Elf32_Addr *) ((Elf32_Addr)first_rela)
+ + (2 * (2<<12)) + (4 * (nplt - (2<<12)));
+ } else {
+ plttable = (Elf32_Addr *) ((Elf32_Addr)first_rela)
+ + (2 * nplt);
+ }
pltinfo[0] = (Elf32_Addr)plttable;
@@ -255,7 +261,7 @@ _dl_printf(" ooff %x, sym val %x, addend %x"
/* if offset is > RELOC_24 deal with it */
index = (r_addr - first_rela) >> 1;
- if (index > (2 << 14)) {
+ if (index >= (2 << 12)) {
/* addis r11,r11,.PLTtable@ha*/
r_addr[0] = ADDIS_R11_R0 | HA(index*4);
r_addr[1] = ADDI_R11_R11 | L(index*4);
@@ -514,14 +520,13 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
r_addr = (Elf32_Addr *)(relas->r_offset + object->load_offs);
for (i = 0, index = 0; i < numrela; i++, r_addr+=2, index++) {
- if (index > (2 << 14)) {
+ if (index >= (2 << 12)) {
/* addis r11,r11,.PLTtable@ha*/
r_addr[0] = ADDIS_R11_R0 | HA(index*4);
r_addr[1] = ADDI_R11_R11 | L(index*4);
BR(r_addr[2], pltresolve);
- /* only every other slot is used after 2^14 entries */
+ /* only every other slot is used after index == 2^14 */
r_addr += 2;
- index++;
} else {
r_addr[0] = LI_R11 | (index * 4);
BR(r_addr[1], pltresolve);
@@ -600,7 +605,7 @@ _dl_bind(elf_object_t *object, int reloff)
plttable = (Elf32_Addr *)pltinfo[0];
plttable[index] = val;
- if (index > (2 << 14)) {
+ if (index >= (2 << 12)) {
/* r_addr[0,1] is initialized to correct
* value in reloc_got.
*/