summaryrefslogtreecommitdiff
path: root/libexec/ld.so/i386
diff options
context:
space:
mode:
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__*/