diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2013-01-20 23:01:45 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2013-01-20 23:01:45 +0000 |
commit | bff7d10841ef6922ebf90625e6761701537fbde4 (patch) | |
tree | fb109592d309cee5b59dace36a9675e690d20613 /libexec | |
parent | 13726355595f5d0c6ee8bb3f6afee91ccc824d8f (diff) |
A first cut at ld.so bits for m88k. Lazy binding is currently disabled as it
does not work beyond the first few lazy resolver calls. But that's already
enough to run simple binaries.
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/ld.so/m88k/Makefile.inc | 7 | ||||
-rw-r--r-- | libexec/ld.so/m88k/archdep.h | 73 | ||||
-rw-r--r-- | libexec/ld.so/m88k/ldasm.S | 236 | ||||
-rw-r--r-- | libexec/ld.so/m88k/memcpy.c | 58 | ||||
-rw-r--r-- | libexec/ld.so/m88k/rtld_machine.c | 387 | ||||
-rw-r--r-- | libexec/ld.so/m88k/syscall.h | 71 |
6 files changed, 832 insertions, 0 deletions
diff --git a/libexec/ld.so/m88k/Makefile.inc b/libexec/ld.so/m88k/Makefile.inc new file mode 100644 index 00000000000..fb435868c31 --- /dev/null +++ b/libexec/ld.so/m88k/Makefile.inc @@ -0,0 +1,7 @@ +# $OpenBSD: Makefile.inc,v 1.1 2013/01/20 23:01:44 miod Exp $ + +LIBCSRCDIR=${.CURDIR}/../../lib/libc +CFLAGS += -fpic +CPPFLAGS += -I${LIBCSRCDIR}/arch/m88k + +SRCS+= memcpy.c diff --git a/libexec/ld.so/m88k/archdep.h b/libexec/ld.so/m88k/archdep.h new file mode 100644 index 00000000000..019acd62004 --- /dev/null +++ b/libexec/ld.so/m88k/archdep.h @@ -0,0 +1,73 @@ +/* $OpenBSD: archdep.h,v 1.1 2013/01/20 23:01:44 miod 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 _M88K_ARCHDEP_H_ +#define _M88K_ARCHDEP_H_ + +#define DL_MALLOC_ALIGN 4 /* Arch constraint or otherwise */ + +#define MACHID EM_88K /* 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" + +/* + * The following functions are declared inline so they can + * be used before bootstrap linking has been finished. + */ + +static inline void +RELOC_REL(Elf_Rel *r, const Elf_Sym *s, Elf_Addr *p, unsigned long v) +{ + /* m88k does not use REL type relocations */ + _dl_exit(20); +} + +static inline void +RELOC_RELA(Elf32_Rela *r, const Elf32_Sym *s, Elf32_Addr *p, unsigned long v, + Elf_Addr *pltgot) +{ + if (ELF32_R_TYPE(r->r_info) == RELOC_BBASED_32) { + *p = v + r->r_addend; + } else { + /* _dl_printf("Unexpected bootstrap relocation (%d).\n", + ELF32_R_TYPE(r->r_info)); */ + _dl_exit(6); + } +} + +#define RELOC_GOT(obj, offs) do { } while (0) + +#define GOT_PERMS PROT_READ + +#endif /* _M88K_ARCHDEP_H_ */ diff --git a/libexec/ld.so/m88k/ldasm.S b/libexec/ld.so/m88k/ldasm.S new file mode 100644 index 00000000000..05a07538379 --- /dev/null +++ b/libexec/ld.so/m88k/ldasm.S @@ -0,0 +1,236 @@ +/* $OpenBSD: ldasm.S,v 1.1 2013/01/20 23:01:44 miod Exp $ */ + +/* + * Copyright (c) 2013 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 2006 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. + * + */ + +#include <machine/asm.h> +#include <sys/syscall.h> +#include <SYS.h> + +/* + * ld.so entry point. + * On entry: r31 points to the kernel argument struct (argv, argv, environ). + * The environment pointers list is followed by an array of AuxInfo + * structs filled by the kernel. + */ +#define DL_DATA_SIZE (4 * 16) /* 16 * sizeof(ELF_Addr) */ +ENTRY(_dl_start) + /* + * Two nop because execution may skip up to two instructions. + * See setregs() in the kernel for details. + * + * Note that I have been hacking m88k for years and still fall + * into this trap, every time. -- miod + */ + or %r0, %r0, %r0 + or %r0, %r0, %r0 + + /* + * Get some room for the contiguous AUX pointers array. + */ + or %r30, %r31, 0 + subu %r31, %r31, DL_DATA_SIZE + + /* + * Invoke _dl_boot_bind + */ + or %r2, %r30, 0 | kernel args + or %r3, %r31, 0 | array base +#if 0 /* _dl_boot_bind() can compute this itself */ + bsr 1f | the following instruction is skipped + bcnd eq0, %r0, _DYNAMIC | but gives us the pc-relative offset +1: ld.hu %r5, %r1, 2 | fetch branch offset (low 16 bits) + lda %r4, %r1[%r5] | +#endif + bsr _dl_boot_bind + + ld %r2, %r30, 0 | argc + addu %r6, %r30, 4 + 4 + lda %r3, %r6[%r2] | envp + ld %r4, %r31, 4 * 7 | ldoff +/* DEBUG */ or %r29, %r4, %r0 + or %r5, %r31, 0 | array base + bsr.n _dl_boot + addu %r2, %r30, 4 | argv + + addu %r31, %r31, DL_DATA_SIZE + jsr.n %r2 + or %r5, %r0, %r0 | cleanup as expected by CSU +END(_dl_start) + +/* + * PLT resolver entry point. + * Invoked with the following stack frame: + * r31(0x00) zero + * r31(0x04) ELF object + * r31(0x08) saved r11 + * r31(0x0c) saved r1 + * All registers but r1 and r11 must be preserved. The resolver must return + * to the resolved address with r1 restored. + */ +#define OBJECT_OFFSET (4 * 1) +#define R11_OFFSET (4 * 2) +#define R1_OFFSET (4 * 3) +#define PLT_FRAME_SIZE (4 * 4) +#define REG_SIZE (4 * 12) +ENTRY(_dl_bind_start) + /* + * Preserve caller-saved registers. + */ + subu %r31, %r31, REG_SIZE + st %r2, %r31, 4 * 0 + st %r3, %r31, 4 * 1 + st %r4, %r31, 4 * 2 + st %r5, %r31, 4 * 3 + st %r6, %r31, 4 * 4 + st %r7, %r31, 4 * 5 + st %r8, %r31, 4 * 6 + st %r9, %r31, 4 * 7 + st %r10, %r31, 4 * 8 + st %r12, %r31, 4 * 9 + st %r13, %r31, 4 * 10 + + /* + * Invoke resolver entry point. + */ + ld %r2, %r31, REG_SIZE + OBJECT_OFFSET + bsr.n _dl_bind + ld %r3, %r31, REG_SIZE + R11_OFFSET | reloff + + /* + * Preserve return address. + */ + or %r11, %r2, %r0 + + /* + * Restore caller-saved registers. + */ + ld %r13, %r31, 4 * 10 + ld %r12, %r31, 4 * 9 + ld %r10, %r31, 4 * 8 + ld %r9, %r31, 4 * 7 + ld %r8, %r31, 4 * 6 + ld %r7, %r31, 4 * 5 + ld %r6, %r31, 4 * 4 + ld %r5, %r31, 4 * 3 + ld %r4, %r31, 4 * 2 + ld %r3, %r31, 4 * 1 + ld %r2, %r31, 4 * 0 + ld %r1, %r31, REG_SIZE + R1_OFFSET + + jsr.n %r11 + addu %r31, %r31, REG_SIZE + PLT_FRAME_SIZE + +/* ld.so SYSCALLS */ + +#define DL_SYSCALL(n) DL_SYSCALL2(n,n) +#define DL_SYSCALL2(n,c) \ + __ENTRY(_dl_,n); \ + __DO_SYSCALL(c); \ + br _dl_cerror + +#define DL_SYSCALL2_NOERR(n,c) \ + __ENTRY(_dl_,n); \ + __DO_SYSCALL(c) + +DL_SYSCALL(close) + jmp %r1 + +ENTRY(_dl_exit) + __DO_SYSCALL(exit) +1: br 1b + +DL_SYSCALL(issetugid) + jmp %r1 + +DL_SYSCALL2(_syscall,__syscall) + jmp %r1 + +DL_SYSCALL(munmap) + jmp %r1 + +DL_SYSCALL(mprotect) + jmp %r1 + +DL_SYSCALL(open) + jmp %r1 + +DL_SYSCALL(read) + jmp %r1 + +_dl_cerror: + jmp.n %r1 + subu %r2, %r0, 1 + +DL_SYSCALL(write) + jmp %r1 + +DL_SYSCALL(fstat) + jmp %r1 + +DL_SYSCALL(fcntl) + jmp %r1 + +DL_SYSCALL(gettimeofday) + jmp %r1 + +DL_SYSCALL2(sysctl,__sysctl) + jmp %r1 + +DL_SYSCALL(getdirentries) + jmp %r1 + +ENTRY(_dl_sigprocmask) + bcnd ne0, %r3, 1f + or %r2, %r0, 1 /* SIG_BLOCK */ + br 2f +1: + ld %r3, %r3, 0 +2: + or %r13, %r0, SYS_sigprocmask + tb0 0, %r0, 128 + br _dl_cerror + bcnd eq0, %r4, 3f + st %r2, %r4, 0 +3: + jmp.n %r1 + or %r2, %r0, 0 +END(sigprocmask) diff --git a/libexec/ld.so/m88k/memcpy.c b/libexec/ld.so/m88k/memcpy.c new file mode 100644 index 00000000000..ca2c21974a2 --- /dev/null +++ b/libexec/ld.so/m88k/memcpy.c @@ -0,0 +1,58 @@ +/* $OpenBSD: memcpy.c,v 1.1 2013/01/20 23:01:44 miod Exp $ */ +/* $NetBSD: bcopy.c,v 1.5 1995/04/22 13:46:50 cgd Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * 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. + * + * @(#)bcopy.c 8.1 (Berkeley) 6/11/93 + */ + +#include <sys/types.h> + +/* + * This is designed to be small, not fast. + */ +void * +memcpy(s1, s2, n) + void *s1; + const void *s2; + size_t n; +{ + register const char *f = s2; + register char *t = s1; + + if (f < t) { + f += n; + t += n; + while (n-- > 0) + *--t = *--f; + } else + while (n-- > 0) + *t++ = *f++; + return s1; +} diff --git a/libexec/ld.so/m88k/rtld_machine.c b/libexec/ld.so/m88k/rtld_machine.c new file mode 100644 index 00000000000..34d82188006 --- /dev/null +++ b/libexec/ld.so/m88k/rtld_machine.c @@ -0,0 +1,387 @@ +/* $OpenBSD: rtld_machine.c,v 1.1 2013/01/20 23:01:44 miod Exp $ */ + +/* + * Copyright (c) 2013 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* + * 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. + * + * 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" + +Elf_Addr _dl_bind(elf_object_t *object, int reloff); +void _dl_md_reloc_gotp_ent(Elf_Addr, Elf_Addr, Elf_Addr); + +int +_dl_md_reloc(elf_object_t *object, int rel, int relasz) +{ + int i; + int numrela; + int fails = 0; + struct load_list *llist; + Elf32_Addr loff; + Elf32_Rela *relas; + + loff = object->obj_base; + numrela = object->Dyn.info[relasz] / sizeof(Elf32_Rela); + relas = (Elf32_Rela *)(object->Dyn.info[rel]); + +#ifdef DL_PRINTF_DEBUG + _dl_printf("object relocation size %x, numrela %x\n", + object->Dyn.info[relasz], numrela); +#endif + + if (relas == NULL) + return(0); + + /* + * Change protection of all write protected segments in the object + * so we can do relocations such as PC32. After relocation, + * restore protection. + */ + 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 < numrela; i++, relas++) { + Elf32_Addr *r_addr = (Elf32_Addr *)(relas->r_offset + loff); + Elf32_Addr ooff, addend, newval; + const Elf32_Sym *sym, *this; + const char *symn; + int type; + + type = ELF32_R_TYPE(relas->r_info); + + if (type == RELOC_GOTP_ENT && rel != DT_JMPREL) + continue; + + if (type == RELOC_NONE) + continue; + + sym = object->dyn.symtab; + sym += ELF32_R_SYM(relas->r_info); + symn = object->dyn.strtab + sym->st_name; + + if (type == RELOC_COPY) { + /* + * 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. + */ + const Elf32_Sym *cpysrc = NULL; + Elf32_Addr src_loff; + int size; + + src_loff = 0; + src_loff = _dl_find_symbol(symn, &cpysrc, + SYM_SEARCH_OTHER | SYM_WARNNOTFOUND | SYM_NOTPLT, + sym, object, NULL); + if (cpysrc != NULL) { + size = sym->st_size; + if (sym->st_size != cpysrc->st_size) { + /* _dl_find_symbol() has warned + about this already */ + size = sym->st_size < cpysrc->st_size ? + sym->st_size : cpysrc->st_size; + } + _dl_bcopy((void *)(src_loff + cpysrc->st_value), + r_addr, size); + } else + fails++; + + continue; + } + + ooff = 0; + this = NULL; + 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_bysym(object, + ELF32_R_SYM(relas->r_info), &this, + SYM_SEARCH_ALL | SYM_WARNNOTFOUND | + ((type == RELOC_GOTP_ENT) ? SYM_PLT : SYM_NOTPLT), + sym, NULL); + + if (this == NULL) { + if (ELF_ST_BIND(sym->st_info) != STB_WEAK) + fails++; + continue; + } + } + + if (type == RELOC_GOTP_ENT) { + _dl_md_reloc_gotp_ent((Elf_Addr)r_addr, + relas->r_addend + loff, + ooff + this->st_value); + continue; + } + + 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)) + addend = relas->r_addend; + else + addend = this->st_value + relas->r_addend; + + switch (type) { + case RELOC_32: + newval = ooff + addend; + *r_addr = newval; + break; + case RELOC_BBASED_32: + newval = loff + addend; + *r_addr = newval; + break; + default: + _dl_printf("%s:" + " %s: unsupported relocation '%s' %d at %x\n", + _dl_progname, object->load_name, symn, type, + r_addr); + _dl_exit(1); + } + } + + /* 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); +} + +/* + * GOTP_ENT relocations are special in that they define both a .got and a + * .plt relocation. + */ +void +_dl_md_reloc_gotp_ent(Elf_Addr got_addr, Elf_Addr plt_addr, Elf_Addr val) +{ + uint16_t *plt_entry = (uint16_t *)plt_addr; + + /* .got update */ + *(Elf_Addr *)got_addr = val; + /* .plt update */ + plt_entry[1] = got_addr >> 16; + plt_entry[3] = got_addr & 0xffff; +} + +/* + * Relocate the Global Offset Table (GOT). + * This is done by calling _dl_md_reloc on DT_JMPREL for DL_BIND_NOW, + * otherwise the lazy binding plt operation is preserved. + */ +int +_dl_md_reloc_got(elf_object_t *object, int lazy) +{ + extern void _dl_bind_start(void); /* XXX */ + int fails = 0; + Elf_Addr *pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT]; + Elf_Addr ooff; + Elf_Addr plt_addr; + const Elf_Sym *this; + +#if 1 + /* XXX force non-lazy binding for now, until it gets fixed... */ + lazy = 0; +#endif + + if (pltgot == NULL) + return (0); + + pltgot[1] = (Elf_Addr)object; + pltgot[2] = (Elf_Addr)_dl_bind_start; + + if (object->Dyn.info[DT_PLTREL] != DT_RELA) + return (0); + + object->got_addr = 0; + 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; + + if (object->got_addr == 0) + object->got_start = 0; + 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); + } + + plt_addr = 0; + object->plt_size = 0; + this = NULL; + ooff = _dl_find_symbol("__plt_start", &this, + SYM_SEARCH_OBJ | SYM_NOWARNNOTFOUND | SYM_PLT, NULL, object, NULL); + if (this != NULL) + plt_addr = ooff + this->st_value; + + this = NULL; + ooff = _dl_find_symbol("__plt_end", &this, + SYM_SEARCH_OBJ | SYM_NOWARNNOTFOUND | SYM_PLT, NULL, object, NULL); + if (this != NULL) + object->plt_size = ooff + this->st_value - plt_addr; + + if (plt_addr == 0) + object->plt_start = 0; + else { + object->plt_start = ELF_TRUNC(plt_addr, _dl_pagesz); + object->plt_size += plt_addr - object->plt_start; + object->plt_size = ELF_ROUND(object->plt_size, _dl_pagesz); + + /* + * GOT relocation will require PLT to be writeable. + */ + if (!lazy || object->obj_base != 0) + _dl_mprotect((void*)object->plt_start, object->plt_size, + PROT_READ | PROT_WRITE); + } + + if (!lazy) { + fails = _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); + } else { + if (object->obj_base != 0) { + int cnt; + Elf_Addr *addr; + Elf_RelA *rela; + + cnt = object->Dyn.info[DT_PLTRELSZ] / sizeof(Elf_RelA); + rela = (Elf_RelA *)object->Dyn.info[DT_JMPREL]; + + for (; cnt != 0; cnt--, rela++) { + addr = (Elf_Addr *)(object->obj_base + + rela->r_offset); + _dl_md_reloc_gotp_ent((Elf_Addr)addr, + object->obj_base + rela->r_addend, + *addr + object->obj_base); + } + /* + * XXX We ought to invalidate I$ on the whole + * XXX plt here. + */ + } + } + + if (object->got_size != 0) { + _dl_mprotect((void*)object->got_start, object->got_size, + PROT_READ); + } + if (object->plt_size != 0) { + if (!lazy || object->obj_base != 0) + _dl_mprotect((void*)object->plt_start, object->plt_size, + PROT_READ | PROT_EXEC); + } + + return (fails); +} + +Elf_Addr +_dl_bind(elf_object_t *object, int reloff) +{ + Elf_RelA *rel; + Elf_Addr *r_addr, ooff, value; + const Elf_Sym *sym, *this; + const char *symn; + sigset_t savedmask; + + rel = (Elf_RelA *)(object->Dyn.info[DT_JMPREL] + reloff); + + sym = object->dyn.symtab; + sym += ELF_R_SYM(rel->r_info); + symn = object->dyn.strtab + sym->st_name; + + r_addr = (Elf_Addr *)(object->obj_base + rel->r_offset); + 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 */ + } + + value = ooff + this->st_value; + + /* if GOT is protected, allow the write */ + if (object->got_size != 0) { + _dl_thread_bind_lock(0, &savedmask); + _dl_mprotect((void*)object->got_start, object->got_size, + PROT_READ | PROT_WRITE); + } + + *r_addr = value; + + /* put the GOT back to RO */ + if (object->got_size != 0) { + _dl_mprotect((void*)object->got_start, object->got_size, + PROT_READ); + _dl_thread_bind_lock(1, &savedmask); + } + + return (value); +} diff --git a/libexec/ld.so/m88k/syscall.h b/libexec/ld.so/m88k/syscall.h new file mode 100644 index 00000000000..cd82f08f478 --- /dev/null +++ b/libexec/ld.so/m88k/syscall.h @@ -0,0 +1,71 @@ +/* $OpenBSD: syscall.h,v 1.1 2013/01/20 23:01:44 miod 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 512L +#endif +#define _dl_mmap_error(__res) \ + ((long)__res < 0 && (long)__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_fstat(int, struct stat *); +int _dl_fcntl(int, int, ...); +int _dl_getdirentries(int, char*, int, off_t *); +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); +} + +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)); +} + +#endif /*__DL_SYSCALL_H__*/ |