diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2010-04-24 18:12:30 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2010-04-24 18:12:30 +0000 |
commit | 824c0ae01a78b8cb968cd05489febb9b375cfcdd (patch) | |
tree | b0f1ec97858fb48bb9fcecf2473a0060f580c822 /libexec/ld.so/sparc64 | |
parent | 7aec5b0f6ddc48947940a5488c79b478d0550c24 (diff) |
Fix handling of more than 32768 PLT entries. Mostly from NetBSD.
eyeballed by deraadt@ and drahn@
Diffstat (limited to 'libexec/ld.so/sparc64')
-rw-r--r-- | libexec/ld.so/sparc64/ldasm.S | 20 | ||||
-rw-r--r-- | libexec/ld.so/sparc64/rtld_machine.c | 19 |
2 files changed, 24 insertions, 15 deletions
diff --git a/libexec/ld.so/sparc64/ldasm.S b/libexec/ld.so/sparc64/ldasm.S index 332bc13ebd8..7b9f8d72210 100644 --- a/libexec/ld.so/sparc64/ldasm.S +++ b/libexec/ld.so/sparc64/ldasm.S @@ -1,4 +1,4 @@ -/* $OpenBSD: ldasm.S,v 1.24 2006/05/03 16:10:52 drahn Exp $ */ +/* $OpenBSD: ldasm.S,v 1.25 2010/04/24 18:12:29 kettenis Exp $ */ /* $NetBSD: rtld_start.S,v 1.5 2001/08/14 22:17:48 eeh Exp $ */ /* @@ -157,7 +157,7 @@ _ENTRY(_dl_start) * * and _dl_bind_start_0(x, y) does: * - * i = x - y + 1048596; + * i = x - y + 8 - 32768*32; * n = 32768 + (i/5120)*160 + (i%5120)/24; * * Neither routine needs to issue a save since it's already been @@ -167,17 +167,21 @@ _ENTRY(_dl_start) /* NOTE: _dl_bind_start_0 is untested. Hence the debug stuff */ _ENTRY(_dl_bind_start_0) # (x, y) - sethi %hi(1048596), %l1 + sethi %hi(32768*32-8), %l1 sub %o0, %o1, %l0 /* x - y */ - or %l1, %lo(1048596), %l1 - add %l0, %l1, %l0 /* x - y + 1048596 */ + or %l1, %lo(32768*32-8), %l1 + sub %l0, %l1, %l0 /* x - y + 8 - 32768*32 */ - sdivx %l0, 5120, %l1 /* Calculate i/5120 */ + sethi %hi(5120), %l1 + sdivx %l0, %l1, %l1 /* Calculate i/5120 */ ldx [%o1 + (10*4)], %o0 /* Load object pointer from PLT2 */ - sub %l0, %l1, %l2 /* And i%5120 */ + sllx %l1, 2, %l2 + add %l1, %l2, %l2 + sllx %l2, 10, %l2 + sub %l0, %l2, %l2 /* And i%5120 */ /* Let the division churn for a bit. */ - sdivx %l2, 14, %l4 /* (i%5120)/24 */ + sdivx %l2, 24, %l4 /* (i%5120)/24 */ /* 160 is (32 * 5) or (32 * (4 + 1)) */ sllx %l1, 2, %l3 /* 4 * (i/5120) */ diff --git a/libexec/ld.so/sparc64/rtld_machine.c b/libexec/ld.so/sparc64/rtld_machine.c index 4fa524db1d4..0776204ba71 100644 --- a/libexec/ld.so/sparc64/rtld_machine.c +++ b/libexec/ld.so/sparc64/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.43 2008/07/16 20:33:42 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.44 2010/04/24 18:12:29 kettenis Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -197,7 +197,8 @@ static long reloc_target_bitmask[] = { }; #define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) -void _dl_reloc_plt(Elf_Word *where, Elf_Addr value, Elf_RelA *rela); +void _dl_reloc_plt(elf_object_t *object, Elf_Word *where, Elf_Addr value, + Elf_RelA *rela); void _dl_install_plt(Elf_Word *pltgot, Elf_Addr proc); int @@ -279,7 +280,7 @@ resolve_failed: } if (type == R_TYPE(JMP_SLOT)) { - _dl_reloc_plt((Elf_Word *)where, value, relas); + _dl_reloc_plt(object, (Elf_Word *)where, value, relas); continue; } @@ -374,7 +375,8 @@ resolve_failed: #define LOVAL(v) ((v) & 0x000003ff) void -_dl_reloc_plt(Elf_Word *where, Elf_Addr value, Elf_RelA *rela) +_dl_reloc_plt(elf_object_t *object, Elf_Word *where, Elf_Addr value, + Elf_RelA *rela) { Elf_Addr offset; @@ -408,9 +410,12 @@ _dl_reloc_plt(Elf_Word *where, Elf_Addr value, Elf_RelA *rela) if (rela->r_addend) { Elf_Addr *ptr = (Elf_Addr *)where; /* - * This entry is >32768. Just replace the pointer. + * This entry is >32768. The relocation points to a + * PC-relative pointer to the _dl_bind_start_0 stub at + * the top of the PLT section. Update it to point to + * the target function. */ - ptr[0] = value; + ptr[0] += value - object->Dyn.info[DT_PLTGOT]; } else if (offset <= (1L<<20) && offset >= -(1L<<20)) { /* @@ -645,7 +650,7 @@ _dl_bind(elf_object_t *object, int index) PROT_READ|PROT_WRITE|PROT_EXEC); } - _dl_reloc_plt(addr, ooff + this->st_value, rela); + _dl_reloc_plt(object, addr, ooff + this->st_value, rela); /* if PLT is (to be protected), change back to RO/X */ if (object->plt_size != 0) { |