summaryrefslogtreecommitdiff
path: root/libexec/ld.so
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2004-02-07 06:00:50 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2004-02-07 06:00:50 +0000
commit05e780b2273263dc4bdf41c5f3418152f9170239 (patch)
treeedf857fcf50e521cd6dd4ec6bb03645ae7060238 /libexec/ld.so
parentb967f1918bb48b58bbd7ed8be0142d51578da4a7 (diff)
Dynamic linker support for arm. non-lazy binding works.
Diffstat (limited to 'libexec/ld.so')
-rw-r--r--libexec/ld.so/arm/Makefile.inc8
-rw-r--r--libexec/ld.so/arm/archdep.h85
-rw-r--r--libexec/ld.so/arm/ldasm.S186
-rw-r--r--libexec/ld.so/arm/rtld_machine.c435
-rw-r--r--libexec/ld.so/arm/syscall.h63
-rw-r--r--libexec/ld.so/loader.c6
6 files changed, 780 insertions, 3 deletions
diff --git a/libexec/ld.so/arm/Makefile.inc b/libexec/ld.so/arm/Makefile.inc
new file mode 100644
index 00000000000..55e406b0814
--- /dev/null
+++ b/libexec/ld.so/arm/Makefile.inc
@@ -0,0 +1,8 @@
+# $OpenBSD: Makefile.inc,v 1.1 2004/02/07 06:00:49 drahn Exp $
+
+CFLAGS += -fpic -msoft-float
+AFLAGS += -D_STANDALONE
+SRCS+= divsi3.S
+ELF_LDFLAGS+=-z nocombreloc
+LIBCSRCDIR=${.CURDIR}/../../lib/libc
+.PATH: ${LIBCSRCDIR}/arch/arm/gen/
diff --git a/libexec/ld.so/arm/archdep.h b/libexec/ld.so/arm/archdep.h
new file mode 100644
index 00000000000..4babebe6b33
--- /dev/null
+++ b/libexec/ld.so/arm/archdep.h
@@ -0,0 +1,85 @@
+/* $OpenBSD: archdep.h,v 1.1 2004/02/07 06:00:49 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 _ARM_ARCHDEP_H_
+#define _ARM_ARCHDEP_H_
+
+#define DL_MALLOC_ALIGN 4 /* Arch constraint or otherwise */
+
+#define MACHID EM_ARM /* 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
+
+/*
+ * 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 *)_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_ARM_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)
+{
+ _dl_exit(20);
+}
+
+#define RELOC_GOT(obj, offs)
+
+#define GOT_PERMS (PROT_READ|PROT_EXEC)
+
+#endif /* _ARM_ARCHDEP_H_ */
diff --git a/libexec/ld.so/arm/ldasm.S b/libexec/ld.so/arm/ldasm.S
new file mode 100644
index 00000000000..07db25d8e41
--- /dev/null
+++ b/libexec/ld.so/arm/ldasm.S
@@ -0,0 +1,186 @@
+/* $OpenBSD: ldasm.S,v 1.1 2004/02/07 06:00:49 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 <arm/swi.h>
+
+ENTRY(_dl_start)
+ mov fp, sp
+ mov r5, sp
+ mov lr, r6 @ save lr
+ sub sp, sp, #4+4+DL_DATA_SIZE
+ add r7, sp, #4 @ dl_data
+
+ mov r0, fp @ original stack
+ mov r1, r7 @ dl_data
+
+
+ bl _dl_boot_bind
+
+ add r0, r5, #4 @ argv
+ ldr r1, [r5, #0x0] @ envp
+ add r1, r1, #2
+ add r1, fp, r1, lsl #2
+ ldr r2, [r7, #7*4] @ loff from dl_data
+ mov r3, r7 @ dl_data
+ bl _dl_boot
+
+ mov sp, fp
+ mov fp, #0
+ mov lr, r6
+
+ mov pc, r0
+
+
+ENTRY(_dl_bind_start)
+ /* STUB */
+
+
+/* ld.so SYSCALLS */
+
+ .section ".text"
+ .align 4
+ .global _dl_close
+ .type _dl_close%function
+_dl_close:
+ swi SWI_OS_NETBSD|SYS_close
+ bcs .L_cerr
+ mov pc, lr
+
+ .global _dl_exit
+ .type _dl_exit%function
+_dl_exit:
+ swi SWI_OS_NETBSD|SYS_exit
+ 1:
+ b 1b
+
+ .global _dl_issetugid
+ .type _dl_issetugid%function
+_dl_issetugid:
+ swi SWI_OS_NETBSD|SYS_issetugid
+ bcs .L_cerr
+ mov pc, lr
+
+
+ .global _dl__syscall
+ .type _dl__syscall%function
+_dl__syscall:
+ swi SWI_OS_NETBSD|SYS___syscall
+ bcs .L_cerr
+ mov pc, lr
+
+ .global _dl_munmap
+ .type _dl_munmap%function
+_dl_munmap:
+ swi SWI_OS_NETBSD|SYS_munmap
+ bcs .L_cerr
+ mov pc, lr
+
+ .global _dl_mprotect
+ .type _dl_mprotect%function
+_dl_mprotect:
+ swi SWI_OS_NETBSD|SYS_mprotect
+ bcs .L_cerr
+ mov pc, lr
+
+ .global _dl_open
+ .type _dl_open%function
+_dl_open:
+ swi SWI_OS_NETBSD|SYS_open
+ bcs .L_cerr
+ mov pc, lr
+
+ .global _dl_read
+ .type _dl_read%function
+_dl_read:
+ swi SWI_OS_NETBSD|SYS_read
+ bcs .L_cerr
+ mov pc, lr
+
+ .global _dl_write
+ .type _dl_write%function
+_dl_write:
+ swi SWI_OS_NETBSD|SYS_write
+ bcs .L_cerr
+ mov pc, lr
+
+ .global _dl_stat
+ .type _dl_stat%function
+_dl_stat:
+ swi SWI_OS_NETBSD|SYS_stat
+ bcs .L_cerr
+ mov pc, lr
+
+ .global _dl_fstat
+ .type _dl_fstat%function
+_dl_fstat:
+ swi SWI_OS_NETBSD|SYS_fstat
+ bcs .L_cerr
+ mov pc, lr
+
+ .global _dl_fcntl
+ .type _dl_fcntl%function
+_dl_fcntl:
+ swi SWI_OS_NETBSD|SYS_fcntl
+ bcs .L_cerr
+ mov pc, lr
+
+ .global _dl_sysctl
+ .type _dl_sysctl%function
+_dl_sysctl:
+ swi SWI_OS_NETBSD|SYS___sysctl
+ bcs .L_cerr
+ mov pc, lr
+
+ .global _dl_getdirentries
+ .type _dl_getdirentries%function
+_dl_getdirentries:
+ swi SWI_OS_NETBSD|SYS_getdirentries
+ bcs .L_cerr
+ mov pc, lr
+
+ .global _dl_sigprocmask
+ .type _dl_sigprocmask%function
+_dl_sigprocmask:
+ teq r1, #0
+ moveq r0, #1
+ moveq r1, #0
+ ldrne r1, [r1]
+ swi SWI_OS_NETBSD|SYS_sigprocmask
+ bcs .L_cerr
+ teq r2, #0
+ strne r0, [r2]
+ mov r0, #0
+ mov pc, lr
+
+.L_cerr:
+ mov r0, #0
+ sub r0, r0, #1
+ mov pc, lr
diff --git a/libexec/ld.so/arm/rtld_machine.c b/libexec/ld.so/arm/rtld_machine.c
new file mode 100644
index 00000000000..de652c63a80
--- /dev/null
+++ b/libexec/ld.so/arm/rtld_machine.c
@@ -0,0 +1,435 @@
+/* $OpenBSD: rtld_machine.c,v 1.1 2004/02/07 06:00:49 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 JUMP_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 JUMP_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])
+
+void
+_dl_bcopy(const void *src, void *dest, int size)
+{
+ unsigned const char *psrc = src;
+ unsigned char *pdest = dest;
+ int i;
+
+ for (i = 0; i < size; i++)
+ pdest[i] = psrc[i];
+}
+
+#define R_TYPE(x) R_ARM_ ## x
+
+void _dl_reloc_plt(Elf_Word *where, Elf_Addr value, Elf_Rel *rel);
+
+#define LD_PROTECT_TEXT
+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;
+#ifndef LD_PROTECT_TEXT
+ struct load_list *llist;
+#endif
+
+ loff = object->load_offs;
+ numrel = object->Dyn.info[relsz] / sizeof(Elf_Rel);
+ rels = (Elf_Rel *)(object->Dyn.info[rel]);
+
+ if (rels == NULL)
+ return(0);
+
+#ifndef LD_PROTECT_TEXT
+ /*
+ * unprotect some segments if we need it.
+ */
+ if ((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);
+ }
+ }
+#endif
+
+ 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(JUMP_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),
+ _dl_objects, &this,
+ SYM_SEARCH_ALL|SYM_WARNNOTFOUND|
+ ((type == R_TYPE(JUMP_SLOT)) ?
+ SYM_PLT : SYM_NOTPLT),
+ sym->st_size);
+ if (this == NULL) {
+resolve_failed:
+ _dl_printf("%s: %s: can't resolve "
+ "reference '%s'\n",
+ _dl_progname, object->load_name,
+ symn);
+ fails++;
+ continue;
+ }
+ value += (Elf_Addr)(ooff + this->st_value);
+ }
+ }
+
+ if (type == R_TYPE(JUMP_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;
+ size_t size = dstsym->st_size;
+ Elf_Addr soff;
+
+ soff = _dl_find_symbol(symn, object->next, &srcsym,
+ SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_NOTPLT,
+ size, object);
+ if (srcsym == NULL)
+ goto resolve_failed;
+
+ srcaddr = (void *)(soff + srcsym->st_value);
+ _dl_bcopy(srcaddr, dstaddr, 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;
+ }
+ }
+
+#ifndef LD_PROTECT_TEXT
+ /* reprotect the unprotected segments */
+ if ((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);
+ }
+ }
+ #endif
+
+ 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;
+ Elf_Addr plt_addr;
+ const Elf_Sym *this;
+
+ 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", object, &this,
+ SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object);
+ if (this != NULL)
+ object->got_addr = ooff + this->st_value;
+
+ this = NULL;
+ ooff = _dl_find_symbol("__got_end", object, &this,
+ SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object);
+ if (this != NULL)
+ object->got_size = ooff + this->st_value - object->got_addr;
+
+ plt_addr = 0;
+ object->plt_size = 0;
+ this = NULL;
+ ooff = _dl_find_symbol("__plt_start", object, &this,
+ SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object);
+ if (this != NULL)
+ plt_addr = ooff + this->st_value;
+
+ 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);
+ }
+#if 1
+ object->plt_start = NULL;
+#else
+ if (plt_addr == NULL)
+ object->plt_start = NULL;
+ 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) {
+ _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ);
+ } else {
+ 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 reloff)
+{
+ const Elf_Sym *sym, *this;
+ Elf_Addr *r_addr, ooff, newval;
+ const char *symn;
+ Elf_Rel *rels;
+
+ rels = ((Elf_Rel *)object->Dyn.info[DT_JMPREL]) + (reloff>>2);
+
+ sym = object->dyn.symtab;
+ sym += ELF_R_SYM(rels->r_info);
+ symn = object->dyn.strtab + sym->st_name;
+
+ ooff = _dl_find_symbol(symn, _dl_objects, &this,
+ SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym->st_size, object);
+ if (this == NULL) {
+ _dl_printf("lazy binding failed!\n");
+ *((int *)0) = 0; /* XXX */
+ }
+
+ r_addr = (Elf_Addr *)(object->load_offs + rels->r_offset);
+ newval = ooff + this->st_value;
+
+ if (*r_addr != newval)
+ *r_addr = newval;
+
+ return newval;
+}
+
diff --git a/libexec/ld.so/arm/syscall.h b/libexec/ld.so/arm/syscall.h
new file mode 100644
index 00000000000..882e393522a
--- /dev/null
+++ b/libexec/ld.so/arm/syscall.h
@@ -0,0 +1,63 @@
+/* $OpenBSD: syscall.h,v 1.1 2004/02/07 06:00:49 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);
+
+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/loader.c b/libexec/ld.so/loader.c
index 3a0fba9b32c..f5b70df104d 100644
--- a/libexec/ld.so/loader.c
+++ b/libexec/ld.so/loader.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: loader.c,v 1.70 2003/10/04 16:13:33 deraadt Exp $ */
+/* $OpenBSD: loader.c,v 1.71 2004/02/07 06:00:48 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -205,7 +205,7 @@ _dl_boot(const char **argv, char **envp, const long loff, long *dl_data)
{
extern char *__got_start;
extern char *__got_end;
-#ifndef __i386__
+#if !defined(__i386__) && !defined(__arm__)
extern char *__plt_start;
extern char *__plt_end;
#endif
@@ -215,7 +215,7 @@ _dl_boot(const char **argv, char **envp, const long loff, long *dl_data)
ELF_TRUNC((long)&__got_start, _dl_pagesz),
GOT_PERMS);
-#ifndef __i386__
+#if !defined(__i386__) && !defined(__arm__)
/* only for DATA_PLT or BSS_PLT */
_dl_mprotect((void *)ELF_TRUNC((long)&__plt_start, _dl_pagesz),
ELF_ROUND((long)&__plt_end,_dl_pagesz) -