diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-01-11 14:11:28 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-01-11 14:11:28 +0000 |
commit | a19ef24e00ae92f5d564a101a554ca67972dae31 (patch) | |
tree | 1bbc89b060ec7d4909c4d1c1ceafa903d4eb2d0e /libexec | |
parent | 6666f619700e1195ae197f6fda756130f17c3769 (diff) |
Add support for AArch64.
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/ld.so/aarch64/Makefile.inc | 6 | ||||
-rw-r--r-- | libexec/ld.so/aarch64/archdep.h | 73 | ||||
-rw-r--r-- | libexec/ld.so/aarch64/ldasm.S | 182 | ||||
-rw-r--r-- | libexec/ld.so/aarch64/rtld_machine.c | 378 | ||||
-rw-r--r-- | libexec/ld.so/aarch64/syscall.h | 62 |
5 files changed, 701 insertions, 0 deletions
diff --git a/libexec/ld.so/aarch64/Makefile.inc b/libexec/ld.so/aarch64/Makefile.inc new file mode 100644 index 00000000000..1eaf4504070 --- /dev/null +++ b/libexec/ld.so/aarch64/Makefile.inc @@ -0,0 +1,6 @@ +# $OpenBSD: Makefile.inc,v 1.1 2017/01/11 14:11:27 patrick Exp $ + +CFLAGS += -fpic -fno-stack-protector +CFLAGS += -mcpu=cortex-a57+nofp+nosimd # this is -msoft-float +AFLAGS += -D_STANDALONE +CPPFLAGS += -I${.CURDIR}/../../lib/libc/arch/aarch64 diff --git a/libexec/ld.so/aarch64/archdep.h b/libexec/ld.so/aarch64/archdep.h new file mode 100644 index 00000000000..48f763c940e --- /dev/null +++ b/libexec/ld.so/aarch64/archdep.h @@ -0,0 +1,73 @@ +/* $OpenBSD: archdep.h,v 1.1 2017/01/11 14:11:27 patrick 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 _AARCH64_ARCHDEP_H_ +#define _AARCH64_ARCHDEP_H_ + +#define RELOC_TAG DT_RELA + +#define DL_MALLOC_ALIGN 4 /* Arch constraint or otherwise */ + +#define MACHID EM_AARCH64 /* ELF e_machine ID value checked */ + +#define RELTYPE Elf64_Rela +#define RELSIZE sizeof(Elf64_Rela) + +#include <elf_abi.h> +#include <machine/reloc.h> +#include "syscall.h" +#include "util.h" + +static inline void * +_dl_mmap(void *addr, size_t len, int prot, 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_DYN(Elf64_Rela *r, const Elf64_Sym *s, Elf64_Addr *p, unsigned long v) +{ + if (ELF64_R_TYPE(r->r_info) == R_AARCH64_RELATIVE) { + *p = v + r->r_addend; + } else if (ELF64_R_TYPE(r->r_info) == R_AARCH64_GLOB_DAT) { + *p = v + s->st_value + r->r_addend; + } else if (ELF64_R_TYPE(r->r_info) == R_AARCH64_ABS64) { + *p = v + s->st_value + r->r_addend; + } else { +#if !defined(RCRT0) + _dl_printf("unknown bootstrap relocation\n"); +#endif + _dl_exit(6); + } +} + +#define RELOC_GOT(obj, offs) + +#endif /* _AARCH64_ARCHDEP_H_ */ diff --git a/libexec/ld.so/aarch64/ldasm.S b/libexec/ld.so/aarch64/ldasm.S new file mode 100644 index 00000000000..491d05d5e17 --- /dev/null +++ b/libexec/ld.so/aarch64/ldasm.S @@ -0,0 +1,182 @@ +/* $OpenBSD: ldasm.S,v 1.1 2017/01/11 14:11:27 patrick Exp $ */ + +/* + * Copyright (c) 2016 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 * 8) /* XXX */ +#include <machine/asm.h> +#include <sys/syscall.h> +#include <SYS.h> + +ENTRY(_dl_start) + mov x29, sp + // need to worry about alignment, I think not? + mov x19, sp + sub sp, sp, #8+8+DL_DATA_SIZE // dl_data size + add x20, sp, #4 // dl_data + mov x21, lr // save old lr + + mov x0, x29 // original stack + mov x1, x20 // dl_data + + adrp x2, :got:_DYNAMIC /* &_DYNAMIC */ + add x2, x2, #:lo12:_DYNAMIC + + bl _dl_boot_bind + + add x0, x29, #8 // argv + ldr x1, [x29] // load argc + add x1, x0, x1, lsl #3 // envp = argv + argc * 8 + add x1, x1, #8 // + 8 + ldr x2, [x20, #7*8] // loff from dl_data + mov x3, x20 // dl_data + bl _dl_boot + + mov sp, x29 // move stack back + mov x29, xzr // clear frame back pointer + mov lr, xzr + + adrp x8, :got:_dl_dtors + ldr x2, [x8, :got_lo12:_dl_dtors] + + br x0 + +ENTRY(_dl_bind_start) + /* + * ip is pointer to got entry for this relocation + * lr is pointer to pltgot[2], which is entry -1 of got plt reloc. + * return address is on stack + */ + stp x29, x30, [sp, #-160]! + stp x0, x1, [sp,#16] + stp x2, x3, [sp,#32] + stp x4, x5, [sp,#48] + stp x6, x7, [sp,#64] + stp x8, x9, [sp,#80] + stp x10, x11, [sp,#96] + stp x12, x13, [sp,#112] + stp x14, x15, [sp,#128] + str x18, [sp,#144] + + mov x1, x16 // reladdr + + + ldp x0, x1, [sp,#16] + ldp x2, x3, [sp,#32] + ldp x4, x5, [sp,#48] + ldp x6, x7, [sp,#64] + ldp x8, x9, [sp,#80] + ldp x10, x11, [sp,#96] + ldp x12, x13, [sp,#112] + ldp x14, x15, [sp,#128] + ldr x18, [sp,#144] + ldp x29, x30, [sp], #-160 + br x16 + + +#if 0 + stmdb sp!, {r0-r4,sl,fp} + + sub r1, ip, lr /* r1 = 4 * (n + 1) */ + sub r1, r1, #4 /* r1 = 4 * n */ + mov r1, r1, lsr #2 /* r1 = n */ + + ldr r0, [lr, #-4] + bl _dl_bind + mov ip, r0 + ldmia sp!, {r0-r4,sl,fp,lr} + mov pc, ip +#endif + + /* 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) ;\ + bcs .L_cerr ;\ + ret + + .section ".text" + .align 4 +DL_SYSCALL(close) + + + .global _dl_exit + .type _dl_exit%function +_dl_exit: + SYSTRAP(exit) + 1: + b 1b + +DL_SYSCALL(issetugid) +DL_SYSCALL(getthrid) +DL_SYSCALL2(_syscall,__syscall) +DL_SYSCALL(munmap) +DL_SYSCALL(mprotect) +DL_SYSCALL(open) +DL_SYSCALL(read) +DL_SYSCALL(write) +DL_SYSCALL(fstat) +DL_SYSCALL(readlink) +DL_SYSCALL(utrace) +DL_SYSCALL(getentropy) +DL_SYSCALL(sendsyslog) +DL_SYSCALL(pledge) +DL_SYSCALL2(getcwd,__getcwd) +DL_SYSCALL(sysctl) +DL_SYSCALL2(set_tcb,__set_tcb) + +DL_SYSCALL(getdents) + + .global _dl_sigprocmask + .type _dl_sigprocmask%function +_dl_sigprocmask: +#if 0 + teq r1, #0 + moveq r0, #1 + moveq r1, #0 + ldrne r1, [r1] + SYSTRAP(sigprocmask) + bcs .L_cerr + teq r2, #0 + strne r0, [r2] + mov r0, #0 + mov pc, lr +#endif + +.L_cerr: + neg w0, w0 /* r0 = -errno */ + ret + +ENTRY(_rtld_tlsdesc) + ldr x0, [x0, #8] + ret diff --git a/libexec/ld.so/aarch64/rtld_machine.c b/libexec/ld.so/aarch64/rtld_machine.c new file mode 100644 index 00000000000..bfed15414e8 --- /dev/null +++ b/libexec/ld.so/aarch64/rtld_machine.c @@ -0,0 +1,378 @@ +/* $OpenBSD: rtld_machine.c,v 1.1 2017/01/11 14:11:27 patrick 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 <sys/syscall.h> +#include <sys/unistd.h> + +#include <nlist.h> +#include <link.h> + +#include "syscall.h" +#include "archdep.h" +#include "resolve.h" + +int64_t pcookie __attribute__((section(".openbsd.randomdata"))) __dso_hidden; + +void _dl_bind_start(void); /* XXX */ +Elf_Addr _dl_bind(elf_object_t *object, int index); +#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_V 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 */ + [ R_AARCH64_ABS64 ] = + _RF_V|_RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* ABS64 */ + [ R_AARCH64_GLOB_DAT ] = + _RF_V|_RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* GLOB_DAT */ + [ R_AARCH64_JUMP_SLOT ] = + _RF_V|_RF_S| _RF_SZ(64) | _RF_RS(0), /* JUMP_SLOT */ + [ R_AARCH64_RELATIVE ] = + _RF_V|_RF_B|_RF_A| _RF_SZ(64) | _RF_RS(0), /* REL64 */ + [ R_AARCH64_TLSDESC ] = + _RF_V|_RF_S, + [ R_AARCH64_TLS_TPREL64 ] = + _RF_V|_RF_S, + [ R_AARCH64_COPY ] = + _RF_V|_RF_S| _RF_SZ(32) | _RF_RS(0), /* 20 COPY */ + +}; + +#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 Elf_Addr reloc_target_bitmask[] = { +#define _BM(x) (~(Elf_Addr)0 >> ((8*sizeof(reloc_target_bitmask[0])) - (x))) + 0, /* 0 NONE */ + [ R_AARCH64_ABS64 ] = _BM(64), + [ R_AARCH64_GLOB_DAT ] = _BM(64), + [ R_AARCH64_JUMP_SLOT ] = _BM(64), + [ R_AARCH64_RELATIVE ] = _BM(64), + [ R_AARCH64_TLSDESC ] = _BM(64), + [ R_AARCH64_TLS_TPREL64 ] = _BM(64), + [ R_AARCH64_COPY ] = _BM(64), +#undef _BM +}; +#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) + +#define R_TYPE(x) R_AARCH64_ ## x + +void _dl_reloc_plt(Elf_Word *where, Elf_Addr value, Elf_RelA *rel); + +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) + +int +_dl_md_reloc(elf_object_t *object, int rel, int relsz) +{ + long i; + long numrel; + long relrel; + int fails = 0; + Elf_Addr loff; + Elf_Addr prev_value = 0; + const Elf_Sym *prev_sym = NULL; + Elf_RelA *rels; + struct load_list *llist; + + loff = object->obj_base; + numrel = object->Dyn.info[relsz] / sizeof(Elf_RelA); + relrel = rel == DT_RELA ? object->relcount : 0; + rels = (Elf_RelA *)(object->Dyn.info[rel]); + + if (rels == NULL) + return(0); + + if (relrel > numrel) { + _dl_printf("relcount > numrel: %ld > %ld\n", relrel, numrel); + _dl_exit(20); + } + + /* + * 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); + } + } + + /* tight loop for leading RELATIVE relocs */ + for (i = 0; i < relrel; i++, rels++) { + Elf_Addr *where; + +#ifdef DEBUG + if (ELF_R_TYPE(rels->r_info) != R_TYPE(RELATIVE)) { + _dl_printf("RELCOUNT wrong\n"); + _dl_exit(20); + } +#endif + where = (Elf_Addr *)(rels->r_offset + loff); + *where += loff; + } + for (; 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 >= nitems(reloc_target_flags)) { + _dl_printf(" bad relocation %d %d\n", i, type); + _dl_exit(1); + } + if ((reloc_target_flags[type] & _RF_V)==0) { + _dl_printf(" bad relocation %d %d\n", i, type); + _dl_exit(1); + } + 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 = rels->r_addend; + 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 if (sym == prev_sym) { + value += prev_value; + } else { + this = NULL; + ooff = _dl_find_symbol_bysym(object, + ELF_R_SYM(rels->r_info), &this, + SYM_SEARCH_ALL|SYM_WARNNOTFOUND| + ((type == R_TYPE(JUMP_SLOT)) ? + SYM_PLT : SYM_NOTPLT), + sym, NULL); + if (this == NULL) { +resolve_failed: + if (ELF_ST_BIND(sym->st_info) != + STB_WEAK) + fails++; + continue; + } + prev_sym = sym; + prev_value = (Elf_Addr)(ooff + this->st_value); + value += prev_value; + } + } + + if (type == R_TYPE(JUMP_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_JMPREL for DL_BIND_NOW, + * otherwise the lazy binding plt initialization is performed. + */ +int +_dl_md_reloc_got(elf_object_t *object, int lazy) +{ + int fails = 0; + Elf_Addr *pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT]; + int i, num; + Elf_RelA *rel; + + if (object->Dyn.info[DT_PLTREL] != DT_RELA) + return (0); + + if (object->traced) + lazy = 1; + + lazy = 0; // until support is written. + + if (!lazy) { + fails = _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); + } else { + rel = (Elf_RelA *)(object->Dyn.info[DT_JMPREL]); + num = (object->Dyn.info[DT_PLTRELSZ]); + + for (i = 0; i < num/sizeof(Elf_RelA); i++, rel++) { + Elf_Addr *where; + where = (Elf_Addr *)(rel->r_offset + object->obj_base); + *where += object->obj_base; + } + + pltgot[1] = (Elf_Addr)object; + pltgot[2] = (Elf_Addr)_dl_bind_start; + } + + /* mprotect the GOT */ + _dl_protect_segment(object, 0, "__got_start", "__got_end", PROT_READ); + + return (fails); +} + +Elf_Addr +_dl_bind(elf_object_t *object, int relidx) +{ + Elf_RelA *rel; + const Elf_Sym *sym, *this; + const char *symn; + const elf_object_t *sobj; + Elf_Addr ooff; + int64_t cookie = pcookie; + struct { + struct __kbind param; + Elf_Addr newval; + } buf; + + rel = ((Elf_RelA *)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, &sobj); + if (this == NULL) { + _dl_printf("lazy binding failed!\n"); + *(volatile int *)0 = 0; /* XXX */ + } + + buf.newval = ooff + this->st_value; + + if (sobj->traced && _dl_trace_plt(sobj, symn)) + return buf.newval; + + buf.param.kb_addr = (Elf_Word *)(object->obj_base + rel->r_offset); + buf.param.kb_size = sizeof(Elf_Addr); + + /* directly code the syscall, so that it's actually inline here */ + { + register long syscall_num __asm("x8") = SYS_kbind; + register void *arg1 __asm("x0") = &buf; + register long arg2 __asm("x1") = sizeof(buf); + register long arg3 __asm("x2") = cookie; + + __asm volatile("svc 0" : "+r" (arg1), "+r" (arg2) + : "r" (syscall_num), "r" (arg3) + : "cc", "memory"); + } + + return buf.newval; +} diff --git a/libexec/ld.so/aarch64/syscall.h b/libexec/ld.so/aarch64/syscall.h new file mode 100644 index 00000000000..6160e700a55 --- /dev/null +++ b/libexec/ld.so/aarch64/syscall.h @@ -0,0 +1,62 @@ +/* $OpenBSD: syscall.h,v 1.1 2017/01/11 14:11:27 patrick 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> + +#ifndef _dl_MAX_ERRNO +#define _dl_MAX_ERRNO 512L +#endif +#define _dl_mmap_error(__res) \ + ((long)__res < 0 && (long)__res >= -_dl_MAX_ERRNO) + +int _dl_close(int); +__dead +int _dl_exit(int); +int _dl_issetugid(void); +int _dl_getthrid(void); +long _dl__syscall(quad_t, ...); +int _dl_mprotect(const void *, size_t, int); +int _dl_munmap(const void *, size_t); +int _dl_open(const char *, int); +ssize_t _dl_read(int, const char *, size_t); +int _dl_fstat(int, struct stat *); +ssize_t _dl_getdents(int, char *, size_t); +int _dl_sysctl(const int *, u_int, void *, size_t *, void *, size_t); +ssize_t _dl_readlink(const char *, char *, size_t); +int _dl_pledge(const char *, const char **); +int _dl_getcwd(char *, size_t); +int _dl_utrace(const char *, const void *, size_t); +int _dl_getentropy(char *, size_t); +int _dl_sendsyslog(const char *, size_t, int); +void _dl_set_tcb(void *); + +#endif /*__DL_SYSCALL_H__*/ |