diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2013-01-23 19:15:59 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2013-01-23 19:15:59 +0000 |
commit | 429523d1bd5e8c0ebda83774cbf47de073e280df (patch) | |
tree | cc93ec9a38af2abae3b099be6c76ee7271a13c26 | |
parent | c81801b09463606eb08e2aa96ad551e3324b4563 (diff) |
bits for an m68k ELF ld.so, to be used soon. Lazy resolver wrapper borrowed from
NetBSD.
-rw-r--r-- | libexec/ld.so/ldconfig/prebind.c | 5 | ||||
-rw-r--r-- | libexec/ld.so/m68k/Makefile.inc | 5 | ||||
-rw-r--r-- | libexec/ld.so/m68k/archdep.h | 72 | ||||
-rw-r--r-- | libexec/ld.so/m68k/ldasm.S | 209 | ||||
-rw-r--r-- | libexec/ld.so/m68k/rtld_machine.c | 354 | ||||
-rw-r--r-- | libexec/ld.so/m68k/syscall.h | 71 |
6 files changed, 715 insertions, 1 deletions
diff --git a/libexec/ld.so/ldconfig/prebind.c b/libexec/ld.so/ldconfig/prebind.c index e638cd77468..e8890184343 100644 --- a/libexec/ld.so/ldconfig/prebind.c +++ b/libexec/ld.so/ldconfig/prebind.c @@ -1,4 +1,4 @@ -/* $OpenBSD: prebind.c,v 1.17 2013/01/21 17:19:11 miod Exp $ */ +/* $OpenBSD: prebind.c,v 1.18 2013/01/23 19:15:58 miod Exp $ */ /* * Copyright (c) 2006 Dale Rahn <drahn@dalerahn.com> * @@ -60,6 +60,9 @@ char *shstrtab; #ifdef __i386__ #define RELOC_JMP_SLOT RELOC_JUMP_SLOT #endif +#ifdef __m68k__ +#define RELOC_JMP_SLOT R_68K_JMP_SLOT +#endif #ifdef __sh__ #define RELOC_JMP_SLOT R_SH_JMP_SLOT #endif diff --git a/libexec/ld.so/m68k/Makefile.inc b/libexec/ld.so/m68k/Makefile.inc new file mode 100644 index 00000000000..b9a139ed8c8 --- /dev/null +++ b/libexec/ld.so/m68k/Makefile.inc @@ -0,0 +1,5 @@ +# $OpenBSD: Makefile.inc,v 1.1 2013/01/23 19:15:58 miod Exp $ + +CFLAGS += -fpic +CPPFLAGS += -I${.CURDIR}/../../lib/libc/arch/m68k +LIBCSRCDIR=${.CURDIR}/../../lib/libc diff --git a/libexec/ld.so/m68k/archdep.h b/libexec/ld.so/m68k/archdep.h new file mode 100644 index 00000000000..5d8ccc441dd --- /dev/null +++ b/libexec/ld.so/m68k/archdep.h @@ -0,0 +1,72 @@ +/* $OpenBSD: archdep.h,v 1.1 2013/01/23 19:15:58 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 _M68K_ARCHDEP_H_ +#define _M68K_ARCHDEP_H_ + +#define DL_MALLOC_ALIGN 4 /* Arch constraint or otherwise */ + +#define MACHID EM_68K /* 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) +{ + /* m68k 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) == R_68K_RELATIVE) { + *p = v + r->r_addend; + } else { + /* _dl_printf("Unknown bootstrap relocation.\n"); */ + _dl_exit(6); + } +} + +#define RELOC_GOT(obj, offs) do { } while (0) + +#define GOT_PERMS PROT_READ + +#endif /* _M68K_ARCHDEP_H_ */ diff --git a/libexec/ld.so/m68k/ldasm.S b/libexec/ld.so/m68k/ldasm.S new file mode 100644 index 00000000000..793329d6214 --- /dev/null +++ b/libexec/ld.so/m68k/ldasm.S @@ -0,0 +1,209 @@ +/* $OpenBSD: ldasm.S,v 1.1 2013/01/23 19:15:58 miod Exp $ */ + +/* + * 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. + * + */ +/*- + * Copyright (c) 1999, 2002, 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Klaus Klein and by Charles M. Hannum. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include <machine/asm.h> +#include <sys/syscall.h> +#include <SYS.h> + +/* + * ld.so entry point. + * On entry: %sp 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) + /* + * Get some room for the contiguous AUX pointers array. + */ + subl #DL_DATA_SIZE, %sp + + /* + * Invoke _dl_boot_bind + */ + pea 0(%sp) | array base + pea (4 + DL_DATA_SIZE)(%sp) | kernel args + jbsr _dl_boot_bind@PLTPC + addql #8, %sp + + movl (4 * 7)(%sp), %d1 | ldoff + leal DL_DATA_SIZE(%sp), %a0 + movl (%a0)+, %d0 | argc, a0 points to argv + lea 4(%a0,%d0.l*4), %a1 | envp + + pea 0(%sp) | array base + movl %d1, -(%sp) | ldoff + movl %a1, -(%sp) | envp + movl %a0, -(%sp) | argv + jbsr _dl_boot@PLTPC + addl #16, %sp + + addl #DL_DATA_SIZE, %sp | restore sp + moveal %d0, %a0 + jmp (%a0) + + rts + +ENTRY(_dl_bind_start) + moveml %d0-%d1/%a0-%a1,-(%sp) /* preserve caller-saved registers */ + movel 20(%sp),-(%sp) /* push reloff */ + movel (16+4)(%sp),-(%sp) /* push obj */ + jbsr _dl_bind@PLTPC /* %d0 = _dl_bind(obj, reloff) */ + addql #8,%sp /* pop args */ + movel %d0,20(%sp) /* write fake `return' address over + reloff */ + moveml (%sp)+,%d0-%d1/%a0-%a1 /* restore caller-saved registers */ + addql #4,%sp /* skip obj */ + rts /* `return' right into function */ + +/* ld.so SYSCALLS */ + +#ifdef __STDC__ +#define __CONCAT(x,y) x ## y +#else +#define __CONCAT(x,y) x/**/y +#endif + +#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): ;\ + __DO_SYSCALL(c) ;\ + jcs .L_cerr + +#define DL_SYSCALL2_NOERR(n,c) \ + .global __CONCAT(_dl_,n) ;\ + .type __CONCAT(_dl_,n)%function ;\ +__CONCAT(_dl_,n): ;\ + __DO_SYSCALL(c) + + .section ".text" + .align 2 +DL_SYSCALL(close) + rts + + .global _dl_exit + .type _dl_exit%function +_dl_exit: + __DO_SYSCALL(exit) +1: + jra 1b + +DL_SYSCALL(issetugid) + rts + +DL_SYSCALL2(_syscall,__syscall) + movl %d0, %a0 /* ??? */ + rts + +DL_SYSCALL(munmap) + rts + +DL_SYSCALL(mprotect) + rts + +DL_SYSCALL(open) + rts + +DL_SYSCALL(read) + rts + +DL_SYSCALL(write) + rts + +DL_SYSCALL(fstat) + rts + +DL_SYSCALL(fcntl) + rts + +DL_SYSCALL(gettimeofday) + rts + +DL_SYSCALL2(sysctl,__sysctl) + rts + +DL_SYSCALL(getdirentries) + rts + + .global _dl_sigprocmask + .type _dl_sigprocmask%function +_dl_sigprocmask: + tstl %sp@(8) /* check new sigset pointer */ + jne gotptr /* if not null, indirect */ +/* movl #0,%sp@(8) */ /* null mask pointer: block empty set */ + movl #1,%sp@(4) /* SIG_BLOCK */ + jra doit +gotptr: + movl %sp@(8),%a0 + movl %a0@,%sp@(8) /* indirect to new mask arg */ +doit: + movl #SYS_sigprocmask,%d0 + trap #0 + jcs .L_cerr + tstl %sp@(12) /* test if old mask requested */ + jeq out + movl %sp@(12),%a0 + movl %d0,%a0@ /* store old mask */ +out: + clrl %d0 + rts + +.L_cerr: + movl #-1, %d0 + rts + diff --git a/libexec/ld.so/m68k/rtld_machine.c b/libexec/ld.so/m68k/rtld_machine.c new file mode 100644 index 00000000000..f8c3abf2594 --- /dev/null +++ b/libexec/ld.so/m68k/rtld_machine.c @@ -0,0 +1,354 @@ +/* $OpenBSD: rtld_machine.c,v 1.1 2013/01/23 19:15:58 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); + +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 == R_68K_JMP_SLOT && rel != DT_JMPREL) + continue; + + if (type == R_68K_NONE) + continue; + + sym = object->dyn.symtab; + sym += ELF32_R_SYM(relas->r_info); + symn = object->dyn.strtab + sym->st_name; + + if (type == R_68K_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 == R_68K_JMP_SLOT) ? SYM_PLT:SYM_NOTPLT), + sym, NULL); + + if (this == NULL) { + if (ELF_ST_BIND(sym->st_info) != STB_WEAK) + fails++; + 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 R_68K_PC32: + newval = ooff + addend; + newval -= (Elf_Addr)r_addr; + *r_addr = newval; + break; + case R_68K_32: + case R_68K_GLOB_DAT: + case R_68K_JMP_SLOT: + newval = ooff + addend; + *r_addr = newval; + break; + case R_68K_RELATIVE: + 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, + ELF32_R_TYPE(relas->r_info), 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); +} + +/* + * 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 initialization is performed. + */ +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; + const Elf_Sym *this; + + 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 0 + 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; +#endif + + 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); + } +#if 0 + 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); + } +#endif + + if (!lazy) { + fails = _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); + } else { + if (object->obj_base != 0) { + int i, size; + Elf_Addr *addr; + Elf_RelA *rela; + + size = object->Dyn.info[DT_PLTRELSZ] / sizeof(Elf_RelA); + rela = (Elf_RelA *)object->Dyn.info[DT_JMPREL]; + + for (i = 0; i < size; i++) { + addr = (Elf_Addr *)(object->obj_base + + rela[i].r_offset); + *addr += object->obj_base; + } + } + } + if (object->got_size != 0) { + _dl_mprotect((void*)object->got_start, object->got_size, + PROT_READ); + } + /* PLT is already RO, no point in mprotecting it, just do GOT */ +#if 0 + if (object->plt_size != 0) + _dl_mprotect((void*)object->plt_start, object->plt_size, + PROT_READ|PROT_EXEC); +#endif + + 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 + rel->r_addend; + + /* 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/m68k/syscall.h b/libexec/ld.so/m68k/syscall.h new file mode 100644 index 00000000000..656445e3937 --- /dev/null +++ b/libexec/ld.so/m68k/syscall.h @@ -0,0 +1,71 @@ +/* $OpenBSD: syscall.h,v 1.1 2013/01/23 19:15:58 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__*/ |