diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2003-08-19 04:15:55 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2003-08-19 04:15:55 +0000 |
commit | 9866a4b6d58ce8a0385b91596f9fcc1468056032 (patch) | |
tree | e9485860bec8fd4fa09087f3494e3fa70f8f551d | |
parent | bc0dffd272dfdfd568d260b38405f3e822fe0466 (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.c | 23 |
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. */ |