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