diff options
-rw-r--r-- | libexec/ld.so/loader.c | 4 | ||||
-rw-r--r-- | libexec/ld.so/sh/Makefile.inc | 8 | ||||
-rw-r--r-- | libexec/ld.so/sh/archdep.h | 93 | ||||
-rw-r--r-- | libexec/ld.so/sh/ldasm.S | 205 | ||||
-rw-r--r-- | libexec/ld.so/sh/rtld_machine.c | 428 | ||||
-rw-r--r-- | libexec/ld.so/sh/sdivsi3.S | 69 | ||||
-rw-r--r-- | libexec/ld.so/sh/syscall.h | 64 | ||||
-rw-r--r-- | libexec/ld.so/sh/udivsi3.S | 83 |
8 files changed, 953 insertions, 1 deletions
diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c index 62d63237a79..09b6add6275 100644 --- a/libexec/ld.so/loader.c +++ b/libexec/ld.so/loader.c @@ -1,4 +1,4 @@ -/* $OpenBSD: loader.c,v 1.104 2006/09/24 21:52:49 kettenis Exp $ */ +/* $OpenBSD: loader.c,v 1.105 2006/11/10 07:44:58 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -375,6 +375,7 @@ _dl_boot(const char **argv, char **envp, const long loff, long *dl_data) * now that GOT and PLT has been relocated, and we know * page size, protect it from modification */ +#ifndef RTLD_NO_WXORX { extern char *__got_start; extern char *__got_end; @@ -396,6 +397,7 @@ _dl_boot(const char **argv, char **envp, const long loff, long *dl_data) PROT_READ|PROT_EXEC); #endif } +#endif DL_DEB(("rtld loading: '%s'\n", _dl_progname)); diff --git a/libexec/ld.so/sh/Makefile.inc b/libexec/ld.so/sh/Makefile.inc new file mode 100644 index 00000000000..19e1b36bd49 --- /dev/null +++ b/libexec/ld.so/sh/Makefile.inc @@ -0,0 +1,8 @@ +# $OpenBSD: Makefile.inc,v 1.1 2006/11/10 07:44:58 drahn Exp $ + +CFLAGS += -fpic +AFLAGS += -D_STANDALONE +AFLAGS += -I${.CURDIR}/../../lib/libc/arch/sh +SRCS+= udivsi3.S sdivsi3.S +ELF_LDFLAGS+=-z nocombreloc +LIBCSRCDIR=${.CURDIR}/../../lib/libc diff --git a/libexec/ld.so/sh/archdep.h b/libexec/ld.so/sh/archdep.h new file mode 100644 index 00000000000..a4b71daa2fc --- /dev/null +++ b/libexec/ld.so/sh/archdep.h @@ -0,0 +1,93 @@ +/* $OpenBSD: archdep.h,v 1.1 2006/11/10 07:44:58 drahn 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. + * + * 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 _SH_ARCHDEP_H_ +#define _SH_ARCHDEP_H_ + +#define DL_MALLOC_ALIGN 4 /* Arch constraint or otherwise */ + +#define MACHID EM_SH /* ELF e_machine ID value checked */ + +#define RELTYPE Elf32_Rela +#define RELSIZE sizeof(Elf32_Rela) + +#include <elf_abi.h> +#include <machine/reloc.h> +#include "syscall.h" +#include "util.h" + +/* HACK */ +#define DT_PROCNUM 0 +#ifndef DT_BIND_NOW +#define DT_BIND_NOW 0 +#endif + +#define RTLD_NO_WXORX + +/* + * The following functions are declared inline so they can + * be used before bootstrap linking has been finished. + */ + +static inline void * +_dl_mmap(void *addr, unsigned int len, unsigned int prot, + unsigned int flags, int fd, off_t offset) +{ + return((void *)(long)_dl__syscall((quad_t)SYS_mmap, addr, len, prot, + flags, fd, 0, offset)); +} + +static inline void +RELOC_REL(Elf_Rel *r, const Elf_Sym *s, Elf_Addr *p, unsigned long v) +{ + if (ELF_R_TYPE(r->r_info) == R_SH_RELATIVE) { + *p += v; + } else { + /* XXX - printf might not work here, but we give it a shot. */ + _dl_printf("Unknown bootstrap relocation.\n"); + _dl_exit(6); + } +} + +static inline void +RELOC_RELA(Elf32_Rela *r, const Elf32_Sym *s, Elf32_Addr *p, unsigned long v) +{ + if (ELF_R_TYPE(r->r_info) == R_SH_RELATIVE) { + *p = v + r->r_addend; + } else { + /* XXX - printf might not work here, but we give it a shot. */ + _dl_printf("Unknown bootstrap relocation.\n"); + _dl_exit(6); + } +} + +#define RELOC_GOT(obj, offs) + +#define GOT_PERMS (PROT_READ|PROT_EXEC) + +#endif /* _SH_ARCHDEP_H_ */ diff --git a/libexec/ld.so/sh/ldasm.S b/libexec/ld.so/sh/ldasm.S new file mode 100644 index 00000000000..7082f02e0d2 --- /dev/null +++ b/libexec/ld.so/sh/ldasm.S @@ -0,0 +1,205 @@ +/* $OpenBSD: ldasm.S,v 1.1 2006/11/10 07:44:58 drahn Exp $ */ + +/* + * Copyright (c) 2004 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. + * + * 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 DL_DATA_SIZE (16 * 4) /* XXX */ +#include <machine/asm.h> +#include <sys/syscall.h> +#include <SYS.h> + +ENTRY(_dl_start) + mov r15, r8 // save for later + mov r15,r14 + sts pr, r10 + mov r15, r4 // boot_bind(sp, dl_data) (sp) + mov.l .L_datasize, r0 + sub r0, r15 + mov r15, r5 + add #4, r5 + mov r5, r9 + mov.l .L_boot_bind, r0 + bsrf r0 + nop +.L_call_boot_bind: + mov r8, r4 + add #4, r4 + mov.l @r8, r5 //loads argc + add #2, r5 + shll2 r5 + add r8, r5 + mov r9, r6 + mov.l .L_loff, r0 + add r0, r6 + mov.l .L_boot, r0 + mov r9, r7 + mov r8, r15 + bsrf r0 + nop +.L_call_boot: + + mov r14, r15 + lds r10, pr + jmp @r0 + + .align 2 +.L_boot_bind: + .long _dl_boot_bind-.L_call_boot_bind +.L_boot: + .long _dl_boot-.L_call_boot +.L_datasize: + .long 4+4+DL_DATA_SIZE +.L_loff: + .long 7*4 + .size _dl_start, .-dl_start + + +/* + * r0 - obj + * r1 - reloff + */ + +ENTRY(_dl_bind_start) + mov.l r2, @-r15 + mov.l r3, @-r15 + mov.l r4, @-r15 + mov.l r5, @-r15 + mov.l r6, @-r15 + mov.l r7, @-r15 + sts.l pr, @-r15 + sts.l macl, @-r15 + sts.l mach, @-r15 + + mov r0, r4 /* move obj to 'C' arg */ + mov.l .L_dl_bind, r0 + bsrf r0 + mov r1, r5 /* move reloff to 'C' arg */ +.L_call_dl_bind: + + lds.l @r15+, mach + lds.l @r15+, macl + lds.l @r15+, pr + mov.l @r15+, r7 + mov.l @r15+, r6 + mov.l @r15+, r5 + mov.l @r15+, r4 + mov.l @r15+, r3 + jmp @r0 /* jump to specified address */ + mov.l @r15+, r2 + + .align 2 +.L_dl_bind: + .long _dl_bind-.L_call_dl_bind + .size _dl_bind_start, .-dl_bind_start + + + /* STUB */ + + +/* ld.so SYSCALLS */ + +#define DL_SYSCALL(n) DL_SYSCALL2(n,n) +#define DL_SYSCALL2(n,c) \ + .global __CONCAT(_dl_,n) ;\ + .type __CONCAT(_dl_,n)%function ;\ +__CONCAT(_dl_,n): ;\ + SYSTRAP(c) ;\ + bf .L_cerr ;\ + nop ;\ + rts ;\ + nop + +#define DL_SYSCALL2_NOERR(n,c) \ + .global __CONCAT(_dl_,n) ;\ + .type __CONCAT(_dl_,n)%function ;\ +__CONCAT(_dl_,n): ;\ + SYSTRAP(c) ;\ + rts ;\ + nop + + + .section ".text" + .align 4 +DL_SYSCALL(close) + + + .global _dl_exit + .type _dl_exit%function +_dl_exit: + SYSTRAP(exit) +1: + bra 1b + nop + +DL_SYSCALL(issetugid) +DL_SYSCALL2(_syscall,__syscall) +DL_SYSCALL(munmap) +DL_SYSCALL(mprotect) +DL_SYSCALL(open) +DL_SYSCALL(read) + +.L_cerr: + mov #-1, r0 + rts + nop + +DL_SYSCALL(write) +DL_SYSCALL(stat) +DL_SYSCALL(fstat) +DL_SYSCALL(fcntl) +DL_SYSCALL(gettimeofday) +DL_SYSCALL2(sysctl,__sysctl) + +DL_SYSCALL(getdirentries) + + .global _dl_sigprocmask + .type _dl_sigprocmask%function +_dl_sigprocmask: + mov r5, r2 /* fetch new sigset pointer */ + tst r2, r2 /* check new sigset pointer */ + bf 1f /* if not null, indirect */ + mov #1, r4 /* SIG_BLOCK */ + bra 2f + nop +1: mov.l @r2, r2 /* fetch indirect ... */ + mov r2, r5 /* to new mask arg */ +2: mov.l LSYS_sigprocmask, r0 + trapa #0x80 + bf .L_cerr + mov r6, r2 /* fetch old mask requested */ + tst r2, r2 /* test if old mask requested */ + bt out + mov.l r0, @r2 /* store old mask */ +out: + xor r0, r0 + rts + nop + + .align 2 +LSYS_sigprocmask: + .long SYS_sigprocmask + + diff --git a/libexec/ld.so/sh/rtld_machine.c b/libexec/ld.so/sh/rtld_machine.c new file mode 100644 index 00000000000..5922ddd73fd --- /dev/null +++ b/libexec/ld.so/sh/rtld_machine.c @@ -0,0 +1,428 @@ +/* $OpenBSD: rtld_machine.c,v 1.1 2006/11/10 07:44:58 drahn Exp $ */ + +/* + * Copyright (c) 2004 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. + * + * 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/mman.h> + +#include <nlist.h> +#include <link.h> +#include <signal.h> + +#include "syscall.h" +#include "archdep.h" +#include "resolve.h" + +void _dl_bind_start(void); /* XXX */ +Elf_Addr _dl_bind(elf_object_t *object, int reloff); +#define _RF_S 0x80000000 /* Resolve symbol */ +#define _RF_A 0x40000000 /* Use addend */ +#define _RF_P 0x20000000 /* Location relative */ +#define _RF_G 0x10000000 /* GOT offset */ +#define _RF_B 0x08000000 /* Load address relative */ +#define _RF_U 0x04000000 /* Unaligned */ +#define _RF_E 0x02000000 /* ERROR */ +#define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */ +#define _RF_RS(s) ((s) & 0xff) /* right shift */ +static int reloc_target_flags[] = { + 0, /* 0 NONE */ + _RF_S|_RF_P|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 1 PC24 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 2 ABS32 */ + _RF_S|_RF_P|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 3 REL32 */ + _RF_S|_RF_P|_RF_A| _RF_E, /* 4 REL13 */ + _RF_S|_RF_A| _RF_E, /* 5 ABS16 */ + _RF_S|_RF_A| _RF_E, /* 6 ABS12 */ + _RF_S|_RF_A| _RF_E, /* 7 T_ABS5 */ + _RF_S|_RF_A| _RF_E, /* 8 ABS8 */ + _RF_S|_RF_B|_RF_A| _RF_E, /* 9 SBREL32 */ + _RF_S|_RF_P|_RF_A| _RF_E, /* 10 T_PC22 */ + _RF_S|_RF_P|_RF_A| _RF_E, /* 11 T_PC8 */ + _RF_E, /* 12 Reserved */ + _RF_S|_RF_A| _RF_E, /* 13 SWI24 */ + _RF_S|_RF_A| _RF_E, /* 14 T_SWI8 */ + _RF_E, /* 15 OBSL */ + _RF_E, /* 16 OBSL */ + _RF_E, /* 17 UNUSED */ + _RF_E, /* 18 UNUSED */ + _RF_E, /* 19 UNUSED */ + _RF_S| _RF_SZ(32) | _RF_RS(0), /* 20 COPY */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 21 GLOB_DAT */ + _RF_S| _RF_SZ(32) | _RF_RS(0), /* 22 JMP_SLOT */ + _RF_A| _RF_B| _RF_SZ(32) | _RF_RS(0), /* 23 RELATIVE */ + _RF_E, /* 24 GOTOFF */ + _RF_E, /* 25 GOTPC */ + _RF_E, /* 26 GOT32 */ + _RF_E, /* 27 PLT32 */ + _RF_E, /* 28 UNUSED */ + _RF_E, /* 29 UNUSED */ + _RF_E, /* 30 UNUSED */ + _RF_E, /* 31 UNUSED */ + _RF_E, /* 32 A_PCR 0 */ + _RF_E, /* 33 A_PCR 8 */ + _RF_E, /* 34 A_PCR 16 */ + _RF_E, /* 35 B_PCR 0 */ + _RF_E, /* 36 B_PCR 12 */ + _RF_E, /* 37 B_PCR 20 */ + _RF_E, /* 38 RELAB32 */ + _RF_E, /* 39 ROSGREL32 */ + _RF_E, /* 40 V4BX */ + _RF_E, /* 41 STKCHK */ + _RF_E /* 42 TSTKCHK */ +}; + +#define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) +#define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) +#define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) +#define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0) +#define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) +#define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) +#define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) +static int reloc_target_bitmask[] = { +#define _BM(x) (x == 32? ~0 : ~(-(1UL << (x)))) + _BM(0), /* 0 NONE */ + _BM(24), /* 1 PC24 */ + _BM(32), /* 2 ABS32 */ + _BM(32), /* 3 REL32 */ + _BM(0), /* 4 REL13 */ + _BM(0), /* 5 ABS16 */ + _BM(0), /* 6 ABS12 */ + _BM(0), /* 7 T_ABS5 */ + _BM(0), /* 8 ABS8 */ + _BM(32), /* 9 SBREL32 */ + _BM(0), /* 10 T_PC22 */ + _BM(0), /* 11 T_PC8 */ + _BM(0), /* 12 Reserved */ + _BM(0), /* 13 SWI24 */ + _BM(0), /* 14 T_SWI8 */ + _BM(0), /* 15 OBSL */ + _BM(0), /* 16 OBSL */ + _BM(0), /* 17 UNUSED */ + _BM(0), /* 18 UNUSED */ + _BM(0), /* 19 UNUSED */ + _BM(32), /* 20 COPY */ + _BM(32), /* 21 GLOB_DAT */ + _BM(32), /* 22 JMP_SLOT */ + _BM(32), /* 23 RELATIVE */ + _BM(0), /* 24 GOTOFF */ + _BM(0), /* 25 GOTPC */ + _BM(0), /* 26 GOT32 */ + _BM(0), /* 27 PLT32 */ + _BM(0), /* 28 UNUSED */ + _BM(0), /* 29 UNUSED */ + _BM(0), /* 30 UNUSED */ + _BM(0), /* 31 UNUSED */ + _BM(0), /* 32 A_PCR 0 */ + _BM(0), /* 33 A_PCR 8 */ + _BM(0), /* 34 A_PCR 16 */ + _BM(0), /* 35 B_PCR 0 */ + _BM(0), /* 36 B_PCR 12 */ + _BM(0), /* 37 B_PCR 20 */ + _BM(0), /* 38 RELAB32 */ + _BM(0), /* 39 ROSGREL32 */ + _BM(0), /* 40 V4BX */ + _BM(0), /* 41 STKCHK */ + _BM(0) /* 42 TSTKCHK */ +#undef _BM +}; +#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) + +#define R_TYPE(x) R_SH_ ## x + +void _dl_reloc_plt(Elf_Word *where, Elf_Addr value, Elf_Rel *rel); + +int +_dl_md_reloc(elf_object_t *object, int rel, int relsz) +{ + long i; + long numrel; + long fails = 0; + Elf_Addr loff; + Elf_Rel *rels; + struct load_list *llist; + + loff = object->load_offs; + numrel = object->Dyn.info[relsz] / sizeof(Elf_Rel); + rels = (Elf_Rel *)(object->Dyn.info[rel]); + + if (rels == NULL) + return(0); + + /* + * unprotect some segments if we need it. + */ + if ((object->dyn.textrel == 1) && (rel == DT_REL || rel == DT_RELA)) { + for (llist = object->load_list; + llist != NULL; + llist = llist->next) { + if (!(llist->prot & PROT_WRITE)) + _dl_mprotect(llist->start, llist->size, + llist->prot|PROT_WRITE); + } + } + + for (i = 0; i < numrel; i++, rels++) { + Elf_Addr *where, value, ooff, mask; + Elf_Word type; + const Elf_Sym *sym, *this; + const char *symn; + + type = ELF_R_TYPE(rels->r_info); + + if (reloc_target_flags[type] & _RF_E) { + _dl_printf(" bad relocation %d %d\n", i, type); + _dl_exit(1); + } + if (type == R_TYPE(NONE)) + continue; + + if (type == R_TYPE(JMP_SLOT) && rel != DT_JMPREL) + continue; + + where = (Elf_Addr *)(rels->r_offset + loff); + + if (RELOC_USE_ADDEND(type)) +#ifdef LDSO_ARCH_IS_RELA_ + value = rels->r_addend; +#else + value = *where & RELOC_VALUE_BITMASK(type); +#endif + else + value = 0; + + sym = NULL; + symn = NULL; + if (RELOC_RESOLVE_SYMBOL(type)) { + sym = object->dyn.symtab; + sym += ELF_R_SYM(rels->r_info); + symn = object->dyn.strtab + sym->st_name; + + if (sym->st_shndx != SHN_UNDEF && + ELF_ST_BIND(sym->st_info) == STB_LOCAL) { + value += loff; + } else { + this = NULL; + ooff = _dl_find_symbol_bysym(object, + ELF_R_SYM(rels->r_info), &this, + SYM_SEARCH_ALL|SYM_WARNNOTFOUND| + ((type == R_TYPE(JMP_SLOT)) ? + SYM_PLT : SYM_NOTPLT), + sym, NULL); + if (this == NULL) { +resolve_failed: + if (ELF_ST_BIND(sym->st_info) != + STB_WEAK) + fails++; + continue; + } + value += (Elf_Addr)(ooff + this->st_value); + } + } + + if (type == R_TYPE(JMP_SLOT)) { + /* + _dl_reloc_plt((Elf_Word *)where, value, rels); + */ + *where = value; + continue; + } + + if (type == R_TYPE(COPY)) { + void *dstaddr = where; + const void *srcaddr; + const Elf_Sym *dstsym = sym, *srcsym = NULL; + Elf_Addr soff; + + soff = _dl_find_symbol(symn, &srcsym, + SYM_SEARCH_OTHER|SYM_WARNNOTFOUND|SYM_NOTPLT, + dstsym, object, NULL); + if (srcsym == NULL) + goto resolve_failed; + + srcaddr = (void *)(soff + srcsym->st_value); + _dl_bcopy(srcaddr, dstaddr, dstsym->st_size); + continue; + } + + if (RELOC_PC_RELATIVE(type)) + value -= (Elf_Addr)where; + if (RELOC_BASE_RELATIVE(type)) + value += loff; + + mask = RELOC_VALUE_BITMASK(type); + value >>= RELOC_VALUE_RIGHTSHIFT(type); + value &= mask; + + if (RELOC_UNALIGNED(type)) { + /* Handle unaligned relocations. */ + Elf_Addr tmp = 0; + char *ptr = (char *)where; + int i, size = RELOC_TARGET_SIZE(type)/8; + + /* Read it in one byte at a time. */ + for (i=0; i<size; i++) + tmp = (tmp << 8) | ptr[i]; + + tmp &= ~mask; + tmp |= value; + + /* Write it back out. */ + for (i=0; i<size; i++) + ptr[i] = ((tmp >> (8*i)) & 0xff); + } else { + *where &= ~mask; + *where |= value; + } + } + + /* reprotect the unprotected segments */ + if ((object->dyn.textrel == 1) && (rel == DT_REL || rel == DT_RELA)) { + for (llist = object->load_list; + llist != NULL; + llist = llist->next) { + if (!(llist->prot & PROT_WRITE)) + _dl_mprotect(llist->start, llist->size, + llist->prot); + } + } + + return (fails); +} + +/* + * Relocate the Global Offset Table (GOT). + * This is done by calling _dl_md_reloc on DT_JUMPREL for DL_BIND_NOW, + * otherwise the lazy binding plt initialization is performed. + */ +void +_dl_md_reloc_got(elf_object_t *object, int lazy) +{ + Elf_Addr *pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT]; + Elf_Addr ooff; + const Elf_Sym *this; + int i, num; + Elf_Rel *rel; + + if (object->Dyn.info[DT_PLTREL] != DT_REL) + return; + + object->got_addr = NULL; + object->got_size = 0; + this = NULL; + ooff = _dl_find_symbol("__got_start", &this, + SYM_SEARCH_OBJ|SYM_NOWARNNOTFOUND|SYM_PLT, NULL, object, NULL); + if (this != NULL) + object->got_addr = ooff + this->st_value; + + this = NULL; + ooff = _dl_find_symbol("__got_end", &this, + SYM_SEARCH_OBJ|SYM_NOWARNNOTFOUND|SYM_PLT, NULL, object, NULL); + if (this != NULL) + object->got_size = ooff + this->st_value - object->got_addr; + + object->plt_size = 0; /* Text PLT on ARM */ + + if (object->got_addr == NULL) + object->got_start = NULL; + else { + object->got_start = ELF_TRUNC(object->got_addr, _dl_pagesz); + object->got_size += object->got_addr - object->got_start; + object->got_size = ELF_ROUND(object->got_size, _dl_pagesz); + } + object->plt_start = NULL; + + if (!lazy) { + _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); + } else { + rel = (Elf_Rel *)(object->Dyn.info[DT_JMPREL]); + num = (object->Dyn.info[DT_PLTRELSZ]); + + for (i = 0; i < num/sizeof(Elf_Rel); i++, rel++) { + Elf_Addr *where; + where = (Elf_Addr *)(rel->r_offset + object->load_offs); + *where += object->load_offs; + } + + pltgot[1] = (Elf_Addr)object; + pltgot[2] = (Elf_Addr)_dl_bind_start; + } + if (object->got_size != 0) + _dl_mprotect((void*)object->got_addr, object->got_size, + PROT_READ); + if (object->plt_size != 0) + _dl_mprotect((void*)object->plt_start, object->plt_size, + PROT_READ|PROT_EXEC); +} + +Elf_Addr +_dl_bind(elf_object_t *object, int relidx) +{ + Elf_Rel *rel; + Elf_Word *addr; + const Elf_Sym *sym, *this; + const char *symn; + Elf_Addr ooff, newval; + sigset_t omask, nmask; + + rel = ((Elf_Rel *)object->Dyn.info[DT_JMPREL]) + (relidx); + + sym = object->dyn.symtab; + sym += ELF_R_SYM(rel->r_info); + symn = object->dyn.strtab + sym->st_name; + + this = NULL; + ooff = _dl_find_symbol(symn, &this, + SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym, + object, NULL); + if (this == NULL) { + _dl_printf("lazy binding failed!\n"); + *((int *)0) = 0; /* XXX */ + } + + addr = (Elf_Addr *)(object->load_offs + rel->r_offset); + newval = ooff + this->st_value; + + /* if GOT is protected, allow the write */ + if (object->got_size != 0) { + sigfillset(&nmask); + _dl_sigprocmask(SIG_BLOCK, &nmask, &omask); + _dl_mprotect((void*)object->got_start, object->got_size, + PROT_READ|PROT_WRITE); + } + + if (*addr != newval) + *addr = newval; + + /* put the GOT back to RO */ + if (object->got_size != 0) { + _dl_mprotect((void*)object->got_start, object->got_size, + PROT_READ); + _dl_sigprocmask(SIG_SETMASK, &omask, NULL); + } + return newval; +} diff --git a/libexec/ld.so/sh/sdivsi3.S b/libexec/ld.so/sh/sdivsi3.S new file mode 100644 index 00000000000..f7ef27a34c5 --- /dev/null +++ b/libexec/ld.so/sh/sdivsi3.S @@ -0,0 +1,69 @@ +/* $OpenBSD: sdivsi3.S,v 1.1 2006/11/10 07:44:58 drahn Exp $ */ +/* $NetBSD: sdivsi3.S,v 1.8 2006/05/22 20:56:44 uwe Exp $ */ + +/* copied from libkern with raise code removed */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + * from: @(#)udivsi3.s 5.1 (Berkeley) 5/15/90 + */ + +#include <machine/asm.h> + +/* r0 <= r4 / r5 */ +NENTRY(__sdivsi3) + mov r4, r0 + mov r5, r1 + + tst r1, r1 + bt div_by_zero + + mov #0, r2 + div0s r2, r0 + subc r3, r3 + subc r2, r0 + div0s r1, r3 +#define DIVSTEP rotcl r0; div1 r1, r3 + /* repeat 32 times */ + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; +#undef DIVSTEP + rotcl r0 + + rts + addc r2, r0 + +div_by_zero: + rts + mov #0, r0 diff --git a/libexec/ld.so/sh/syscall.h b/libexec/ld.so/sh/syscall.h new file mode 100644 index 00000000000..be119fc778a --- /dev/null +++ b/libexec/ld.so/sh/syscall.h @@ -0,0 +1,64 @@ +/* $OpenBSD: syscall.h,v 1.1 2006/11/10 07:44:58 drahn 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. + * + * 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 __DL_SYSCALL_H__ +#define __DL_SYSCALL_H__ + +#include <sys/syscall.h> +#include <sys/stat.h> +#include <sys/signal.h> + +#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(int); +int _dl_exit(int); +int _dl_issetugid(void); +long _dl__syscall(quad_t, ...); +int _dl_mprotect(const void *, int, int); +int _dl_munmap(const void *, unsigned int); +int _dl_open(const char *, unsigned int); +int _dl_read(int, const char *, int); +int _dl_stat(const char *, struct stat *); +int _dl_fstat(int, struct stat *); +int _dl_fcntl(int, int, ...); +int _dl_getdirentries(int, char*, int, long *); +int _dl_sigprocmask(int, const sigset_t *, sigset_t *); +int _dl_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int _dl_gettimeofday(struct timeval *tp, struct timezone *tzp); + +static inline off_t +_dl_lseek(int fildes, off_t offset, int whence) +{ + return _dl__syscall((quad_t)SYS_lseek, fildes, 0, offset, whence); +} + +#endif /*__DL_SYSCALL_H__*/ diff --git a/libexec/ld.so/sh/udivsi3.S b/libexec/ld.so/sh/udivsi3.S new file mode 100644 index 00000000000..a11ad8ce1a1 --- /dev/null +++ b/libexec/ld.so/sh/udivsi3.S @@ -0,0 +1,83 @@ +/* $OpenBSD: udivsi3.S,v 1.1 2006/11/10 07:44:58 drahn Exp $ */ +/* $NetBSD: udivsi3.S,v 1.7 2006/05/22 20:56:44 uwe Exp $ */ + +/* copied from libkern with raise code removed */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + * from: @(#)udivsi3.s 5.1 (Berkeley) 5/15/90 + */ + +#include <machine/asm.h> + +/* + * IMPORTANT: This function is special. + * + * This function is an auxiliary function that is referenced by the + * code generated by gcc for integer division. But gcc does NOT treat + * a call to this function as an ordinary function call w.r.t. the set + * of register this call clobbers. See the definition of "udivsi3_i1" + * in gcc/config/sh/sh.md. + * + * Any call to this function MUST NOT clobber any registers besides r4 + * and r0, where the result is returned. At the time of the call the + * r4 contains the first argument, so we are only left with r0, and we + * cannot do anything meaningful using only one register. The + * consequences are: + * + * . this function cannot have _PROF_PROLOGUE + * . this function cannot be called via PLT + */ + + +/* r0 <= r4 / r5 */ +NENTRY(__udivsi3) + tst r5, r5 + bt div_by_zero + + mov #0, r0 + div0u +#define DIVSTEP rotcl r4; div1 r5, r0 + /* repeat 32 times */ + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; + DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; DIVSTEP; +#undef DIVSTEP + rotcl r4 + + rts + mov r4, r0 + +div_by_zero: + rts + mov #0, r0 |