diff options
-rw-r--r-- | libexec/ld.so/library.c | 34 | ||||
-rw-r--r-- | libexec/ld.so/powerpc/rtld_machine.c | 83 | ||||
-rw-r--r-- | libexec/ld.so/resolve.h | 14 |
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); |