diff options
author | Dale S. Rahn <rahnds@cvs.openbsd.org> | 2000-06-13 03:40:40 +0000 |
---|---|---|
committer | Dale S. Rahn <rahnds@cvs.openbsd.org> | 2000-06-13 03:40:40 +0000 |
commit | 737c8c92ac5bae0de1427970dff4bdd4cf9bd85e (patch) | |
tree | d47d8a6808081befd72dbcafb7bffadf104b1411 /libexec/ld.so/powerpc | |
parent | fe1bdbab88774dd0b581b085d5bd355f2b2ab86b (diff) |
Updated version of ld.so, contains additional functionality and fixes/
design changes required by egcs.
added support for ldconfig/ld.so.hints
changes to low level relocation code, required by egcs pic
code generation that moved global variable loads to before the
self relocation was performed. Only powerpc supported, mips code not updated.
Code cleaned up somewhat reasonably.
This code needs to be reviewed closely for significant problems
such as correctness and security.
Diffstat (limited to 'libexec/ld.so/powerpc')
-rw-r--r-- | libexec/ld.so/powerpc/archdep.h | 182 | ||||
-rw-r--r-- | libexec/ld.so/powerpc/ldasm.S | 156 | ||||
-rw-r--r-- | libexec/ld.so/powerpc/rtld_machine.c | 369 | ||||
-rw-r--r-- | libexec/ld.so/powerpc/syscall.h | 334 |
4 files changed, 1041 insertions, 0 deletions
diff --git a/libexec/ld.so/powerpc/archdep.h b/libexec/ld.so/powerpc/archdep.h new file mode 100644 index 00000000000..836fa33e1be --- /dev/null +++ b/libexec/ld.so/powerpc/archdep.h @@ -0,0 +1,182 @@ +/* $OpenBSD: archdep.h,v 1.1 2000/06/13 03:40:32 rahnds 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 _POWERPC_ARCHDEP_H_ +#define _POWERPC_ARCHDEP_H_ + +#define DL_MALLOC_ALIGN 4 /* Arch constraint or otherwise */ + +#define MACHID EM_PPC /* ELF e_machine ID value checked */ + +#define RELTYPE Elf32_Rela +#define RELSIZE sizeof(Elf32_Rela) + +#include <elf_abi.h> +#include <machine/reloc.h> + +/* HACK */ +#define DT_PROCNUM 0 +#ifndef DT_BIND_NOW +#define DT_BIND_NOW 0 +#endif + +/* + * Simple reloc of REL32's. Used by bootstrapping. + */ +#define SIMPLE_RELOC(r, s, p, v) \ + if(ELF32_R_TYPE((r)->r_info) == RELOC_32) { \ + if((ELF32_ST_BIND((s)->st_info) == STB_LOCAL) && \ + (ELF32_ST_TYPE((s)->st_info) == STT_SECTION || \ + ELF32_ST_TYPE((s)->st_info) == STT_NOTYPE) ) { \ + *(p) += (v); \ + } \ + else { \ + *(p) = (v) + (s)->st_value; \ + } \ + } + +/* + * The following functions are declared inline so they can + * be used before bootstrap linking has been finished. + */ +static inline void +_dl_dcbf(Elf32_Addr *addr) +{ + __asm__ volatile ("li 0, 0\n\t" + "dcbf 0, %0" + : : "r" (addr) : "0"); +} + +static inline int _dl_write (int fd, const char* buf, int len); +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++) {}; + if(c < 0) { + return(0); + } + return(d[-1] - s[-1]); +} + +static inline int +_dl_strcmp(const char *d, const char *s) +{ + while(*d && *d++ == *s++) {}; + return(d[-1] - s[-1]); +} + +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(Elf32_Rela *r, + const Elf32_Sym *s, Elf32_Addr *p, int v) +{ + if(ELF32_R_TYPE((r)->r_info) == RELOC_RELATIVE) { + if((ELF32_ST_BIND((s)->st_info) == STB_LOCAL) && + ((ELF32_ST_TYPE((s)->st_info) == STT_SECTION) || + (ELF32_ST_TYPE((s)->st_info) == STT_NOTYPE)) ) { + *(p) = (v) + (r)->r_addend; + } else { + *(p) = (v) + (s)->st_value + (r)->r_addend; + } + } else if(ELF32_R_TYPE((r)->r_info) == RELOC_JMP_SLOT) { + Elf32_Addr val = (v) + (s)->st_value + (r)->r_addend - + (Elf32_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(ELF32_R_TYPE((r)->r_info) == RELOC_GLOB_DAT) { + *(p) = (v) + (s)->st_value + (r)->r_addend; + } else { + /* error */ + } +} + +#endif /* _POWERPC_ARCHDEP_H_ */ diff --git a/libexec/ld.so/powerpc/ldasm.S b/libexec/ld.so/powerpc/ldasm.S new file mode 100644 index 00000000000..34a674fe0fe --- /dev/null +++ b/libexec/ld.so/powerpc/ldasm.S @@ -0,0 +1,156 @@ +/* $OpenBSD: ldasm.S,v 1.1 2000/06/13 03:40:35 rahnds Exp $ */ + +/* + * Copyright (c) 1999 Dale Rahn + * + * 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. + * + */ + +/* + * #ifdef blrl_never_causes_illegal_access + * background for the else of this define + * On the machine this code is being written, on a large portion + * of the tims this code is executed the blrl instruct causes an + * illegal instruction, hopefully by touching the page with a load + * will prevent the execute access from faulting. + */ + +#define AUX_entry 9 + +#include <machine/asm.h> + +ENTRY(_dl_start) + mr 19, 1 + stwu 1, (-16 -((AUX_entry+1)*4))(1) # Some space. + + mflr 27 /* save off old link register */ + stw 27, 4(19) /* save in normal location */ + + # squirrel away the arguments for main + mr 20, 3 #argc + mr 21, 4 #argv + mr 22, 5 #envp + mr 23, 6 # ??? + + .local .L___offset_sym + .type .L___offset_sym,@function + bl 1f +.L___offset_sym: + # this instruction never gets executed but can be used + # to find the virtual address where the page is loaded. + bl _GLOBAL_OFFSET_TABLE_@local-4 + bl _DYNAMIC@local +1: + mflr 5 # this stores where we are (+4) + lwz 18, 0(5) # load the instruction at offset_sym + # it contains an offset to the location + # of the GOT. + + rlwinm 18,18,0,8,30 # mask off the offset portion of the instr. + + /* + * these adds effectively calculates the value the + * bl _GLOBAL_OFFSET_TABLE_@local-4 + * operation that would be below would calulate. + */ + add 28, 18, 5 + + li 0, 0 + dcbf 5, 18 + sync + isync + icbi 5, 18 # make certain that the got table addr is + # not in the icache + + sync + isync + + addi 28, 28, 4 + mr 29, 28 + + lwz 30, 0(28) # this loads the first entry of the GOT + # thus forcing it to be paged in when + # we jump to it below. + + + # calculate where we want to be (via the got) + bl _GLOBAL_OFFSET_TABLE_@local-4 + mflr 28 + + + lwz 4, .L___offset_sym@got(28) + mr 6, 4 # make copy of register for debugging + + /* This cheats and calculates the address of _DYNAMIC + * the same way that the GLOBAL_OFFSET_TABLE was calcuated + */ + lwz 18, 4(5) + rlwinm 18,18,0,8,30 # mask off the offset portion of the instr. + add 8, 18, 5 # address of _DYNAMIC (arg6 for _dl_boot) + addi 18, 8, 4 # correction. + + sub 4, 5, 4 # calculate offset (arg1 for _dl_boot) + mr 17, 4 + + + mr 3, 19 # Get stack pointer (arg0 for _dl_boot). + mr 4, 17 # loff + mr 5, 20 # argc + mr 6, 21 # argv + mr 7, 22 # envp + mr 8, 18 # dynamicp + addi 9, 1, 8 # dl_data + + bl _dl_boot_bind@local + + mr 3, 21 # argv + mr 4, 22 # envp + mr 5, 17 # loff + mr 6, 18 # dynamicp + addi 7, 1, 8 # dl_data + + bl _dl_boot@local + + mtctr 3 # put return value into ctr to execute + + # get back the squirreled away the arguments for main + mr 3, 20 + mr 4, 21 + mr 5, 22 + mr 6, 23 + + + mtlr 27 + lwz 1, 0(1) # Restore stack pointer. + bctr # Go execute the 'real' program. + + .globl _dl_rt_resolve + .data +_dl_rt_resolve: + .long 0 diff --git a/libexec/ld.so/powerpc/rtld_machine.c b/libexec/ld.so/powerpc/rtld_machine.c new file mode 100644 index 00000000000..7762c76773a --- /dev/null +++ b/libexec/ld.so/powerpc/rtld_machine.c @@ -0,0 +1,369 @@ +/* $OpenBSD: rtld_machine.c,v 1.1 2000/06/13 03:40:38 rahnds Exp $ */ + +/* + * Copyright (c) 1999 Dale Rahn + * + * 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 <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; + Elf32_Addr loff; + Elf32_Rela *relas; + /* for jmp table relocations */ + Elf32_Addr *pltcall; + Elf32_Addr *plttable; + + Elf32_Addr * first_rela; + + loff = object->load_offs; + numrela = object->Dyn.info[relasz] / sizeof(Elf32_Rela); + relas = (Elf32_Rela *)(object->Dyn.info[rel]); + +#if 0 +_dl_printf("object relocation size %x, numrela %x\n", + 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 */ + Elf32_Addr val; + + first_rela = (Elf32_Addr *) + (((Elf32_Rela *)(object->Dyn.info[DT_JMPREL]))->r_offset + + loff); + /* Need to construct table to do jumps */ + pltcall = (Elf32_Addr *)(first_rela) - 12; +#if 0 +_dl_printf("creating pltcall at %x\n", pltcall); +_dl_printf("md_reloc( jumprel %x\n", first_rela ); +#endif + plttable = (Elf32_Addr *) + ((Elf32_Addr)first_rela) + (2 * + (object->Dyn.info[DT_PLTRELSZ]/sizeof(Elf32_Rela)) + ); + +#if 0 +_dl_printf("md_reloc: plttbl size %x\n", + (object->Dyn.info[DT_PLTRELSZ]/sizeof(Elf32_Rela)) +); +_dl_printf("md_reloc: plttable %x\n", plttable); +#endif + pltcall[-1]= 0x504c5400; /* PLT tag :-) */ + val = ((Elf32_Addr)plttable >> 16) + + (((Elf32_Addr)plttable & 0x00008000) >> 15); + pltcall[0] = 0x3d6b0000 | val; /* addis r11,r11,.PLTtable@ha*/ + val = (Elf32_Addr)plttable & 0x0000ffff; + pltcall[1] = 0x816b0000 | val; /* lwz r11,plttable@l(r11) */ + pltcall[2] = 0x7d6903a6; /* mtctr r12 */ + pltcall[3] = 0x4e800420; /* bctr */ + _dl_dcbf(pltcall); + _dl_dcbf(&pltcall[3]); + } else { + first_rela = NULL; + } + + for(i = 0; i < numrela; i++, relas++) { + Elf32_Addr *r_addr = (Elf32_Addr *)(relas->r_offset + loff); + Elf32_Addr ooff; + const Elf32_Sym *sym, *this; + const char *symn; + + if(ELF32_R_SYM(relas->r_info) == 0xffffff) { + continue; + } + + sym = object->dyn.symtab; + sym += ELF32_R_SYM(relas->r_info); + this = sym; + symn = object->dyn.strtab + sym->st_name; + + if(ELF32_R_SYM(relas->r_info) && + !(ELF32_ST_BIND(sym->st_info) == STB_LOCAL && + ELF32_ST_TYPE (sym->st_info) == STT_NOTYPE)) { + + ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1); + if(!this && ELF32_ST_BIND(sym->st_info) == STB_GLOBAL) { + _dl_printf("%s:" + " %s :can't resolve reference '%s'\n", + _dl_progname, object->load_name, + symn); + fails++; + } + + } + + switch(ELF32_R_TYPE(relas->r_info)) { +#if 1 + case RELOC_32: + if(ELF32_ST_BIND(sym->st_info) == STB_LOCAL && + (ELF32_ST_TYPE(sym->st_info) == STT_SECTION || + ELF32_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 RELOC_RELATIVE: + if(ELF32_ST_BIND(sym->st_info) == STB_LOCAL && + (ELF32_ST_TYPE(sym->st_info) == STT_SECTION || + ELF32_ST_TYPE(sym->st_info) == STT_NOTYPE) ) { + *r_addr = loff + relas->r_addend; + +#if 0 +_dl_printf("rel1 r_addr %x val %x loff %x ooff %x addend %x\n", r_addr, +loff + relas->r_addend, loff, ooff, relas->r_addend); +#endif + + } else { + *r_addr = loff + this->st_value + + relas->r_addend; + } + break; + case RELOC_JMP_SLOT: + { + Elf32_Addr val = ooff + this->st_value + + relas->r_addend - (Elf32_Addr)r_addr; + if (!(((val & 0xfe000000) == 0x00000000) || + ((val & 0xfe000000) == 0xfe000000))) + { + int index; +#if 0 +_dl_printf(" ooff %x, sym val %x, addend %x" + " r_addr %x 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 = (Elf32_Addr)pltcall - + (Elf32_Addr)&r_addr[2]; + r_addr[1] = 0x396b0000 | val; + val &= ~0xfc000000; + val |= 0x48000000; + r_addr[2] = val; + + } else { +#if 0 + _dl_printf(" index %d, pltcall %x r_addr %x\n", + index, pltcall, r_addr); +#endif + + r_addr[0] = 0x39600000 | (index * 4); + val = (Elf32_Addr)pltcall - + (Elf32_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; +#if 0 + _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 RELOC_GLOB_DAT: + *r_addr = ooff + this->st_value + relas->r_addend; + break; +#if 0 + /* 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)) + { + /* 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: + { + Elf32_Addr val = ooff + this->st_value + + relas->r_addend - (Elf32_Addr)r_addr; + if (((val & 0xffff8000) != 0) && + ((val & 0xffff8000) != 0xffff8000)) + { + /* invalid offset */ + _dl_exit(20); + } + val &= ~0xffff0003; + val |= (*r_addr & 0xffff0003); + *r_addr = val; +#if 0 + _dl_printf("rel 14 %x val %x\n", + r_addr, val); +#endif + + _dl_dcbf(r_addr); + } + break; + case RELOC_COPY: +#if 0 + _dl_printf("copy r_addr %x, sym %x [%s] size %d val %x\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 Elf32_Sym *cpysrc = NULL; + Elf32_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; + } +#if 0 +_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 RELOC_NONE: + break; + + default: + _dl_printf("%s:" + " %s: unsupported relocation '%s' %d at %x\n", + _dl_progname, object->load_name, symn, + ELF32_R_TYPE(relas->r_info), r_addr ); + _dl_exit(1); + } + } + object->status |= STAT_RELOC_DONE; + 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 */ +} diff --git a/libexec/ld.so/powerpc/syscall.h b/libexec/ld.so/powerpc/syscall.h new file mode 100644 index 00000000000..e169333b8a3 --- /dev/null +++ b/libexec/ld.so/powerpc/syscall.h @@ -0,0 +1,334 @@ +/* $OpenBSD: syscall.h,v 1.1 2000/06/13 03:40:39 rahnds 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. + * + */ + +#ifdef USE_CACHE +#include <sys/stat.h> +#endif + +#include <sys/syscall.h> + +#ifndef _dl_MAX_ERRNO +#define _dl_MAX_ERRNO 4096 +#endif +#define _dl_check_error(__res) \ + ((int) __res < 0 && (int) __res >= -_dl_MAX_ERRNO) + +/* + * Inlined system call functions that can be used before + * any dynamic address resoving has been done. + */ + +void _dl_printf(const char *, ...); + +static inline int +_dl_exit (int status) +{ + register int __status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "mr 3,%2\n\t" + "sc" + : "=r" (__status) + : "r" (SYS_exit), "r" (status) : "0", "3"); + while(1); +} + +static inline int +_dl_open (const char* addr, unsigned int flags) +{ + register int status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "mr 3,%2\n\t" + "mr 4,%3\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3,-1\n\t" + "1:" + : "=r" (status) + : "r" (SYS_open), "r" (addr), "r" (flags) + : "0", "3", "4" ); + return status; +} + +static inline int +_dl_close (int fd) +{ + register int status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "mr 3,%2\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3,-1\n\t" + "1:" + : "=r" (status) + : "r" (SYS_close), "r" (fd) + : "0", "3"); + return status; +} + +static inline int +_dl_write (int fd, const char* buf, int len) +{ + register int status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "mr 3,%2\n\t" + "mr 4,%3\n\t" + "mr 5,%4\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3,-1\n\t" + "1:" + : "=r" (status) + : "r" (SYS_write), "r" (fd), "r" (buf), "r" (len) + : "0", "3", "4", "5" ); + return status; +} + +static inline int +_dl_read (int fd, const char* buf, int len) +{ + register int status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "mr 3,%2\n\t" + "mr 4,%3\n\t" + "mr 5,%4\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3,-1\n\t" + "1:" + : "=r" (status) + : "r" (SYS_read), "r" (fd), "r" (buf), "r" (len) + : "0", "3", "4", "5"); + return status; +} +#if 0 +static inline int +_dl__syscall(quad_t val, ...) +{ + register int status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "mr 3,%2\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3,-1\n\t" + "1:" + : "=r" (status) + : "r" (SYS___syscall), "r" (val) + : "0"); + +} +#else + +#define STRINGIFY(x) #x +#define XSTRINGIFY(x) STRINGIFY(x) +int _dl__syscall(quad_t val, ...); +__asm__(".align 2\n\t" + ".type _dl__syscall,@function\n" + "_dl__syscall:\n\t" + "li 0, " XSTRINGIFY(SYS___syscall) "\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3, -1\n\t" + "1:\n\t" + "blr"); +#endif +static int +_dl_mmap (void *addr, unsigned int len, unsigned int prot, + unsigned int flags, int fd, off_t offset) +{ + return((int)_dl__syscall((quad_t)SYS_mmap, addr, len, prot, + flags, fd, 0, offset)); +} + +static inline int +_dl_munmap (const void* addr, unsigned int len) +{ + register int status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "mr 3,%2\n\t" + "mr 4,%3\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3,-1\n\t" + "1:" + : "=r" (status) + : "r" (SYS_read), "r" (addr), "r" (len) + : "0", "3", "4"); + return status; +} + +static inline int +_dl_mprotect (const void *addr, int size, int prot) +{ + register int status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "mr 3,%2\n\t" + "mr 4,%3\n\t" + "mr 5,%4\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3,-1\n\t" + "1:" + : "=r" (status) + : "r" (SYS_read), "r" (addr), "r" (size), "r" (prot) + : "0", "3", "4", "5"); + return status; +} +#if 0 + +#ifdef USE_CACHE +static inline int +_dl_stat (const char *addr, struct stat *sb) +{ + register int status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "mr 3,%2\n\t" + "mr 4,%3\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3,-1\n\t" + "1:" + : "=r" (status) + : "r" (SYS_read), "r" (addr), "r" (sb) + : "0", "3", "4"); + return status; +} + +#endif + +/* Not an actual syscall, but we need something in assembly to say + whether this is OK or not. */ + +static inline int +_dl_getuid (const void *addr, int size, int prot) +{ + register int status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3,-1\n\t" + "1:" + : "=r" (status) + : "r" (SYS_getuid) + : "0", "3"); + return status; +} +static inline int +_dl_geteuid (const void *addr, int size, int prot) +{ + register int status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3,-1\n\t" + "1:" + : "=r" (status) + : "r" (SYS_geteuid) + : "0", "3"); + return status; +} +static inline int +_dl_getgid (const void *addr, int size, int prot) +{ + register int status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3,-1\n\t" + "1:" + : "=r" (status) + : "r" (SYS_getgid) + : "0", "3"); + return status; +} +static inline int +_dl_getuid (const void *addr, int size, int prot) +{ + register int status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3,-1\n\t" + "1:" + : "=r" (status) + : "r" (SYS_getegid), + : "0", "3"); + return status; +} +static inline int +_dl_getuid (const void *addr, int size, int prot) +{ + register int status __asm__ ("3"); + __asm__ volatile ("mr 0,%1\n\t" + "sc\n\t" + "cmpwi 0, 0\n\t" + "beq 1f\n\t" + "li 3,-1\n\t" + "1:" + : "=r" (status) + : "r" (SYS_read), + : "0", "3"); + return status; +} +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); +} +#endif +static inline int +_dl_suid_ok(void) +{ + return 1; +} + +#include <elf_abi.h> |