diff options
-rw-r--r-- | libexec/ld.so/hppa/Makefile.inc | 6 | ||||
-rw-r--r-- | libexec/ld.so/hppa/archdep.h | 99 | ||||
-rw-r--r-- | libexec/ld.so/hppa/ldasm.S | 272 | ||||
-rw-r--r-- | libexec/ld.so/hppa/rtld_machine.c | 341 | ||||
-rw-r--r-- | libexec/ld.so/hppa/syscall.h | 63 | ||||
-rw-r--r-- | libexec/ld.so/loader.c | 5 |
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); |