diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2013-03-26 18:53:48 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2013-03-26 18:53:48 +0000 |
commit | 913a3e3b0242cdfbdfe600f0c8a4da0b623a62d5 (patch) | |
tree | 89369fca3b88a954a4ff109b388ae03d7c65c0d7 | |
parent | 4bb9f2e4ead9d46937b677111281cfe6f4ef8606 (diff) |
SH is a RelA architecture, not a Rel one. Fix _dl_bind() and lazy gotplt
relocation to correctly process RelA entries.
This allows lazy binding to work so far; not enabled yet, must survive some
serious churning first.
-rw-r--r-- | libexec/ld.so/sh/rtld_machine.c | 33 |
1 files changed, 18 insertions, 15 deletions
diff --git a/libexec/ld.so/sh/rtld_machine.c b/libexec/ld.so/sh/rtld_machine.c index c6df59ddf0b..9e11c8a9370 100644 --- a/libexec/ld.so/sh/rtld_machine.c +++ b/libexec/ld.so/sh/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.15 2011/04/06 11:36:25 miod Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.16 2013/03/26 18:53:47 miod Exp $ */ /* * Copyright (c) 2004 Dale Rahn @@ -771,7 +771,7 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) Elf_Addr ooff; const Elf_Sym *this; int i, num; - Elf_Rel *rel; + Elf_RelA *rel; /* XXX - lazy binding not supported yet */ lazy = 0; @@ -793,8 +793,6 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) if (this != NULL) object->got_size = ooff + this->st_value - object->got_addr; - object->plt_size = 0; /* Text PLT on ARM */ - if (object->got_addr == 0) object->got_start = 0; else { @@ -803,17 +801,25 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) object->got_size = ELF_ROUND(object->got_size, _dl_pagesz); } object->plt_start = 0; + object->plt_size = 0; if (!lazy) { fails = _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); } else { - rel = (Elf_Rel *)(object->Dyn.info[DT_JMPREL]); - num = (object->Dyn.info[DT_PLTRELSZ]); + rel = (Elf_RelA *)(object->Dyn.info[DT_JMPREL]); + num = (object->Dyn.info[DT_PLTRELSZ]) / sizeof(Elf_RelA); + + for (i = 0; i < num; i++, rel++) { + Elf_Addr *where, value; + Elf_Word type; - for (i = 0; i < num/sizeof(Elf_Rel); i++, rel++) { - Elf_Addr *where; where = (Elf_Addr *)(rel->r_offset + object->obj_base); - *where += object->obj_base; + type = ELF_R_TYPE(rel->r_info); + if (RELOC_USE_ADDEND(type)) + value = rel->r_addend; + else + value = 0; + *where += object->obj_base + value; } pltgot[1] = (Elf_Addr)object; @@ -822,24 +828,21 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) if (object->got_size != 0) _dl_mprotect((void*)object->got_start, object->got_size, PROT_READ); - if (object->plt_size != 0) - _dl_mprotect((void*)object->plt_start, object->plt_size, - PROT_READ|PROT_EXEC); return (fails); } Elf_Addr -_dl_bind(elf_object_t *object, int relidx) +_dl_bind(elf_object_t *object, int reloff) { - Elf_Rel *rel; + Elf_RelA *rel; Elf_Word *addr; const Elf_Sym *sym, *this; const char *symn; Elf_Addr ooff, newval; sigset_t savedmask; - rel = ((Elf_Rel *)object->Dyn.info[DT_JMPREL]) + (relidx); + rel = (Elf_RelA *)(object->Dyn.info[DT_JMPREL] + reloff); sym = object->dyn.symtab; sym += ELF_R_SYM(rel->r_info); |