diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2001-03-30 01:35:22 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2001-03-30 01:35:22 +0000 |
commit | 3cce29673e509737c9de72c84989642c9564e292 (patch) | |
tree | c26b82ebd9e02b5190b0f5ccfdb0da035f4611d7 /libexec/ld.so | |
parent | 01237d63b727bd16f83cc6170dca9c942469a206 (diff) |
Add infrastructure to allow mapping of text sections which are normally
RO, RW while ld.so is working. And then the information to set the
sections back to RO (or appropriate mode).
PowerPC now supports the typical NON-PIC relocations in ld.so.
I do not know how well this will work with large shared libraries.
I seem to recall a possible problem with large data where data is
located in a different shared library.
Diffstat (limited to 'libexec/ld.so')
-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); |