summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2013-03-26 18:53:48 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2013-03-26 18:53:48 +0000
commit913a3e3b0242cdfbdfe600f0c8a4da0b623a62d5 (patch)
tree89369fca3b88a954a4ff109b388ae03d7c65c0d7
parent4bb9f2e4ead9d46937b677111281cfe6f4ef8606 (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.c33
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);