summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libexec/ld.so/hppa/Makefile.inc6
-rw-r--r--libexec/ld.so/hppa/archdep.h99
-rw-r--r--libexec/ld.so/hppa/ldasm.S272
-rw-r--r--libexec/ld.so/hppa/rtld_machine.c341
-rw-r--r--libexec/ld.so/hppa/syscall.h63
-rw-r--r--libexec/ld.so/loader.c5
6 files changed, 784 insertions, 2 deletions
diff --git a/libexec/ld.so/hppa/Makefile.inc b/libexec/ld.so/hppa/Makefile.inc
new file mode 100644
index 00000000000..c3453709e1d
--- /dev/null
+++ b/libexec/ld.so/hppa/Makefile.inc
@@ -0,0 +1,6 @@
+# $OpenBSD: Makefile.inc,v 1.1 2004/05/25 21:48:00 mickey Exp $
+
+CFLAGS += -fpic
+AFLAGS += -fpic
+#ELF_LDFLAGS=-t
+LDADD= `$(CC) -print-libgcc-file-name`
diff --git a/libexec/ld.so/hppa/archdep.h b/libexec/ld.so/hppa/archdep.h
new file mode 100644
index 00000000000..655acccc27b
--- /dev/null
+++ b/libexec/ld.so/hppa/archdep.h
@@ -0,0 +1,99 @@
+/* $OpenBSD: archdep.h,v 1.1 2004/05/25 21:48:00 mickey Exp $ */
+
+/*
+ * Copyright (c) 2004 Michael Shalayeff
+ * 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 _HPPA_ARCHDEP_H_
+#define _HPPA_ARCHDEP_H_
+
+#define DL_MALLOC_ALIGN 8 /* Arch constraint or otherwise */
+
+#define MACHID EM_PARISC /* ELF e_machine ID value checked */
+
+#define RELTYPE Elf_Rela
+#define RELSIZE sizeof(Elf_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 *
+_dl_mquery(void *addr, unsigned int len, unsigned int prot,
+ unsigned int flags, int fd, off_t offset)
+{
+ return((void *)_dl__syscall((quad_t)SYS_mquery, 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)
+{
+ /* HPPA does no REL type relocations */
+ _dl_exit(20);
+}
+
+static inline void
+RELOC_RELA(Elf_RelA *r, const Elf_Sym *s, Elf_Addr *p, unsigned long v)
+{
+ /* XXX fille out _sl ??? */
+ if (ELF_R_TYPE(r->r_info) == RELOC_DIR32) {
+ *p = v + r->r_addend;
+ } else if (ELF_R_TYPE(r->r_info) == RELOC_IPLT) {
+ *p = v + s->st_value + r->r_addend;
+ } else if (ELF_R_TYPE(r->r_info) == RELOC_PLABEL32) {
+ *p = v + s->st_value + r->r_addend;
+ } else {
+ _dl_printf("unknown bootstrap relocation\n");
+ _dl_exit(6);
+ }
+}
+
+#define RELOC_GOT(obj, offs)
+
+#define MD_CALL(sobj, func, arg) \
+ hppa_call((arg), (sobj)->dyn.pltgot, (func))
+
+#define MD_ATEXIT(sobj, sym, func) \
+ MD_CALL((sobj), (void (*)())((sobj)->load_offs + (sym)->st_value), &_hppa_dl_dtors)
+
+#define GOT_PERMS PROT_READ
+
+void _hppa_dl_dtors(void);
+void hppa_call(void *, Elf_Addr *, void (*)(void));
+
+#endif /* _HPPA_ARCHDEP_H_ */
diff --git a/libexec/ld.so/hppa/ldasm.S b/libexec/ld.so/hppa/ldasm.S
new file mode 100644
index 00000000000..5924c87b58f
--- /dev/null
+++ b/libexec/ld.so/hppa/ldasm.S
@@ -0,0 +1,272 @@
+/* $OpenBSD: ldasm.S,v 1.1 2004/05/25 21:48:00 mickey Exp $ */
+
+/*
+ * Copyright (c) 2004 Michael Shalayeff
+ * All rights reserved.
+ *
+ * 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 OR HIS RELATIVES 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 MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/syscall.h>
+#include <machine/asm.h>
+#define _LOCORE
+#include <machine/frame.h>
+#include <machine/vmparam.h>
+#undef _LOCORE
+
+ENTRY(_dl_start,32)
+ copy r3, r1
+ copy sp, r3
+ stwm r1, HPPA_FRAME_SIZE+16*4(sp)
+
+ stw %arg0, HPPA_FRAME_ARG(0)(r3) /* ps_strings */
+
+#define ADDR(s,r) \
+ bl 4, t1 !\
+ depi 0, 31, 2, t1 /* kill pl bits */ !\
+ b s /* cold brunch -- never done */ !\
+ ldw 0(t1), t2 /* cat(w,w1,w2{10},w2{0..9}) << 2 */ !\
+ extru t2, 28, 10, t3 /* w2{0..9} */ !\
+ extru t2, 26, 16, r /* w1 */ !\
+ dep t3, 31, 11, r !\
+ extru,= t2, 31, 1, r0 /* w */ !\
+ depi 1, 15, 1, r !\
+ extru,= t2, 29, 1, r0 /* w2{10} */ !\
+ depi 1, 21, 1, r !\
+ sh2add r, t1, r /* plus the base */ !\
+ addi 8, r, r /* bl target is -8 */
+
+ ADDR(_GLOBAL_OFFSET_TABLE_, r19)
+ ADDR(_DYNAMIC, arg2)
+ stw arg2, HPPA_FRAME_ARG(1)(r3)
+
+ ldw 0(arg0), arg0
+ ldo 4(r3), arg1 /* dl_data */
+ bl _dl_boot_bind, rp
+ ldo -4(arg0), arg0
+
+ ldw HPPA_FRAME_ARG(1)(r3), arg1 /* &_DYNAMIC */
+ ldw HPPA_FRAME_ARG(0)(r3), arg3 /* ps_strings */
+ ldw 0(r19), arg2
+ sub arg1, arg2, arg2 /* loff */
+
+ ldw 0(arg3), arg0 /* argv */
+ ldw 8(arg3), arg1 /* envp */
+
+ bl _dl_boot, rp
+ ldo 4(r3), arg3 /* dl_data */
+
+ ldw HPPA_FRAME_ARG(0)(r3), arg0 /* ps_strings */
+ /* ??? cleanup, arg1 */
+ /* ??? obj, arg2 */
+
+ ldo HPPA_FRAME_SIZE(r3), sp
+ copy r0, rp
+ bv r0(ret0)
+ ldwm -HPPA_FRAME_SIZE(sp), r3
+EXIT(_dl_start)
+
+/*
+ * void _hppa_dl_dtors(void);
+ */
+ENTRY(_hppa_dl_dtors,0)
+ ADDR(_GLOBAL_OFFSET_TABLE_, r19)
+ b _dl_dtors
+ nop
+EXIT(_hppa_dl_dtors)
+
+/*
+ * void hppa_call(void (*arg)(void), void *r19, Elf_Addr func);
+ */
+ENTRY(hppa_call,0)
+ copy r3, r1
+ copy sp, r3
+ stwm r1, HPPA_FRAME_SIZE(sp)
+ stw r19, HPPA_FRAME_SL(r3)
+ stw rp, HPPA_FRAME_CRP(r3)
+ copy arg1, r19
+ .call
+ blr r0, rp
+ bv,n (arg2)
+ nop
+ ldw HPPA_FRAME_CRP(r3), rp
+ ldw HPPA_FRAME_SL(r3), r19
+ ldo HPPA_FRAME_SIZE(r3), sp
+ bv r0(rp)
+ ldwm -HPPA_FRAME_SIZE(sp), r3
+EXIT(hppa_call)
+
+ENTRY(_dl_bind_start,32)
+ copy r3, r1
+ copy sp, r3
+ stwm r1, HPPA_FRAME_SIZE(sp)
+
+ stw rp, HPPA_FRAME_CRP(r3)
+ stw arg0, HPPA_FRAME_ARG(0)(r3)
+ stw arg1, HPPA_FRAME_ARG(1)(r3)
+ stw arg2, HPPA_FRAME_ARG(2)(r3)
+ stw arg3, HPPA_FRAME_ARG(3)(r3)
+ stw ret0, 8(r3)
+ stw ret1, 12(r3)
+
+ ldw 12(r20), arg0
+ copy r19, arg1
+
+ bl _dl_bind, rp
+ copy r21, r19
+
+ /* load &func and sl from plt entry returned */
+ ldw 0(ret0), r21
+ ldw 4(ret0), r19
+
+ ldw HPPA_FRAME_ARG(0)(r3), arg0
+ ldw HPPA_FRAME_ARG(1)(r3), arg1
+ ldw HPPA_FRAME_ARG(2)(r3), arg2
+ ldw HPPA_FRAME_ARG(3)(r3), arg3
+ ldw 8(r3), ret0
+ ldw 12(r3), ret0
+
+ ldw HPPA_FRAME_CRP(r3), rp
+ ldo HPPA_FRAME_SIZE(r3), sp
+ bv r0(r21)
+ ldwm -HPPA_FRAME_SIZE(sp), r3
+EXIT(_dl_bind_start)
+
+#define SYSCALL(x) !\
+ stw rp, HPPA_FRAME_ERP(sr0,sp) !\
+ ldil L%SYSCALLGATE, r1 !\
+ ble 4(sr7, r1) !\
+ ldi __CONCAT(SYS_,x), t1 !\
+ comb,<> r0, t1, _dl_sysexit !\
+ ldw HPPA_FRAME_ERP(sr0,sp), rp
+
+_dl_sysexit
+ bv r0(rp)
+ sub r0, ret0, ret0
+
+ENTRY(_dl_close,0)
+ SYSCALL(close)
+ bv r0(rp)
+ nop
+EXIT(_dl_close)
+
+ENTRY(_dl_exit,0)
+ SYSCALL(exit)
+ bv r0(rp)
+ nop
+EXIT(_dl_exit)
+
+ENTRY(_dl_issetugid,0)
+ SYSCALL(issetugid)
+ bv r0(rp)
+ nop
+EXIT(_dl_issetugid)
+
+ENTRY(_dl__syscall,0)
+ SYSCALL(__syscall)
+ bv r0(rp)
+ nop
+EXIT(_dl__syscall)
+
+ENTRY(_dl_munmap,0)
+ SYSCALL(munmap)
+ bv r0(rp)
+ nop
+EXIT(_dl_munmap)
+
+ENTRY(_dl_mprotect,0)
+ SYSCALL(mprotect)
+ bv r0(rp)
+ nop
+EXIT(_dl_mprotect)
+
+ENTRY(_dl_open,0)
+ SYSCALL(open)
+ bv r0(rp)
+ nop
+EXIT(_dl_open)
+
+ENTRY(_dl_read,0)
+ SYSCALL(read)
+ bv r0(rp)
+ nop
+EXIT(_dl_read)
+
+ENTRY(_dl_write,0)
+ SYSCALL(write)
+ bv r0(rp)
+ nop
+EXIT(_dl_write)
+
+ENTRY(_dl_stat,0)
+ SYSCALL(stat)
+ bv r0(rp)
+ nop
+EXIT(_dl_stat)
+
+ENTRY(_dl_fstat,0)
+ SYSCALL(fstat)
+ bv r0(rp)
+ nop
+EXIT(_dl_fstat)
+
+ENTRY(_dl_fcntl,0)
+ SYSCALL(fcntl)
+ bv r0(rp)
+ nop
+EXIT(_dl_fcntl)
+
+ENTRY(_dl_sysctl,0)
+ SYSCALL(__sysctl)
+ bv r0(rp)
+ nop
+EXIT(_dl_issetugid)
+
+ENTRY(_dl_getdirentries,0)
+ SYSCALL(getdirentries)
+ bv r0(rp)
+ nop
+EXIT(_dl_getdirentries)
+
+ENTRY(_dl_sigprocmask,0)
+ stw arg2, HPPA_FRAME_ARG(2)(sp)
+
+ comb,<>,n r0, arg1, _dl_sigprocmask$nblock
+
+ b _dl_sigprocmask$call
+ ldi 1, arg0
+
+_dl_sigprocmask$nblock
+ ldw 0(arg1), arg1
+ stw arg1, HPPA_FRAME_ARG(1)(sp)
+
+_dl_sigprocmask$call
+ SYSCALL(sigprocmask)
+
+ ldw HPPA_FRAME_ARG(2)(sp), arg2
+ add,= r0, arg2, r0
+ stw ret0, 0(arg2)
+ bv r0(rp)
+ copy r0, ret0
+EXIT(_dl_sigprocmask)
+
+ .end
diff --git a/libexec/ld.so/hppa/rtld_machine.c b/libexec/ld.so/hppa/rtld_machine.c
new file mode 100644
index 00000000000..a202ad34cf9
--- /dev/null
+++ b/libexec/ld.so/hppa/rtld_machine.c
@@ -0,0 +1,341 @@
+/* $OpenBSD: rtld_machine.c,v 1.1 2004/05/25 21:48:00 mickey Exp $ */
+
+/*
+ * Copyright (c) 2004 Michael Shalayeff
+ * Copyright (c) 2001 Niklas Hallqvist
+ * Copyright (c) 2001 Artur Grabowski
+ * Copyright (c) 1999 Dale Rahn
+ * All rights reserved.
+ *
+ * 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 OR HIS RELATIVES 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 MIND, 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/cdefs.h>
+#include <sys/mman.h>
+#include <sys/tree.h>
+
+#include <nlist.h>
+#include <link.h>
+#include <signal.h>
+#include <string.h>
+
+#include "syscall.h"
+#include "archdep.h"
+#include "resolve.h"
+
+typedef
+struct hppa_plabel {
+ Elf_Addr pc;
+ Elf_Addr sl;
+ SPLAY_ENTRY(hppa_plabel) node;
+} hppa_plabel_t;
+SPLAY_HEAD(_dl_md_plabels, hppa_plabel) _dl_md_plabel_root;
+
+static __inline int
+_dl_md_plcmp(hppa_plabel_t *a, hppa_plabel_t *b)
+{
+ if (a->sl < b->sl)
+ return (-1);
+ else if (a->sl > b->sl)
+ return (1);
+ else if (a->pc < b->pc)
+ return (-1);
+ else if (a->pc > b->pc)
+ return (1);
+ else
+ return (0);
+}
+
+SPLAY_PROTOTYPE(_dl_md_plabels, hppa_plabel, node, _dl_md_plcmp);
+SPLAY_GENERATE(_dl_md_plabels, hppa_plabel, node, _dl_md_plcmp);
+
+Elf_Addr
+_dl_md_plabel(const elf_object_t *obj, const Elf_Sym *sym, const Elf_RelA *rela)
+{
+ hppa_plabel_t key, *p;
+
+ if (ELF_ST_TYPE(sym->st_info) != STT_FUNC)
+ return (0);
+
+ key.pc = obj->load_offs + sym->st_value + rela->r_addend;
+ key.sl = (Elf_Addr)obj->dyn.pltgot;
+ p = SPLAY_FIND(_dl_md_plabels, &_dl_md_plabel_root, &key);
+ if (p == NULL) {
+ p = _dl_malloc(sizeof(*p));
+ if (p == NULL)
+ _dl_exit(5);
+ p->pc = key.pc;
+ p->sl = key.sl;
+ SPLAY_INSERT(_dl_md_plabels, &_dl_md_plabel_root, p);
+ }
+
+ return (Elf_Addr)p | 2;
+}
+
+int
+_dl_md_reloc(elf_object_t *object, int rel, int relasz)
+{
+ Elf_RelA *rela;
+ Elf_Addr loff;
+ int i, numrela, fails = 0;
+ size_t size;
+
+ loff = object->load_offs;
+ numrela = object->Dyn.info[relasz] / sizeof(Elf_RelA);
+ rela = (Elf_RelA *)(object->Dyn.info[rel]);
+
+ DL_DEB(("object %s relasz %x, numrela %x loff %x\n",
+ object->load_name, object->Dyn.info[relasz], numrela, loff));
+
+ if (rela == NULL)
+ return (0);
+
+ for (i = 0; i < numrela; i++, rela++) {
+ const elf_object_t *sobj;
+ const Elf_Sym *sym, *this;
+ Elf_Addr *pt, ooff;
+ const char *symn;
+ int type;
+
+ type = ELF_R_TYPE(rela->r_info);
+ if (type == RELOC_NONE)
+ continue;
+
+ this = sym = object->dyn.symtab + ELF_R_SYM(rela->r_info);
+ sobj = object;
+ symn = object->dyn.strtab + sym->st_name;
+ pt = (Elf_Addr *)(rela->r_offset + loff);
+
+ ooff = 0;
+ if (ELF_R_SYM(rela->r_info) && sym->st_name) {
+ ooff = _dl_find_symbol_bysym(object,
+ ELF_R_SYM(rela->r_info), _dl_objects,
+ &this, &sobj, SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND|
+ ((type == RELOC_DIR32) ? SYM_NOTPLT : SYM_PLT),
+ sym->st_size);
+ if (!this) {
+ _dl_printf("%s: %s: can't resolve reference '%s'\n",
+ _dl_progname, object->load_name, symn);
+ fails++;
+ continue;
+ }
+ }
+
+ DL_DEB(("*pt=%x r_addend=%x r_sym=%x\n",
+ *pt, rela->r_addend, ELF_R_SYM(rela->r_info)));
+
+ switch (type) {
+ case RELOC_DIR32:
+ if (ELF_R_SYM(rela->r_info) && sym->st_name) {
+ *pt = ooff + this->st_value + rela->r_addend;
+ DL_DEB(("[%x]DIR32: %s:%s -> 0x%x in %s\n",
+ i, symn, object->load_name,
+ *pt, sobj->load_name));
+ } else {
+ /*
+ * XXX should objects ever get their
+ * sections loaded insequential this
+ * would have to get a section number
+ * (ELF_R_SYM(rela->r_info))-1 and then:
+ * *pt = sect->addr + rela->r_addend;
+ */
+ if (ELF_R_SYM(rela->r_info))
+ *pt += loff;
+ else
+ *pt += loff + rela->r_addend;
+ DL_DEB(("[%x]DIR32: %s @ 0x%x\n", i,
+ object->load_name, *pt));
+ }
+ break;
+
+ case RELOC_PLABEL32:
+ if (ELF_R_SYM(rela->r_info)) {
+ *pt = _dl_md_plabel(sobj, this, rela);
+ DL_DEB(("[%x]PLABEL32: %s:%s -> 0x%x in %s\n",
+ i, symn, object->load_name,
+ *pt, sobj->load_name));
+ } else {
+ *pt = loff + rela->r_addend;
+ DL_DEB(("[%x]PLABEL32: %s @ 0x%x\n", i,
+ object->load_name, *pt));
+ }
+ break;
+
+ case RELOC_IPLT:
+ if (ELF_R_SYM(rela->r_info)) {
+ pt[0] = ooff + this->st_value + rela->r_addend;
+ pt[1] = (Elf_Addr)sobj->dyn.pltgot;
+ DL_DEB(("[%x]IPLT: %s:%s -> 0x%x:0x%x in %s\n",
+ i, symn, object->load_name,
+ pt[0], pt[1], sobj->load_name));
+ } else {
+ pt[0] = loff + rela->r_addend;
+ pt[1] = (Elf_Addr)object->dyn.pltgot;
+ DL_DEB(("[%x]IPLT: %s @ 0x%x:0x%x\n", i,
+ object->load_name, pt[0], pt[1]));
+ }
+ break;
+
+ case RELOC_COPY:
+ size = sym->st_size;
+ ooff = _dl_find_symbol(symn, object->next, &sym, NULL,
+ SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_NOTPLT,
+ size, object);
+ if (sym) {
+ _dl_bcopy((void *)(ooff + sym->st_value),
+ pt, sym->st_size);
+ DL_DEB(("[%x]COPY: %s[%x]:%s -> %p[%x] in %s\n",
+ i, symn, ooff + sym->st_value,
+ object->load_name, pt, sym->st_size,
+ sobj->load_name));
+ } else
+ DL_DEB(("[%x]COPY: no sym\n", i));
+ break;
+
+ default:
+ DL_DEB(("[%x]UNKNOWN(%d): type=%d off=0x%lx "
+ "addend=0x%lx rel=0x%x\n", i, type,
+ ELF_R_TYPE(rela->r_info), rela->r_offset,
+ rela->r_addend, *pt));
+ break;
+ }
+ }
+
+ return (fails);
+}
+
+void
+_dl_md_reloc_got(elf_object_t *object, int lazy)
+{
+ Elf_RelA *rela;
+ Elf_Addr ooff;
+ int i, numrela;
+ const Elf_Sym *this;
+
+ if (object->dyn.pltrel != DT_RELA)
+ return;
+
+ lazy = 0; /* force busy binding */
+
+ object->got_addr = NULL;
+ object->got_size = 0;
+ this = NULL;
+ ooff = _dl_find_symbol("__got_start", object, &this, NULL,
+ 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, NULL,
+ SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, 0, object);
+ if (this != NULL)
+ object->got_size = ooff + this->st_value - object->got_addr;
+
+ 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 (!lazy) {
+ _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ);
+ } else {
+ rela = (Elf_RelA *)(object->dyn.jmprel);
+ numrela = object->dyn.pltrelsz / sizeof(Elf_RelA);
+ ooff = object->load_offs;
+
+ for (i = 0; i < numrela; i++, rela++) {
+ Elf_Addr *r_addr = (Elf_Addr *)(ooff + rela->r_offset);
+
+ if (ELF_R_SYM(rela->r_info)) {
+ r_addr[0] = 0; /* TODO */
+ r_addr[1] = (Elf_Addr) ((void *)rela -
+ (void *)object->dyn.jmprel);
+ } else {
+ r_addr[0] = ooff + rela->r_addend;
+ r_addr[1] = (Elf_Addr)object->dyn.pltgot;
+ }
+ }
+ }
+ if (object->got_size != 0)
+ _dl_mprotect((void *)object->got_start, object->got_size,
+ GOT_PERMS);
+}
+
+/*
+ * Resolve a symbol at run-time.
+ */
+Elf_Addr
+_dl_bind(elf_object_t *object, int reloff)
+{
+ const elf_object_t *sobj;
+ const Elf_Sym *sym, *this;
+ Elf_Addr *addr, ooff;
+ const char *symn;
+ Elf_Addr value;
+ Elf_RelA *rela;
+ sigset_t omask, nmask;
+
+ rela = (Elf_RelA *)(object->dyn.jmprel + reloff);
+
+ sym = object->dyn.symtab;
+ sym += ELF_R_SYM(rela->r_info);
+ symn = object->dyn.strtab + sym->st_name;
+
+ addr = (Elf_Addr *)(object->load_offs + rela->r_offset);
+ this = NULL;
+ ooff = _dl_find_symbol(symn, _dl_objects, &this, &sobj,
+ SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT, sym->st_size, object);
+ if (this == NULL) {
+ _dl_printf("lazy binding failed!\n");
+ *((int *)0) = 0; /* XXX */
+ }
+
+ value = ooff + this->st_value;
+
+ /* if PLT+GOT is protected, allow the write */
+ if (object->got_size != 0) {
+ sigfillset(&nmask);
+ _dl_sigprocmask(SIG_BLOCK, &nmask, &omask);
+ /* mprotect the actual modified region, not the whole plt */
+ _dl_mprotect((void*)addr, sizeof (Elf_Addr) * 2,
+ PROT_READ|PROT_WRITE);
+ }
+
+ addr[0] = value;
+ addr[1] = (Elf_Addr)sobj->dyn.pltgot;
+
+ /* if PLT is (to be protected, change back to RO */
+ if (object->got_size != 0) {
+ /* mprotect the actual modified region, not the whole plt */
+ _dl_mprotect((void*)addr, sizeof (Elf_Addr) * 3,
+ PROT_READ);
+ _dl_sigprocmask(SIG_SETMASK, &omask, NULL);
+ }
+
+ return (value);
+}
diff --git a/libexec/ld.so/hppa/syscall.h b/libexec/ld.so/hppa/syscall.h
new file mode 100644
index 00000000000..d5f93fc71a9
--- /dev/null
+++ b/libexec/ld.so/hppa/syscall.h
@@ -0,0 +1,63 @@
+/* $OpenBSD: syscall.h,v 1.1 2004/05/25 21:48:00 mickey 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 6038b330fde..0ae5055c725 100644
--- a/libexec/ld.so/loader.c
+++ b/libexec/ld.so/loader.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: loader.c,v 1.78 2004/05/25 20:51:03 mickey Exp $ */
+/* $OpenBSD: loader.c,v 1.79 2004/05/25 21:48:00 mickey Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -485,7 +485,8 @@ _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp)
#if defined(__alpha__)
dynp = (Elf_Dyn *)((long)_DYNAMIC);
-#elif defined(__sparc__) || defined(__sparc64__) || defined(__powerpc__)
+#elif defined(__sparc__) || defined(__sparc64__) || defined(__powerpc__) || \
+ defined(__hppa__)
dynp = dynamicp;
#else
dynp = (Elf_Dyn *)((long)_DYNAMIC + loff);