summaryrefslogtreecommitdiff
path: root/libexec/ld.so/arm
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2004-02-09 21:09:32 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2004-02-09 21:09:32 +0000
commit1fabde7ab11cb7c04dfc8f08b71f04abb9217d48 (patch)
tree6c6cf732d47430f8855b4b240373eb481eeb7ccf /libexec/ld.so/arm
parent9e36359644be263f2b921e671e2eea90ea6c72c2 (diff)
Enable lazy binding on arm:
_dl_bind_start inspired by netbsd. changed a define to LD_ALLOW_WRITABLE_TEXT, should this be allowed? remove plt protect code, arm has a text PLT. relocate the got entries associated with the plt. perform got protect/unprotect for lazy binding updates.
Diffstat (limited to 'libexec/ld.so/arm')
-rw-r--r--libexec/ld.so/arm/ldasm.S18
-rw-r--r--libexec/ld.so/arm/rtld_machine.c93
2 files changed, 67 insertions, 44 deletions
diff --git a/libexec/ld.so/arm/ldasm.S b/libexec/ld.so/arm/ldasm.S
index c05e74aae84..a04957f5ba9 100644
--- a/libexec/ld.so/arm/ldasm.S
+++ b/libexec/ld.so/arm/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.2 2004/02/09 16:47:19 drahn Exp $ */
+/* $OpenBSD: ldasm.S,v 1.3 2004/02/09 21:09:31 drahn Exp $ */
/*
* Copyright (c) 2004 Dale Rahn
@@ -59,6 +59,22 @@ ENTRY(_dl_start)
ENTRY(_dl_bind_start)
+ /*
+ * ip is pointer to got entry for this relocation
+ * lr is pointer to pltgot[2], which is entry -1 of got plt reloc.
+ * return address is on stack
+ */
+ stmdb sp!, {r0-r4,sl,fp}
+
+ sub r1, ip, lr /* r1 = 4 * (n + 1) */
+ sub r1, r1, #4 /* r1 = 4 * n */
+ mov r1, r1, lsr #2 /* r1 = n */
+
+ ldr r0, [lr, #-4]
+ bl _dl_bind
+ mov ip, r0
+ ldmia sp!, {r0-r4,sl,fp,lr}
+ mov pc, ip
/* STUB */
diff --git a/libexec/ld.so/arm/rtld_machine.c b/libexec/ld.so/arm/rtld_machine.c
index 922e5046bec..020dbab60a5 100644
--- a/libexec/ld.so/arm/rtld_machine.c
+++ b/libexec/ld.so/arm/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.2 2004/02/09 02:33:48 drahn Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.3 2004/02/09 21:09:31 drahn Exp $ */
/*
* Copyright (c) 2004 Dale Rahn
@@ -167,7 +167,9 @@ _dl_bcopy(const void *src, void *dest, int size)
void _dl_reloc_plt(Elf_Word *where, Elf_Addr value, Elf_Rel *rel);
-#define LD_PROTECT_TEXT
+/*
+#define LD_ALLOW_WRITEABLE_TEXT
+*/
int
_dl_md_reloc(elf_object_t *object, int rel, int relsz)
{
@@ -176,7 +178,7 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
long fails = 0;
Elf_Addr loff;
Elf_Rel *rels;
-#ifndef LD_PROTECT_TEXT
+#ifdef LD_ALLOW_WRITEABLE_TEXT
struct load_list *llist;
#endif
@@ -187,12 +189,14 @@ _dl_md_reloc(elf_object_t *object, int rel, int relsz)
if (rels == NULL)
return(0);
-#ifndef LD_PROTECT_TEXT
+#ifdef LD_ALLOW_WRITEABLE_TEXT
/*
* unprotect some segments if we need it.
*/
if ((rel == DT_REL || rel == DT_RELA)) {
- for (llist = object->load_list; llist != NULL; llist = llist->next) {
+ for (llist = object->load_list;
+ llist != NULL;
+ llist = llist->next) {
if (!(llist->prot & PROT_WRITE))
_dl_mprotect(llist->start, llist->size,
llist->prot|PROT_WRITE);
@@ -318,16 +322,18 @@ resolve_failed:
}
}
-#ifndef LD_PROTECT_TEXT
+#ifdef LD_ALLOW_WRITEABLE_TEXT
/* reprotect the unprotected segments */
if ((rel == DT_REL || rel == DT_RELA)) {
- for (llist = object->load_list; llist != NULL; llist = llist->next) {
+ for (llist = object->load_list;
+ llist != NULL;
+ llist = llist->next) {
if (!(llist->prot & PROT_WRITE))
_dl_mprotect(llist->start, llist->size,
llist->prot);
}
}
- #endif
+#endif
return (fails);
}
@@ -340,13 +346,11 @@ resolve_failed:
void
_dl_md_reloc_got(elf_object_t *object, int lazy)
{
-#define DISABLE_LAZY
-#ifndef DISABLE_LAZY
Elf_Addr *pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT];
-#endif
Elf_Addr ooff;
- Elf_Addr plt_addr;
const Elf_Sym *this;
+ int i, num;
+ Elf_Rel *rel;
if (object->Dyn.info[DT_PLTREL] != DT_REL)
return;
@@ -365,13 +369,7 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
if (this != NULL)
object->got_size = ooff + this->st_value - object->got_addr;
- plt_addr = 0;
- object->plt_size = 0;
- this = NULL;
- ooff = _dl_find_symbol("__plt_start", object, &this,
- SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object);
- if (this != NULL)
- plt_addr = ooff + this->st_value;
+ object->plt_size = 0; /* Text PLT on ARM */
if (object->got_addr == NULL)
object->got_start = NULL;
@@ -380,29 +378,23 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
object->got_size += object->got_addr - object->got_start;
object->got_size = ELF_ROUND(object->got_size, _dl_pagesz);
}
-#if 1
object->plt_start = NULL;
-#else
- if (plt_addr == NULL)
- object->plt_start = NULL;
- else {
- object->plt_start = ELF_TRUNC(plt_addr, _dl_pagesz);
- object->plt_size += plt_addr - object->plt_start;
- object->plt_size = ELF_ROUND(object->plt_size, _dl_pagesz);
- }
-#endif
-#define DISABLE_LAZY
-#ifndef DISABLE_LAZY
if (!lazy) {
-#endif
_dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ);
-#ifndef DISABLE_LAZY
} else {
+ rel = (Elf_Rel *)(object->Dyn.info[DT_JMPREL]);
+ num = (object->Dyn.info[DT_PLTRELSZ]);
+
+ for (i = 0; i < num/sizeof(Elf_Rel); i++, rel++) {
+ Elf_Addr *where;
+ where = (Elf_Addr *)(rel->r_offset + object->load_offs);
+ *where += object->load_offs;
+ }
+
pltgot[1] = (Elf_Addr)object;
pltgot[2] = (Elf_Addr)_dl_bind_start;
}
-#endif
if (object->got_size != 0)
_dl_mprotect((void*)object->got_addr, object->got_size,
PROT_READ);
@@ -412,17 +404,19 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
}
Elf_Addr
-_dl_bind(elf_object_t *object, int reloff)
+_dl_bind(elf_object_t *object, int relidx)
{
+ Elf_Rel *rel;
+ Elf_Word *addr;
const Elf_Sym *sym, *this;
- Elf_Addr *r_addr, ooff, newval;
const char *symn;
- Elf_Rel *rels;
+ Elf_Addr ooff, newval;
+ sigset_t omask, nmask;
- rels = ((Elf_Rel *)object->Dyn.info[DT_JMPREL]) + (reloff>>2);
+ rel = ((Elf_Rel *)object->Dyn.info[DT_JMPREL]) + (relidx);
sym = object->dyn.symtab;
- sym += ELF_R_SYM(rels->r_info);
+ sym += ELF_R_SYM(rel->r_info);
symn = object->dyn.strtab + sym->st_name;
ooff = _dl_find_symbol(symn, _dl_objects, &this,
@@ -432,12 +426,25 @@ _dl_bind(elf_object_t *object, int reloff)
*((int *)0) = 0; /* XXX */
}
- r_addr = (Elf_Addr *)(object->load_offs + rels->r_offset);
+ addr = (Elf_Addr *)(object->load_offs + rel->r_offset);
newval = ooff + this->st_value;
- if (*r_addr != newval)
- *r_addr = newval;
+ /* if GOT is protected, allow the write */
+ if (object->got_size != 0) {
+ sigfillset(&nmask);
+ _dl_sigprocmask(SIG_BLOCK, &nmask, &omask);
+ _dl_mprotect((void*)object->got_start, object->got_size,
+ PROT_READ|PROT_WRITE);
+ }
+
+ if (*addr != newval)
+ *addr = newval;
+ /* put the GOT back to RO */
+ if (object->got_size != 0) {
+ _dl_mprotect((void*)object->got_start, object->got_size,
+ PROT_READ);
+ _dl_sigprocmask(SIG_SETMASK, &omask, NULL);
+ }
return newval;
}
-