diff options
-rw-r--r-- | libexec/ld.so/Makefile | 21 | ||||
-rw-r--r-- | libexec/ld.so/alpha/archdep.h | 165 | ||||
-rw-r--r-- | libexec/ld.so/alpha/ldasm.S | 176 | ||||
-rw-r--r-- | libexec/ld.so/alpha/rtld_machine.c | 401 | ||||
-rw-r--r-- | libexec/ld.so/alpha/syscall.h | 80 | ||||
-rw-r--r-- | libexec/ld.so/ldconfig/Makefile | 3 | ||||
-rw-r--r-- | libexec/ld.so/ldd/Makefile | 3 | ||||
-rw-r--r-- | libexec/ld.so/ldd/ldd.c | 36 | ||||
-rw-r--r-- | libexec/ld.so/loader.c | 48 | ||||
-rw-r--r-- | libexec/ld.so/test/Makefile | 7 | ||||
-rw-r--r-- | libexec/ld.so/test/dltest.c | 6 |
11 files changed, 906 insertions, 40 deletions
diff --git a/libexec/ld.so/Makefile b/libexec/ld.so/Makefile index 3410535349f..cb546787b0e 100644 --- a/libexec/ld.so/Makefile +++ b/libexec/ld.so/Makefile @@ -1,13 +1,6 @@ -# $OpenBSD: Makefile,v 1.3 2000/09/17 17:50:57 deraadt Exp $ +# $OpenBSD: Makefile,v 1.4 2001/05/14 22:18:19 niklas Exp $ SUBDIR=libdl ldconfig ldd -#CFLAGS = -.if (${MACHINE_ARCH} == "powerpc") -CFLAGS += -fpic -msoft-float -.endif -CFLAGS += -I${.CURDIR} -DNO_UNDERSCORE -DVERBOSE_DLINKER \ - -DUSE_CACHE -D__PIC__ -I${.CURDIR}/${MACHINE_ARCH} -#CFLAGS += -g VPATH=${.CURDIR}/../../lib/libc/string:${.CURDIR}/../../sys/lib/libsa NOMAN= @@ -17,6 +10,18 @@ OBJS+= strchr.o PROG= ld.so MAN= ld.so.8 BINDIR=/usr/libexec +CFLAGS += -Werror +.if (${MACHINE_ARCH} == "powerpc") +CFLAGS += -fpic -msoft-float +.endif +.if (${MACHINE_ARCH} == "alpha") +CFLAGS += -fpic -mno-fp-regs +LIBCSRCDIR=${.CURDIR}/../../lib/libc +.include "${LIBCSRCDIR}/arch/alpha/Makefile.inc" +.endif +CFLAGS += -I${.CURDIR} -DNO_UNDERSCORE -DVERBOSE_DLINKER \ + -DUSE_CACHE -D__PIC__ -I${.CURDIR}/${MACHINE_ARCH} +CFLAGS += -g -DDL_PRINTF_DEBUG INSTALL_STRIP= .PATH: ${.CURDIR}/${MACHINE_ARCH} diff --git a/libexec/ld.so/alpha/archdep.h b/libexec/ld.so/alpha/archdep.h new file mode 100644 index 00000000000..49846926455 --- /dev/null +++ b/libexec/ld.so/alpha/archdep.h @@ -0,0 +1,165 @@ +/* $OpenBSD: archdep.h,v 1.1 2001/05/14 22:18:20 niklas Exp $ */ + +/* + * Copyright (c) 1998 Per Fogelstrom, Opsycon AB + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed under OpenBSD by + * Per Fogelstrom, Opsycon AB, Sweden. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _ALPHA_ARCHDEP_H_ +#define _ALPHA_ARCHDEP_H_ + +#define DL_MALLOC_ALIGN 8 /* Arch constraint or otherwise */ + +#define MACHID EM_ALPHA_EXP /* ELF e_machine ID value checked */ + +#define RELTYPE Elf64_Rela +#define RELSIZE sizeof(Elf64_Rela) + +#include <elf_abi.h> +#include <machine/reloc.h> + +int _dl_write __P((int, const char *, int)); + +/* + * The following functions are declared inline so they can + * be used before bootstrap linking has been finished. + */ +static inline void +_dl_dcbf(Elf64_Addr *addr) +{ +} + +static inline void +_dl_wrstderr(const char *s) +{ + while(*s) { + _dl_write(2, s, 1); + s++; + } +} + +static inline void * +_dl_memset(void *p, const char v, size_t c) +{ + char *ip = p; + + while(c--) + *ip++ = v; + return(p); +} + +static inline int +_dl_strlen(const char *p) +{ + const char *s = p; + + while(*s != '\0') + s++; + return(s - p); +} + +static inline char * +_dl_strcpy(char *d, const char *s) +{ + char *rd = d; + + while((*d++ = *s++) != '\0'); + + return(rd); +} + +static inline int +_dl_strncmp(const char *d, const char *s, int c) +{ + while(c-- && *d && *d == *s) { + d++; + s++; + }; + if(c < 0) { + return(0); + } + return(*d - *s); +} + +static inline int +_dl_strcmp(const char *d, const char *s) +{ + while(*d && *d == *s) { + d++; + s++; + } + return(*d - *s); +} + +static inline const char * +_dl_strchr(const char *p, const int c) +{ + while(*p) { + if(*p == c) { + return(p); + } + p++; + } + return(0); +} + +static inline void +RELOC_RELA(Elf64_Rela *r, + const Elf64_Sym *s, Elf64_Addr *p, int v) +{ + if(ELF64_R_TYPE((r)->r_info) == RELOC_RELATIVE) { + if((ELF64_ST_BIND((s)->st_info) == STB_LOCAL) && + ((ELF64_ST_TYPE((s)->st_info) == STT_SECTION) || + (ELF64_ST_TYPE((s)->st_info) == STT_NOTYPE)) ) { + *(p) = (v) + (r)->r_addend; + } else { + *(p) = (v) + (s)->st_value + (r)->r_addend; + } + } else if(ELF64_R_TYPE((r)->r_info) == RELOC_JMP_SLOT) { + Elf64_Addr val = (v) + (s)->st_value + (r)->r_addend - + (Elf64_Addr)(p); + if (((val & 0xfe000000) != 0) && + ((val & 0xfe000000) != 0xfe000000)) + { + /* invalid offset */ + _dl_exit(20); + } + val &= ~0xfc000000; + val |= 0x48000000; + *(p) = val; + _dl_dcbf(p); + } else if(ELF64_R_TYPE((r)->r_info) == RELOC_GLOB_DAT) { + *(p) = (v) + (s)->st_value + (r)->r_addend; + } else { + /* error */ + } +} + +#endif /* _ALPHA_ARCHDEP_H_ */ diff --git a/libexec/ld.so/alpha/ldasm.S b/libexec/ld.so/alpha/ldasm.S new file mode 100644 index 00000000000..0e2cac14f85 --- /dev/null +++ b/libexec/ld.so/alpha/ldasm.S @@ -0,0 +1,176 @@ +/* $OpenBSD: ldasm.S,v 1.1 2001/05/14 22:18:20 niklas Exp $ */ + +/* + * Copyright (c) 2001 Niklas Hallqvist + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed under OpenBSD by + * Niklas Hallqvist. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <machine/asm.h> +#include <machine/pal.h> +#include <sys/syscall.h> + +#define AUX_entry 9 + + .extern _GLOBAL_OFFSET_TABLE_ + +/* Not really a leaf... but we are special. */ +LEAF_NOPROFILE(_dl_start, 0) + .set noreorder + lda sp, (-8 - ((AUX_entry + 1) * 8))(sp) + br pv, L1 +L1: + LDGP(pv) + ldiq t2, L1 + subq pv, t2, t2 + lda t0, _GLOBAL_OFFSET_TABLE_ + addq t0, t2, t0 + lda t1, _DYNAMIC + addq t1, t2, t1 +L2: cmpult t0, t1, t3 + beq t3, L3 + ldq t3, 0(t0) + addq t3, t2, t3 + stq t3, 0(t0) + lda t0, 8(t0) + br L2 +L3: + mov a0, s0 + mov t2, a1 /* relocation displacement */ + mov a1, s1 + ldq a2, 0(a0) /* argc */ + lda a3, 8(a0) /* argv */ + mov a3, s3 + lda t3, 1(a2) + sll t3, 3, t3 + addq a3, t3, a4 /* envp */ + mov a4, s4 + mov t1, a5 /* dynamic */ + mov a5, s5 + lda s2, 8(sp) + stq s2, 0(sp) /* dl_link */ + CALL(_dl_boot_bind) + mov s3, a0 + mov s4, a1 + mov s1, a2 + mov s5, a3 + mov s2, a4 + CALL(_dl_boot) + mov s0, a0 + mov v0, pv + jsr ra, (pv) +END(_dl_start) + +/* + * In reality these are not leaves, but they are stubs which does not need + * further register saving. + */ + +LEAF_NOPROFILE(_dl_exit, 1) + ldiq v0, SYS_exit + call_pal PAL_OSF1_callsys + RET +END(_dl_exit) + +LEAF_NOPROFILE(_dl_open, 2) + ldiq v0, SYS_open + call_pal PAL_OSF1_callsys + RET +END(_dl_open) + +LEAF_NOPROFILE(_dl_close, 1) + ldiq v0, SYS_close + call_pal PAL_OSF1_callsys + RET +END(_dl_close) + +LEAF_NOPROFILE(_dl_write, 3) + ldiq v0, SYS_write + call_pal PAL_OSF1_callsys + RET +END(_dl_write) + +LEAF_NOPROFILE(_dl_read, 3) + ldiq v0, SYS_read + call_pal PAL_OSF1_callsys + RET +END(_dl_exit) + +LEAF_NOPROFILE(_dl_mmap, 6) + lda sp, -8(sp) + stq a5, 0(sp) + ldiq v0, SYS_mmap + call_pal PAL_OSF1_callsys + lda sp, 8(sp) + RET +END(_dl_mmap) + +LEAF_NOPROFILE(_dl_munmap, 2) + ldiq v0, SYS_munmap + call_pal PAL_OSF1_callsys + RET +END(_dl_munmap) + +LEAF_NOPROFILE(_dl_mprotect, 3) + ldiq v0, SYS_mprotect + call_pal PAL_OSF1_callsys + RET +END(_dl_mprotect) + +LEAF_NOPROFILE(_dl_getuid, 0) + ldiq v0, SYS_getuid + call_pal PAL_OSF1_callsys + RET +END(_dl_getuid) + +LEAF_NOPROFILE(_dl_geteuid, 0) + ldiq v0, SYS_geteuid + call_pal PAL_OSF1_callsys + RET +END(_dl_geteuid) + +LEAF_NOPROFILE(_dl_getgid, 0) + ldiq v0, SYS_getgid + call_pal PAL_OSF1_callsys + RET +END(_dl_getgid) + +LEAF_NOPROFILE(_dl_getegid, 0) + ldiq v0, SYS_getegid + call_pal PAL_OSF1_callsys + RET +END(_dl_getegid) + +#ifdef USE_CACHE +LEAF_NOPROFILE(_dl_stat, 2) + ldiq v0, SYS_stat + call_pal PAL_OSF1_callsys + RET +END(_dl_stat) +#endif diff --git a/libexec/ld.so/alpha/rtld_machine.c b/libexec/ld.so/alpha/rtld_machine.c new file mode 100644 index 00000000000..3ce9c1dc4d0 --- /dev/null +++ b/libexec/ld.so/alpha/rtld_machine.c @@ -0,0 +1,401 @@ +/* $OpenBSD: rtld_machine.c,v 1.1 2001/05/14 22:18:21 niklas Exp $ */ + +/* + * Copyright (c) 1999 Dale Rahn + * Copyright (c) 2001 Niklas Hallqvist + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed under OpenBSD by + * Dale Rahn. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#define _DYN_LOADER + +#include <sys/types.h> +#include <sys/cdefs.h> + +#include <machine/elf_machdep.h> + +#include <nlist.h> +#include <link.h> + +#include "syscall.h" +#include "archdep.h" +#include "resolve.h" + +void +_dl_bcopy(void *src, void *dest, int size) +{ + unsigned char *psrc, *pdest; + int i; + psrc = src; + pdest = dest; + for (i = 0; i < size; i++) { + pdest[i] = psrc[i]; + } +} + +int +_dl_md_reloc(elf_object_t *object, int rel, int relasz) +{ + int i; + int numrela; + int fails = 0; + Elf64_Addr loff; + Elf64_Rela *relas; + /* for jmp table relocations */ + Elf64_Addr *pltcall; + Elf64_Addr *plttable; + + Elf64_Addr * first_rela; + + loff = object->load_offs; + numrela = object->Dyn.info[relasz] / sizeof(Elf64_Rela); + relas = (Elf64_Rela *)(object->Dyn.info[rel]); + +#ifdef DL_PRINTF_DEBUG +_dl_printf("loff 0x%lx object relocation size %x, numrela %x\n", loff, + object->Dyn.info[relasz], numrela); +#endif + + if((object->status & STAT_RELOC_DONE) || !relas) { + return(0); + } + /* for plt relocation usage */ + if (object->Dyn.info[DT_JMPREL] != 0) { + /* resolver stub not set up */ + Elf64_Addr val; + + first_rela = (Elf64_Addr *) + (((Elf64_Rela *)(object->Dyn.info[DT_JMPREL]))->r_offset + + loff); + /* Need to construct table to do jumps */ + pltcall = (Elf64_Addr *)(first_rela) - 12; +#ifdef DL_PRINTF_DEBUG +_dl_printf("creating pltcall at %p\n", pltcall); +_dl_printf("md_reloc( jumprel %p\n", first_rela ); +#endif + plttable = (Elf64_Addr *) + ((Elf64_Addr)first_rela) + (2 * + (object->Dyn.info[DT_PLTRELSZ]/sizeof(Elf64_Rela)) + ); + +#ifdef DL_PRINTF_DEBUG +_dl_printf("md_reloc: plttbl size %x\n", + (object->Dyn.info[DT_PLTRELSZ]/sizeof(Elf64_Rela)) +); +_dl_printf("md_reloc: plttable %p\n", plttable); +#endif + } else { + first_rela = NULL; + } + + for(i = 0; i < numrela; i++, relas++) { + Elf64_Addr *r_addr = (Elf64_Addr *)(relas->r_offset + loff); + Elf64_Addr ooff; + const Elf64_Sym *sym, *this; + const char *symn; + +#if 0 +_dl_printf("%d offset 0x%lx info 0x%lx addend 0x%lx\n", i, relas->r_offset, relas->r_info, relas->r_addend); +#endif + + if(ELF64_R_SYM(relas->r_info) == 0xffffff) { + continue; + } + + sym = object->dyn.symtab; + sym += ELF64_R_SYM(relas->r_info); + this = sym; + symn = object->dyn.strtab + sym->st_name; + + if(ELF64_R_SYM(relas->r_info) && + !(ELF64_ST_BIND(sym->st_info) == STB_LOCAL && + ELF64_ST_TYPE (sym->st_info) == STT_NOTYPE)) { + + ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1); + if(!this && ELF64_ST_BIND(sym->st_info) == STB_GLOBAL) { + _dl_printf("%s:" + " %s :can't resolve reference '%s'\n", + _dl_progname, object->load_name, + symn); + fails++; + } + + } + +#if 0 +_dl_printf("reloc %d\n", ELF64_R_TYPE(relas->r_info)); +#endif + switch(ELF64_R_TYPE(relas->r_info)) { +#if 1 + case R_TYPE(REFQUAD): + if(ELF64_ST_BIND(sym->st_info) == STB_LOCAL && + (ELF64_ST_TYPE(sym->st_info) == STT_SECTION || + ELF64_ST_TYPE(sym->st_info) == STT_NOTYPE) ) { + *r_addr = ooff + relas->r_addend; + } else { + *r_addr = ooff + this->st_value + + relas->r_addend; + } + break; +#endif + case R_TYPE(RELATIVE): +#if 0 +_dl_printf("sym info %d r_addr %p relas %p\n", sym->st_info, r_addr, relas); +#endif + if(ELF64_ST_BIND(sym->st_info) == STB_LOCAL && + (ELF64_ST_TYPE(sym->st_info) == STT_SECTION || + ELF64_ST_TYPE(sym->st_info) == STT_NOTYPE) ) { +#if 0 +_dl_printf("addend 0x%lx\n", relas->r_addend); +_dl_printf("*r_addr 0x%lx\n", *r_addr); +#endif + *r_addr = loff + relas->r_addend; +#if 0 +_dl_printf("*r_addr 0x%lx\n", *r_addr); +#endif + +#ifdef DL_PRINTF_DEBUG +_dl_printf("rel1 r_addr %p val %lx loff %lx ooff %lx addend %lx\n", r_addr, +loff + relas->r_addend, loff, ooff, relas->r_addend); +#endif + + } else { +#if 0 +_dl_printf("this %p\n", this); +#endif + *r_addr = loff + this->st_value + + relas->r_addend; + } + break; + case R_TYPE(JMP_SLOT): + { + Elf64_Addr val = ooff + this->st_value + + relas->r_addend - (Elf64_Addr)r_addr; + if (!(((val & 0xfe000000) == 0x00000000) || + ((val & 0xfe000000) == 0xfe000000))) + { + int index; +#ifdef DL_PRINTF_DEBUG +_dl_printf(" ooff %lx, sym val %lx, addend %lx" + " r_addr %lx symn [%s] -> %x\n", + ooff, this->st_value, relas->r_addend, + r_addr, symn, val); +#endif + /* if offset is > RELOC_24 deal with it */ + index = (r_addr - first_rela) >> 1; + + if (index > (2 << 14)) { + + /* addis r11,r11,.PLTtable@ha*/ + val = (index*4 >> 16) + + ((index*4 & 0x00008000) >> 15); + r_addr[0] = 0x3d600000 | val; + val = (Elf64_Addr)pltcall - + (Elf64_Addr)&r_addr[2]; + r_addr[1] = 0x396b0000 | val; + val &= ~0xfc000000; + val |= 0x48000000; + r_addr[2] = val; + + } else { +#ifdef DL_PRINTF_DEBUG + _dl_printf(" index %d, pltcall %x r_addr %lx\n", + index, pltcall, r_addr); +#endif + + r_addr[0] = 0x39600000 | (index * 4); + val = (Elf64_Addr)pltcall - + (Elf64_Addr)&r_addr[1]; + val &= ~0xfc000000; + val |= 0x48000000; + r_addr[1] = val; + + } + _dl_dcbf(r_addr); + _dl_dcbf(&r_addr[2]); + val= ooff + this->st_value + + relas->r_addend; +#ifdef DL_PRINTF_DEBUG + _dl_printf(" symn [%s] val 0x%x\n", symn, val); +#endif + plttable[index] = val; + } else { + /* if the offset is small enough, + * branch directy to the dest + */ + val &= ~0xfc000000; + val |= 0x48000000; + *r_addr = val; + _dl_dcbf(r_addr); + } + } + + break; + case R_TYPE(GLOB_DAT): + *r_addr = ooff + this->st_value + relas->r_addend; + break; +#if 0 +#ifdef DL_PRINTF_DEBUG + /* should not be supported ??? */ + case RELOC_REL24: + { + Elf64_Addr val = ooff + this->st_value + + relas->r_addend - (Elf64_Addr)r_addr; + if ((val & 0xfe000000 != 0) && + (val & 0xfe000000 != 0xfe000000)) + { + /* invalid offset */ + _dl_exit(20); + } + val &= ~0xfc000003; + val |= (*r_addr & 0xfc000003); + *r_addr = val; + + _dl_dcbf(r_addr); + } +#endif + break; + case RELOC_REL14_TAKEN: + /* val |= 1 << (31-10) XXX? */ + case RELOC_REL14: + case RELOC_REL14_NTAKEN: + { + Elf64_Addr val = ooff + this->st_value + + relas->r_addend - (Elf64_Addr)r_addr; + if (((val & 0xffff8000) != 0) && + ((val & 0xffff8000) != 0xffff8000)) + { + /* invalid offset */ + _dl_exit(20); + } + val &= ~0xffff0003; + val |= (*r_addr & 0xffff0003); + *r_addr = val; +#ifdef DL_PRINTF_DEBUG + _dl_printf("rel 14 %lx val %lx\n", + r_addr, val); +#endif + + _dl_dcbf(r_addr); + } + break; +#endif + case R_TYPE(COPY): +#ifdef DL_PRINTF_DEBUG + _dl_printf("copy r_addr %lx, sym %x [%s] size %d val %lx\n", + r_addr, sym, symn, sym->st_size, + (ooff + this->st_value+ + relas->r_addend) + + ); +#endif +{ + /* we need to find a symbol, that is not in the current object, + * start looking at the beginning of the list, searching all objects + * but _not_ the current object, first one found wins. + */ + elf_object_t *cobj; + const Elf64_Sym *cpysrc = NULL; + Elf64_Addr src_loff; + int size; + for (cobj = _dl_objects; + cobj != NULL && cpysrc == NULL; + cobj = cobj->next) + { + if (object != cobj) { + + /* only look in this object */ + src_loff = _dl_find_symbol(symn, cobj, + &cpysrc, 1, 1); + } + } + if (cpysrc == NULL) { + _dl_printf("symbol not found [%s] \n", symn); + } else { + size = sym->st_size; + if (sym->st_size != cpysrc->st_size) { + _dl_printf("symbols size differ [%s] \n", symn); + size = sym->st_size < cpysrc->st_size ? + sym->st_size : cpysrc->st_size; + } +#ifdef DL_PRINTF_DEBUG +_dl_printf(" found other symbol at %x size %d\n", + src_loff + cpysrc->st_value, cpysrc->st_size); +#endif + _dl_bcopy((void *)(src_loff + cpysrc->st_value), + (void *)(ooff + this->st_value+ relas->r_addend), + size); + } +} + break; + case R_TYPE(NONE): + break; + + default: + _dl_printf("%s:" + " %s: unsupported relocation '%s' %d at %lx\n", + _dl_progname, object->load_name, symn, + ELF64_R_TYPE(relas->r_info), r_addr ); + _dl_exit(1); + } + } + object->status |= STAT_RELOC_DONE; +#if 0 +_dl_printf("<\n"); +#endif + return(fails); +} + +/* + * Relocate the Global Offset Table (GOT). Currently we don't + * do lazy evaluation here because the GNU linker doesn't + * follow the ABI spec which says that if an external symbol + * is referenced by other relocations than CALL16 and 26 it + * should not be given a stub and have a zero value in the + * symbol table. By not doing so, we can't use pointers to + * external functions and use them in comparitions... + */ +void +_dl_md_reloc_got(elf_object_t *object, int lazy) +{ + /* relocations all done via rela relocations above */ +} + +/* should not be defined here, but is is 32 for all powerpc 603-G4 */ +#define CACHELINESIZE 32 +void +_dl_syncicache(char *from, size_t len) +{ + int l = len; + unsigned int off = 0; + + while (off < len) { + off += CACHELINESIZE; + } +} diff --git a/libexec/ld.so/alpha/syscall.h b/libexec/ld.so/alpha/syscall.h new file mode 100644 index 00000000000..02ddf74ff33 --- /dev/null +++ b/libexec/ld.so/alpha/syscall.h @@ -0,0 +1,80 @@ +/* $OpenBSD: syscall.h,v 1.1 2001/05/14 22:18:22 niklas Exp $ */ + +/* + * Copyright (c) 2001 Niklas Hallqvist + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed under OpenBSD by + * Niklas Hallqvist. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifdef USE_CACHE +#include <sys/stat.h> +#endif + +#ifndef _dl_MAX_ERRNO +#define _dl_MAX_ERRNO 4096 +#endif +#define _dl_check_error(__res) \ + ((int) __res < 0 && (int) __res >= -_dl_MAX_ERRNO) + +int _dl_close __P((int)); +int _dl_exit __P((int)); +int _dl_getegid __P((void)); +int _dl_geteuid __P((void)); +int _dl_getgid __P((void)); +int _dl_getuid __P((void)); +long _dl_mmap __P((void *, unsigned int, unsigned int, unsigned int, int, + off_t)); +int _dl_mprotect __P((const void *, int, int)); +int _dl_munmap __P((const void*, unsigned int)); +int _dl_open __P((const char*, unsigned int)); +void _dl_printf __P((const char *, ...)); +int _dl_read __P((int, const char*, int)); +#ifdef USE_CACHE +int _dl_stat __P((const char *, struct stat *)); +#endif +int _dl_write __P((int, const char*, int)); + +/* + * Not an actual syscall, but we need something in assembly to say + * whether this is OK or not. + */ + +static inline int +_dl_suid_ok (void) +{ + unsigned int uid, euid, gid, egid; + + uid = _dl_getuid(); + euid = _dl_geteuid(); + gid = _dl_getgid(); + egid = _dl_getegid(); + return (uid == euid && gid == egid); +} + +#include <elf_abi.h> diff --git a/libexec/ld.so/ldconfig/Makefile b/libexec/ld.so/ldconfig/Makefile index 0b938006e3f..66454b75d5a 100644 --- a/libexec/ld.so/ldconfig/Makefile +++ b/libexec/ld.so/ldconfig/Makefile @@ -1,9 +1,10 @@ -# $OpenBSD: Makefile,v 1.1 2000/06/13 03:40:14 rahnds Exp $ +# $OpenBSD: Makefile,v 1.2 2001/05/14 22:18:22 niklas Exp $ # $NetBSD: Makefile,v 1.10 1995/03/06 04:24:41 cgd Exp $ PROG= ldconfig SRCS= ldconfig.c shlib.c etc.c LDDIR?= $(.CURDIR)/.. +CFLAGS+=-Werror #CFLAGS+=-I$(.CURDIR) -I$(LDDIR)/$(MACHINE_ARCH) LDSTATIC=-static BINDIR= /sbin diff --git a/libexec/ld.so/ldd/Makefile b/libexec/ld.so/ldd/Makefile index b0ed6f7af69..ed14c54f7cb 100644 --- a/libexec/ld.so/ldd/Makefile +++ b/libexec/ld.so/ldd/Makefile @@ -1,8 +1,9 @@ -# $OpenBSD: Makefile,v 1.1 2000/09/17 17:50:57 deraadt Exp $ +# $OpenBSD: Makefile,v 1.2 2001/05/14 22:18:22 niklas Exp $ PROG= ldd SRCS= ldd.c MAN= ldd.1 +CFLAGS+=-Werror BINDIR= /usr/bin diff --git a/libexec/ld.so/ldd/ldd.c b/libexec/ld.so/ldd/ldd.c index 5a3bb37c96a..a6fc9453839 100644 --- a/libexec/ld.so/ldd/ldd.c +++ b/libexec/ld.so/ldd/ldd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ldd.c,v 1.2 2001/05/11 15:50:14 art Exp $ */ +/* $OpenBSD: ldd.c,v 1.3 2001/05/14 22:18:23 niklas Exp $ */ /* * Copyright (c) 1993 Paul Kranenburg @@ -176,18 +176,18 @@ main(argc, argv) int readsoneeded(FILE *infile, int dyncheck) { - Elf32_Ehdr *epnt; - Elf32_Phdr *ppnt; + Elf_Ehdr *epnt; + Elf_Phdr *ppnt; int i; int isdynamic = 0; char *header; - unsigned int dynamic_addr = 0; - unsigned int dynamic_size = 0; + unsigned long dynamic_addr = 0; + unsigned long dynamic_size = 0; int strtab_val = 0; int soname_val = 0; - int loadaddr = -1; - int loadbase = 0; - Elf32_Dyn *dpnt; + long loadaddr = -1; + long loadbase = 0; + Elf_Dyn *dpnt; struct stat st; char *res = NULL; @@ -197,13 +197,13 @@ readsoneeded(FILE *infile, int dyncheck) if (header == MAP_FAILED) return -1; - epnt = (Elf32_Ehdr *)header; - if ((int)(epnt+1) > (int)(header + st.st_size)) + epnt = (Elf_Ehdr *)header; + if ((u_long)(epnt+1) > (u_long)(header + st.st_size)) goto skip; - ppnt = (Elf32_Phdr *)&header[epnt->e_phoff]; - if ((int)ppnt < (int)header || - (int)(ppnt+epnt->e_phnum) > (int)(header + st.st_size)) + ppnt = (Elf_Phdr *)&header[epnt->e_phoff]; + if ((u_long)ppnt < (u_long)header || + (u_long)(ppnt+epnt->e_phnum) > (u_long)(header + st.st_size)) goto skip; for (i = 0; i < epnt->e_phnum; i++) { @@ -217,10 +217,10 @@ readsoneeded(FILE *infile, int dyncheck) ppnt++; } - dpnt = (Elf32_Dyn *) &header[dynamic_addr]; - dynamic_size = dynamic_size / sizeof(Elf32_Dyn); - if ((int)dpnt < (int)header || - (int)(dpnt+dynamic_size) > (int)(header + st.st_size)) + dpnt = (Elf_Dyn *) &header[dynamic_addr]; + dynamic_size = dynamic_size / sizeof(Elf_Dyn); + if ((u_long)dpnt < (u_long)header || + (u_long)(dpnt+dynamic_size) > (u_long)(header + st.st_size)) goto skip; while (dpnt->d_tag != DT_NULL) { @@ -235,7 +235,7 @@ readsoneeded(FILE *infile, int dyncheck) if (!strtab_val) goto skip; - dpnt = (Elf32_Dyn *) &header[dynamic_addr]; + dpnt = (Elf_Dyn *) &header[dynamic_addr]; while (dpnt->d_tag != DT_NULL) { if (dpnt->d_tag == DT_NEEDED) { isdynamic = 1; diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c index d9aced351bb..5c85b1d7e4b 100644 --- a/libexec/ld.so/loader.c +++ b/libexec/ld.so/loader.c @@ -1,4 +1,4 @@ -/* $OpenBSD: loader.c,v 1.8 2001/05/12 10:39:54 art Exp $ */ +/* $OpenBSD: loader.c,v 1.9 2001/05/14 22:18:19 niklas Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -54,7 +54,7 @@ */ static void *_dl_malloc_base; static void *_dl_malloc_pool = 0; -static long *_dl_malloc_free = 0; +static long *_dl_malloc_free = 0; const char *_dl_progname; int _dl_pagesz; @@ -140,6 +140,13 @@ _dl_boot(const char **argv, const char **envp, const long loff, struct elf_object *exe_obj; /* Pointer to executable object */ struct elf_object *dyn_obj; /* Pointer to executable object */ struct r_debug * debug_map; +#ifdef __mips__ + struct r_debug **map_link; /* Where to put pointer for gdb */ +#endif /* __mips__ */ + +#if 0 +_dl_printf("%p %p 0x%lx %p %p\n", argv, envp, loff, dynp, dl_data); +#endif /* * Get paths to various things we are going to use. @@ -302,6 +309,9 @@ _dl_boot(const char **argv, const char **envp, const long loff, if (_dl_traceld) { _dl_exit(0); } +#if 0 +_dl_printf("0x%lx\n", dl_data[AUX_entry]); +#endif return(dl_data[AUX_entry]); } @@ -316,10 +326,20 @@ _dl_boot_bind(const long sp, const long loff, int argc, const char **argv, AuxInfo *auxstack; struct elf_object dynld; /* Resolver data for the loader */ -#ifdef __mips__ - struct r_debug *debug_map; /* Dynamic objects map for gdb */ - struct r_debug **map_link; /* Where to put pointer for gdb */ -#endif /* __mips__ */ + +#if 0 +_dl_printf("0x%lx 0x%lx %d %p %p %p %p\n", sp, loff, argc, argv, envp, dynamicp, dl_data); + _dl_printf("%p 0x%lx 0x%lx 0x%lx 0x%lx\n", &((long *)sp)[0], ((long *)sp)[0], ((long *)sp)[1], ((long *)sp)[2], ((long *)sp)[3]); + _dl_printf("%p 0x%lx 0x%lx 0x%lx 0x%lx\n", &((long *)sp)[4], ((long *)sp)[4], ((long *)sp)[5], ((long *)sp)[6], ((long *)sp)[7]); + _dl_printf("%p 0x%lx 0x%lx 0x%lx 0x%lx\n", &((long *)sp)[8], ((long *)sp)[8], ((long *)sp)[9], ((long *)sp)[10], ((long *)sp)[11]); + _dl_printf("%p 0x%lx 0x%lx 0x%lx 0x%lx\n", &((long *)sp)[12], ((long *)sp)[12], ((long *)sp)[13], ((long *)sp)[14], ((long *)sp)[15]); + _dl_printf("%p 0x%lx 0x%lx 0x%lx 0x%lx\n", &((long *)sp)[16], ((long *)sp)[16], ((long *)sp)[17], ((long *)sp)[18], ((long *)sp)[19]); + _dl_printf("%p 0x%lx 0x%lx 0x%lx 0x%lx\n", &((long *)sp)[20], ((long *)sp)[20], ((long *)sp)[21], ((long *)sp)[22], ((long *)sp)[23]); + _dl_printf("%p 0x%lx 0x%lx 0x%lx 0x%lx\n", &((long *)sp)[24], ((long *)sp)[24], ((long *)sp)[25], ((long *)sp)[26], ((long *)sp)[27]); + _dl_printf("%p 0x%lx 0x%lx 0x%lx 0x%lx\n", &((long *)sp)[28], ((long *)sp)[28], ((long *)sp)[29], ((long *)sp)[30], ((long *)sp)[31]); + _dl_printf("%p 0x%lx 0x%lx 0x%lx 0x%lx\n", &((long *)sp)[32], ((long *)sp)[32], ((long *)sp)[33], ((long *)sp)[34], ((long *)sp)[35]); + _dl_printf("XXX 0x%lx\n", ((long *)sp)[23]); +#endif /* * Scan argument and environment vectors. Find dynamic @@ -341,13 +361,29 @@ _dl_boot_bind(const long sp, const long loff, int argc, const char **argv, auxstack = (AuxInfo *)stack; +#if 0 + _dl_printf("XXX 0x%lx\n", ((long *)sp)[23]); +_dl_printf("---\n"); +#endif while(auxstack->au_id != AUX_null) { +#if 0 + _dl_printf("XXX %p 0x%lx\n", &((long *)sp)[23], ((long *)sp)[23]); + _dl_printf("XXX %p 0x%lx\n", &auxstack->au_v, auxstack->au_v); +_dl_printf("%p 0x%lx 0x%lx %d 0x%lx\n", auxstack, ((long *)auxstack)[0], ((long *)auxstack)[1], auxstack->au_id, auxstack->au_v); +#endif if(auxstack->au_id <= AUX_entry) { dl_data[auxstack->au_id] = auxstack->au_v; } auxstack++; } +#if 0 +_dl_printf("---\n"); + _dl_printf("0x%lx 0x%lx 0x%lx 0x%lx\n", dl_data[0], dl_data[1], dl_data[2], dl_data[3]); + _dl_printf("0x%lx 0x%lx 0x%lx 0x%lx\n", dl_data[4], dl_data[5], dl_data[6], dl_data[7]); + _dl_printf("0x%lx 0x%lx 0x%lx 0x%lx\n", dl_data[8], dl_data[9], dl_data[10], dl_data[11]); +#endif + /* * We need to do 'selfreloc' in case the code were'nt * loaded at the address it was linked to. diff --git a/libexec/ld.so/test/Makefile b/libexec/ld.so/test/Makefile index fdf5114fcc6..d5dbc4c2e57 100644 --- a/libexec/ld.so/test/Makefile +++ b/libexec/ld.so/test/Makefile @@ -1,12 +1,13 @@ -# $OpenBSD: Makefile,v 1.3 2000/10/13 05:15:17 drahn Exp $ +# $OpenBSD: Makefile,v 1.4 2001/05/14 22:18:23 niklas Exp $ DIR=/usr/src/libexec/ld.so/obj/ld.so -.if (${MACHINE_ARCH} == "powerpc") +.if (${MACHINE_ARCH} != "mips") #necssary to build the shared objects. not necessary for dltest but #doesn't hurt CFLAGS += -fpic .endif CFLAGS += -g +CFLAGS += -I${.CURDIR}/.. -I${.CURDIR}/../${MACHINE_ARCH} LDFLAGS += -Wl,--export-dynamic -Wl,-dynamic-linker -Wl,${DIR} #LDFLAGS += -Wl,--export-dynamic @@ -43,7 +44,7 @@ libB.so: B.o $(CC) -shared -o $@ B.o CCtest: libA.so libB.so tst.o - g++ ${LDFLAGS} -o $@ tst.o -L . -lB -lA + g++ ${LDFLAGS} -o $@ tst.o libB.so libA.so .include <bsd.prog.mk> .include <bsd.subdir.mk> diff --git a/libexec/ld.so/test/dltest.c b/libexec/ld.so/test/dltest.c index 7d722b43188..ccac4337177 100644 --- a/libexec/ld.so/test/dltest.c +++ b/libexec/ld.so/test/dltest.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dltest.c,v 1.2 2001/01/28 19:34:29 niklas Exp $ */ +/* $OpenBSD: dltest.c,v 1.3 2001/05/14 22:18:23 niklas Exp $ */ #include <stdio.h> #include <stdlib.h> @@ -8,8 +8,8 @@ #include <elf_abi.h> #include <machine/reloc.h> #include <nlist.h> -#include "../powerpc/archdep.h" -#include "../resolve.h" +#include "archdep.h" +#include "resolve.h" typedef void (*func_t)(const char *); |