summaryrefslogtreecommitdiff
path: root/libexec/ld.so/i386
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2002-08-23 23:02:49 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2002-08-23 23:02:49 +0000
commit95ef4c7576484f038c571d3a52fa588c916506b2 (patch)
tree0306a05a272f621022bd3ccc52e79cdc4043c326 /libexec/ld.so/i386
parentbfce6caf8080fa2d4f5024cab4059d709567fae4 (diff)
Support for i386 ELF. Not an indication that the change is going to be made,
just so that these files are maintained in the tree.
Diffstat (limited to 'libexec/ld.so/i386')
-rw-r--r--libexec/ld.so/i386/Makefile.inc4
-rw-r--r--libexec/ld.so/i386/archdep.h88
-rw-r--r--libexec/ld.so/i386/ldasm.S267
-rw-r--r--libexec/ld.so/i386/rtld_machine.c350
-rw-r--r--libexec/ld.so/i386/syscall.h67
5 files changed, 776 insertions, 0 deletions
diff --git a/libexec/ld.so/i386/Makefile.inc b/libexec/ld.so/i386/Makefile.inc
new file mode 100644
index 00000000000..28573b34aec
--- /dev/null
+++ b/libexec/ld.so/i386/Makefile.inc
@@ -0,0 +1,4 @@
+# $OpenBSD: Makefile.inc,v 1.1 2002/08/23 23:02:48 drahn Exp $
+
+CFLAGS += -fPIC
+AFLAGS += -fpic
diff --git a/libexec/ld.so/i386/archdep.h b/libexec/ld.so/i386/archdep.h
new file mode 100644
index 00000000000..006d876c739
--- /dev/null
+++ b/libexec/ld.so/i386/archdep.h
@@ -0,0 +1,88 @@
+/* $OpenBSD: archdep.h,v 1.1 2002/08/23 23:02:48 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed under OpenBSD by
+ * Per Fogelstrom, Opsycon AB, Sweden.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 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 _I386_ARCHDEP_H_
+#define _I386_ARCHDEP_H_
+
+#define DL_MALLOC_ALIGN 8 /* Arch constraint or otherwise */
+
+#define MACHID EM_386 /* ELF e_machine ID value checked */
+
+#define RELTYPE Elf32_Rela
+#define RELSIZE sizeof(Elf32_Rela)
+
+#include <sys/mman.h>
+#include <elf_abi.h>
+#include <machine/reloc.h>
+#include "syscall.h"
+#include "util.h"
+
+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(Elf32_Rel *r, const Elf32_Sym *s, Elf32_Addr *p, unsigned long v)
+{
+
+ if (ELF32_R_TYPE(r->r_info) == RELOC_RELATIVE) {
+ *p += v;
+ } else if (ELF32_R_TYPE(r->r_info) == RELOC_GLOB_DAT) {
+ *p += v + s->st_value;
+ } else {
+ _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)
+{
+ /* does i386 use RELA type relocations? - XXX */
+
+ if (ELF32_R_TYPE(r->r_info) == RELOC_RELATIVE) {
+ *p = v + r->r_addend;
+ } else if (ELF32_R_TYPE(r->r_info) == RELOC_GLOB_DAT) {
+ *p = v + s->st_value + r->r_addend;
+ } else {
+ _dl_printf("unknown bootstrap relocation\n");
+ _dl_exit(6);
+ }
+}
+
+#endif /* _I386_ARCHDEP_H_ */
diff --git a/libexec/ld.so/i386/ldasm.S b/libexec/ld.so/i386/ldasm.S
new file mode 100644
index 00000000000..b86048d3768
--- /dev/null
+++ b/libexec/ld.so/i386/ldasm.S
@@ -0,0 +1,267 @@
+/* $OpenBSD: ldasm.S,v 1.1 2002/08/23 23:02:48 drahn Exp $ */
+
+/*
+ * Copyright (c) 2002 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed under OpenBSD by
+ * Dale Rahn.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WsdfARRANTIES 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)
+#include <sys/syscall.h>
+#include <machine/asm.h>
+
+ .text
+ .align 4
+ .globl _dl_start
+ .type _dl_start,@function
+_dl_start:
+ movl %esp,%eax # save stack pointer for _rtld
+ pushl %ebx # save ps_strings
+ subl $DL_DATA_SIZE,%esp # allocate dl_data
+ movl %esp,%ebx
+ movl %ebx,%edi # save dl_data arg for dl_boot
+ pushl %ebx # push dl_data for dl_boot_bind
+
+ pushl $0 # dynp
+ pushl $0 # push dummy for loff
+
+ mov %eax, %esi # save stack for dl_boot
+
+ pushl %eax # load saved SP for dl_boot_bind
+
+ call _dl_boot_bind@PLT # _dl_boot_bind(sp,loff,dl_data)
+
+ pushl %edi # push saved dl_data
+ movl %edi,%ebp
+ movl (7*4)(%ebp),%eax
+ pushl %eax # push loff from dl_data
+
+ movl %esi,%ebp
+ movl $4,%eax
+ imull 0(%ebp),%eax
+ addl $8,%eax
+ addl %ebp,%eax
+ push %eax # push envp
+
+ leal 4(%ebp),%eax
+ push %eax # push argv
+
+ call _dl_boot@PLT # _dl_boot(argv,envp,loff,dl_data)
+
+ addl $4*6,%esp # pop args
+
+ addl $DL_DATA_SIZE,%esp # return dl_data
+
+ popl %ebx # %ebx = ps_strings - XXXDSR
+ popl %edx # %edx = cleanup - XXXDSR
+ popl %ecx # %ecx = obj_main - XXXDSR
+ jmp *%eax
+
+ .section ".text"
+ .align 4
+ .global _dl_close
+ .type _dl_close,@function
+_dl_close:
+ mov $SYS_close, %eax
+ int $0x80
+ jb 1f
+ ret
+
+ .section ".text"
+ .align 4
+ .global _dl_exit
+ .type _dl_exit,@function
+_dl_exit:
+ mov $SYS_exit, %eax
+ int $0x80
+ ret
+
+
+ .section ".text"
+ .align 4
+ .global _dl_issetugid
+ .type _dl_issetugid,@function
+_dl_issetugid:
+ mov $SYS_issetugid, %eax
+ int $0x80
+ jb 1f /* error: result = -errno */
+ ret
+
+
+ .section ".text"
+ .align 4
+ .global _dl__syscall
+ .type _dl__syscall,@function
+_dl__syscall:
+ mov $SYS___syscall, %eax
+ int $0x80
+ jb 1f /* error: result = -errno */
+ ret
+
+
+ .section ".text"
+ .align 4
+ .global _dl_munmap
+ .type _dl_munmap,@function
+_dl_munmap:
+ mov $SYS_munmap, %eax
+ int $0x80
+ jb 1f /* error: result = -errno */
+ ret
+
+
+ .section ".text"
+ .align 4
+ .global _dl_mprotect
+ .type _dl_mprotect,@function
+_dl_mprotect:
+ mov $SYS_mprotect, %eax
+ int $0x80
+ jb 1f /* error: result = -errno */
+ ret
+
+
+ .section ".text"
+ .align 4
+ .global _dl_open
+ .type _dl_open,@function
+_dl_open:
+ mov $SYS_open, %eax
+ int $0x80
+ jb 1f /* error: result = -errno */
+ ret
+
+
+ .section ".text"
+ .align 4
+ .global _dl_read
+ .type _dl_read,@function
+_dl_read:
+ mov $SYS_read, %eax
+ int $0x80
+ jb 1f /* error: result = -errno */
+ ret
+
+
+ .section ".text"
+ .align 4
+ .global _dl_write
+ .type _dl_write,@function
+_dl_write:
+ mov $SYS_write, %eax
+ int $0x80
+ jb 1f /* error: result = -errno */
+ ret
+
+
+ .section ".text"
+ .align 4
+ .global _dl_stat
+ .type _dl_stat,@function
+_dl_stat:
+ mov $SYS_stat, %eax
+ int $0x80
+ jb 1f /* error: result = -errno */
+ ret
+
+
+ .section ".text"
+ .align 4
+ .global _dl_fstat
+ .type _dl_fstat,@function
+_dl_fstat:
+ mov $SYS_fstat, %eax
+ int $0x80
+ jb 1f /* error: result = -errno */
+ ret
+
+
+ .section ".text"
+ .align 4
+ .global _dl_fcntl
+ .type _dl_fcntl,@function
+_dl_fcntl:
+ mov $SYS_fcntl, %eax
+ int $0x80
+ jb 1f /* error: result = -errno */
+ ret
+
+
+ .section ".text"
+ .align 4
+ .global _dl_getdirentries
+ .type _dl_getdirentries,@function
+_dl_getdirentries:
+ mov $SYS_getdirentries, %eax
+ int $0x80
+ jb 1f /* error: result = -errno */
+ ret
+
+1:
+ /* error: result = -errno; - handled here. */
+ neg %eax
+ ret
+
+
+ .align 4
+ .global _dl_bind_start
+ .type _dl_bind_start,@function
+_dl_bind_start:
+ pushf # save registers
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ pushl %ebx
+ pushl %ebp
+ pushl %esi
+ pushl %edi
+ pushl %ds
+ pushl %es
+
+ pushl 44(%esp) # Copy of reloff
+ pushl 44(%esp) # Copy of obj
+ call _dl_bind@PLT # Call the binder
+ addl $8,%esp # pop binder args
+ movl %eax,44(%esp) # Store function to be called in obj
+
+ popl %es # restore registers
+ popl %ds
+ popl %edi
+ popl %esi
+ popl %ebp
+ popl %ebx
+ popl %edx
+ popl %ecx
+ popl %eax
+ popf
+
+ leal 4(%esp),%esp # Discard reloff, do not change eflags
+ ret
+
diff --git a/libexec/ld.so/i386/rtld_machine.c b/libexec/ld.so/i386/rtld_machine.c
new file mode 100644
index 00000000000..48023f6f226
--- /dev/null
+++ b/libexec/ld.so/i386/rtld_machine.c
@@ -0,0 +1,350 @@
+#define _DYN_LOADER
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/mman.h>
+
+#include <nlist.h>
+#include <link.h>
+
+#include "syscall.h"
+#include "archdep.h"
+#include "resolve.h"
+
+void
+_dl_bcopy(const void *src, void *dest, int size)
+{
+ const unsigned char *psrc = src;
+ unsigned char *pdest = dest;
+ int i;
+
+ for (i = 0; i < size; i++)
+ pdest[i] = psrc[i];
+}
+
+/*
+ * The following table holds for each relocation type:
+ * - the width in bits of the memory location the relocation
+ * applies to (not currently used)
+ * - the number of bits the relocation value must be shifted to the
+ * right (i.e. discard least significant bits) to fit into
+ * the appropriate field in the instruction word.
+ * - flags indicating whether
+ * * the relocation involves a symbol
+ * * the relocation is relative to the current position
+ * * the relocation is for a GOT entry
+ * * the relocation is relative to the load address
+ *
+ */
+#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_SZ(s) (((s) & 0xff) << 8) /* memory target size */
+#define _RF_RS(s) ((s) & 0xff) /* right shift */
+static int reloc_target_flags[] = {
+ 0, /* NONE */
+ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* RELOC_32*/
+ _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC32 */
+ _RF_G| _RF_SZ(32) | _RF_RS(00), /* GOT32 */
+ _RF_A| _RF_SZ(32) | _RF_RS(0), /* PLT32 */
+ _RF_S| _RF_SZ(32) | _RF_RS(0), /* COPY */
+ _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_DAT */
+ _RF_S| _RF_SZ(32) | _RF_RS(0), /* JUMP_SLOT */
+ _RF_A| _RF_B| _RF_SZ(32) | _RF_RS(0), /* RELATIVE */
+ 0, /* GOTOFF XXX */
+ 0, /* GOTPC XXX */
+ 0, /* DUMMY 11 */
+ 0, /* DUMMY 12 */
+ 0, /* DUMMY 13 */
+ 0, /* DUMMY 14 */
+ 0, /* DUMMY 15 */
+ 0, /* DUMMY 16 */
+ 0, /* DUMMY 17 */
+ 0, /* DUMMY 18 */
+ 0, /* DUMMY 19 */
+ _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* RELOC_16 */
+ _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* PC_16 */
+ _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* RELOC_8 */
+ _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* RELOC_PC8 */
+};
+
+#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 long reloc_target_bitmask[] = {
+#define _BM(x) (~(-(1ULL << (x))))
+ 0, /* NONE */
+ _BM(32), /* RELOC_32*/
+ _BM(32), /* PC32 */
+ _BM(32), /* GOT32 */
+ _BM(32), /* PLT32 */
+ 0, /* COPY */
+ _BM(32), /* GLOB_DAT */
+ _BM(32), /* JUMP_SLOT */
+ _BM(32), /* RELATIVE */
+ 0, /* GOTOFF XXX */
+ 0, /* GOTPC XXX */
+ 0, /* DUMMY 11 */
+ 0, /* DUMMY 12 */
+ 0, /* DUMMY 13 */
+ 0, /* DUMMY 14 */
+ 0, /* DUMMY 15 */
+ 0, /* DUMMY 16 */
+ 0, /* DUMMY 17 */
+ 0, /* DUMMY 18 */
+ 0, /* DUMMY 19 */
+ _BM(16), /* RELOC_16 */
+ _BM(8), /* PC_16 */
+ _BM(8), /* RELOC_8 */
+ _BM(8), /* RELOC_PC8 */
+#undef _BM
+};
+#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t])
+
+void _dl_reloc_plt(Elf_Addr *where, Elf_Addr value);
+
+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(Elf32_Rel);
+ rels = (Elf32_Rel *)(object->Dyn.info[rel]);
+ if (rels == NULL)
+ return(0);
+
+ /*
+ * 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);
+ }
+ }
+
+ 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 (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))
+ value = *where & RELOC_VALUE_BITMASK(type);
+ 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(symn, _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);
+ 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|
+ ((type == R_TYPE(JUMP_SLOT)) ? SYM_PLT:SYM_NOTPLT),
+ size);
+ 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 if (RELOC_TARGET_SIZE(type) > 32) {
+ *where &= ~mask;
+ *where |= value;
+ } else {
+ Elf32_Addr *where32 = (Elf32_Addr *)where;
+
+ *where32 &= ~mask;
+ *where32 |= value;
+ }
+ }
+
+ /* 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);
+ }
+ }
+
+ return (fails);
+}
+
+struct jmpslot {
+ u_short opcode;
+ u_short addr[2];
+ u_short reloc_index;
+#define JMPSLOT_RELOC_MASK 0xffff
+};
+#define JUMP 0xe990 /* NOP + JMP opcode */
+
+void
+_dl_reloc_plt(Elf_Addr *where, Elf_Addr value)
+{
+ *where = value;
+}
+
+/*
+ * Resolve a symbol at run-time.
+ */
+Elf_Addr
+_dl_bind(elf_object_t *object, int index)
+{
+ Elf_Rel *rel;
+ Elf_Word *addr;
+ const Elf_Sym *sym, *this;
+ const char *symn;
+ Elf_Addr ooff;
+
+ rel = (Elf_Rel *)(object->Dyn.info[DT_JMPREL]);
+
+ rel += index/sizeof(Elf_Rel);
+
+ sym = object->dyn.symtab;
+ sym += ELF_R_SYM(rel->r_info);
+ symn = object->dyn.strtab + sym->st_name;
+
+ addr = (Elf_Word *)(object->load_offs + rel->r_offset);
+ ooff = _dl_find_symbol(symn, _dl_objects, &this,
+ SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, 0);
+ if (this == NULL) {
+ _dl_printf("lazy binding failed!\n");
+ *((int *)0) = 0; /* XXX */
+ }
+
+ _dl_reloc_plt(addr, ooff + this->st_value);
+
+ return((Elf_Addr)ooff + this->st_value);
+}
+
+void
+_dl_md_reloc_got(elf_object_t *object, int lazy)
+{
+ extern void _dl_bind_start(void); /* XXX */
+ Elf_Addr *pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT];
+ int i, num;
+ Elf_Rel *rel;
+ struct load_list *llist;
+
+ pltgot[1] = (Elf_Addr)object;
+ pltgot[2] = (Elf_Addr)&_dl_bind_start;
+
+ if (object->Dyn.info[DT_PLTREL] != DT_REL)
+ return;
+
+ if (!lazy) {
+ _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ);
+ return;
+ }
+
+ rel = (Elf_Rel *)(object->Dyn.info[DT_JMPREL]);
+ num = (object->Dyn.info[DT_PLTRELSZ]);
+ 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 < num/sizeof(Elf_Rel); i++, rel++) {
+ Elf_Addr *where;
+ where = (Elf_Addr *)(rel->r_offset + object->load_offs);
+ *where += object->load_offs;
+ }
+ for (llist = object->load_list; llist != NULL; llist = llist->next) {
+ if (!(llist->prot & PROT_WRITE))
+ _dl_mprotect(llist->start, llist->size,
+ llist->prot);
+ }
+}
+
+
diff --git a/libexec/ld.so/i386/syscall.h b/libexec/ld.so/i386/syscall.h
new file mode 100644
index 00000000000..c9719118dd1
--- /dev/null
+++ b/libexec/ld.so/i386/syscall.h
@@ -0,0 +1,67 @@
+/* $OpenBSD: syscall.h,v 1.1 2002/08/23 23:02:48 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed under OpenBSD by
+ * Niklas Hallqvist.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 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>
+
+#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_write(int, const char*, int);
+int _dl_fstat(int, struct stat *);
+int _dl_fcntl(int, int, ...);
+int _dl_getdirentries(int, char*, int, long *);
+
+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__*/