summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2013-01-23 19:15:59 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2013-01-23 19:15:59 +0000
commit429523d1bd5e8c0ebda83774cbf47de073e280df (patch)
treecc93ec9a38af2abae3b099be6c76ee7271a13c26
parentc81801b09463606eb08e2aa96ad551e3324b4563 (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.c5
-rw-r--r--libexec/ld.so/m68k/Makefile.inc5
-rw-r--r--libexec/ld.so/m68k/archdep.h72
-rw-r--r--libexec/ld.so/m68k/ldasm.S209
-rw-r--r--libexec/ld.so/m68k/rtld_machine.c354
-rw-r--r--libexec/ld.so/m68k/syscall.h71
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__*/