summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libexec/ld.so/library.c34
-rw-r--r--libexec/ld.so/powerpc/rtld_machine.c83
-rw-r--r--libexec/ld.so/resolve.h14
3 files changed, 113 insertions, 18 deletions
diff --git a/libexec/ld.so/library.c b/libexec/ld.so/library.c
index 3126d5d966a..a591772ea32 100644
--- a/libexec/ld.so/library.c
+++ b/libexec/ld.so/library.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library.c,v 1.3 2001/02/16 05:28:17 drahn Exp $ */
+/* $OpenBSD: library.c,v 1.4 2001/03/30 01:35:20 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -164,9 +164,22 @@ _dl_load_shlib(const char *libname, elf_object_t *parent, int type)
}
void
+_dl_load_list_free(load_list_t *load_list)
+{
+ load_list_t *next;
+
+ while(load_list != NULL) {
+ next = load_list->next;
+ _dl_free(load_list);
+ load_list = next;
+ }
+}
+
+void
_dl_unload_shlib(elf_object_t *object)
{
if(--object->refcount == 0) {
+ _dl_load_list_free(object->load_list);
_dl_munmap((void *)object->load_addr, object->load_size);
_dl_remove_object(object);
}
@@ -188,6 +201,7 @@ _dl_tryload_shlib(const char *libname, int type)
Elf32_Addr loff;
int align = _dl_pagesz - 1;
elf_object_t *object;
+ load_list_t *next_load, *load_list = NULL;
object = _dl_lookup_object(libname);
if(object) {
@@ -254,6 +268,7 @@ _dl_tryload_shlib(const char *libname, int type)
loff = libaddr - minva;
phdp = (Elf32_Phdr *)(hbuf + ehdr->e_phoff);
+
for(i = 0; i < ehdr->e_phnum; i++, phdp++) {
if(phdp->p_type == PT_LOAD) {
int res;
@@ -262,17 +277,27 @@ _dl_tryload_shlib(const char *libname, int type)
res = _dl_mmap(start, size, PFLAGS(phdp->p_flags),
MAP_FIXED|MAP_COPY, libfile,
phdp->p_offset & ~align);
+ next_load = (load_list_t *)_dl_malloc(
+ sizeof(load_list_t));
+ next_load->next = load_list;
+ load_list = next_load;
+ next_load->start = start;
+ next_load->size = size;
+ next_load->prot = PFLAGS(phdp->p_flags);
if(_dl_check_error(res)) {
_dl_printf("%s: rtld mmap failed mapping %s.\n",
_dl_progname, libname);
_dl_close(libfile);
_dl_errno = DL_CANT_MMAP;
_dl_munmap((void *)libaddr, maxva - minva);
+ _dl_load_list_free(load_list);
return(0);
}
if(phdp->p_flags & PF_W) {
- _dl_memset(start + size, 0,
- _dl_pagesz - (size & align));
+ if(size & align) {
+ _dl_memset(start + size, 0,
+ _dl_pagesz - (size & align));
+ }
start = start + ((size + align) & ~align);
size = size - (phdp->p_vaddr & align);
size = phdp->p_memsz - size;
@@ -286,6 +311,7 @@ _dl_tryload_shlib(const char *libname, int type)
_dl_close(libfile);
_dl_errno = DL_CANT_MMAP;
_dl_munmap((void *)libaddr, maxva - minva);
+ _dl_load_list_free(load_list);
return(0);
}
}
@@ -297,9 +323,11 @@ _dl_tryload_shlib(const char *libname, int type)
object = _dl_add_object(libname, dynp, 0, type, libaddr, loff);
if(object) {
object->load_size = maxva - minva; /*XXX*/
+ object->load_list = load_list;
}
else {
_dl_munmap((void *)libaddr, maxva - minva);
+ _dl_load_list_free(load_list);
}
return(object);
}
diff --git a/libexec/ld.so/powerpc/rtld_machine.c b/libexec/ld.so/powerpc/rtld_machine.c
index 299bfeae120..b044e0ce591 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.3 2000/10/06 17:39:30 rahnds Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.4 2001/03/30 01:35:21 drahn Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -35,6 +35,7 @@
#define _DYN_LOADER
#include <sys/types.h>
+#include <sys/mman.h>
#include <nlist.h>
#include <link.h>
@@ -61,6 +62,7 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
int i;
int numrela;
int fails = 0;
+ load_list_t *load_list;
Elf32_Addr loff;
Elf32_Rela *relas;
/* for jmp table relocations */
@@ -120,6 +122,19 @@ _dl_printf("md_reloc: plttable %x\n", plttable);
first_rela = NULL;
}
+ /*
+ * Change protection of all write protected segments in the object
+ * so we can do relocations such as REL24, REL16 etc. After
+ * relocation restore protection.
+ */
+ load_list = object->load_list;
+ while(load_list != NULL) {
+ _dl_mprotect(load_list->start, load_list->size,
+ load_list->prot|PROT_WRITE);
+ load_list = load_list->next;
+ }
+
+
for(i = 0; i < numrela; i++, relas++) {
Elf32_Addr *r_addr = (Elf32_Addr *)(relas->r_offset + loff);
Elf32_Addr ooff;
@@ -246,26 +261,61 @@ _dl_printf(" ooff %x, sym val %x, addend %x"
case RELOC_GLOB_DAT:
*r_addr = ooff + this->st_value + relas->r_addend;
break;
-#ifdef DL_PRINTF_DEBUG
+#if 1
/* should not be supported ??? */
case RELOC_REL24:
- {
+ {
Elf32_Addr val = ooff + this->st_value +
relas->r_addend - (Elf32_Addr)r_addr;
if ((val & 0xfe000000 != 0) &&
- (val & 0xfe000000 != 0xfe000000))
- {
+ (val & 0xfe000000 != 0xfe000000)) {
/* invalid offset */
_dl_exit(20);
}
val &= ~0xfc000003;
val |= (*r_addr & 0xfc000003);
*r_addr = val;
-
+
+_dl_dcbf(r_addr);
+ }
+ break;
+#endif
+#if 1
+ case RELOC_16_LO:
+ {
+ Elf32_Addr val;
+
+ val = loff + relas->r_addend;
+ *(Elf32_Half *)r_addr = val;
+
_dl_dcbf(r_addr);
- }
+ }
+ break;
#endif
- break;
+#if 1
+ case RELOC_16_HI:
+ {
+ Elf32_Addr val;
+
+ val = loff + relas->r_addend;
+ *(Elf32_Half *)r_addr = (val >> 16);
+
+ _dl_dcbf(r_addr);
+ }
+ break;
+#endif
+#if 1
+ case RELOC_16_HA:
+ {
+ Elf32_Addr val;
+
+ val = loff + relas->r_addend;
+ *(Elf32_Half *)r_addr = ((val + 0x8000) >> 16);
+
+ _dl_dcbf(r_addr);
+ }
+ break;
+#endif
case RELOC_REL14_TAKEN:
/* val |= 1 << (31-10) XXX? */
case RELOC_REL14:
@@ -350,6 +400,11 @@ _dl_printf(" found other symbol at %x size %d\n",
}
}
object->status |= STAT_RELOC_DONE;
+ load_list = object->load_list;
+ while(load_list != NULL) {
+ _dl_mprotect(load_list->start, load_list->size, load_list->prot);
+ load_list = load_list->next;
+ }
return(fails);
}
@@ -373,16 +428,16 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
void
_dl_syncicache(char *from, size_t len)
{
- int l = len;
unsigned int off = 0;
+ int l = len + ((int)from & (CACHELINESIZE-1));
- while (off < len) {
- asm volatile ("dcbst %1,%0" :: "r"(from), "r"(off));
+ while (off < l) {
+ asm volatile ("dcbst %1,%0" :: "r"(from), "r"(off));
asm volatile ("sync");
- asm volatile ("icbi 0,%0" :: "r"(from), "r"(off));
+ asm volatile ("icbi %1, %0" :: "r"(from), "r"(off));
asm volatile ("sync");
asm volatile ("isync");
- off += CACHELINESIZE;
- }
+ off += CACHELINESIZE;
+ }
}
diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h
index f44676f4632..7186dd6661c 100644
--- a/libexec/ld.so/resolve.h
+++ b/libexec/ld.so/resolve.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.h,v 1.1 2000/06/13 03:34:09 rahnds Exp $ */
+/* $OpenBSD: resolve.h,v 1.2 2001/03/30 01:35:21 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -37,6 +37,12 @@
#include <link.h>
+typedef struct load_list {
+ struct load_list *next;
+ char *start;
+ size_t size;
+ int prot;
+} load_list_t;
/*
* Structure describing a loaded object.
@@ -52,6 +58,8 @@ typedef struct elf_object {
struct elf_object *prev;
/* End struct link_map compatible */
+ load_list_t *load_list;
+
u_int32_t load_size;
union {
@@ -125,7 +133,11 @@ extern void _dl_unload_shlib(elf_object_t *object);
extern int _dl_md_reloc(elf_object_t *object, int rel, int relsz);
extern void _dl_md_reloc_got(elf_object_t *object, int lazy);
+Elf32_Addr _dl_find_symbol(const char *name, elf_object_t *startlook,
+ const Elf32_Sym **ref, int myself, int warnnotfound);
+
void * _dl_malloc(const int size);
+void _dl_free(void *);
void _dl_rtld(elf_object_t *object);
void _dl_call_init(elf_object_t *object);