summaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2017-01-11 14:11:28 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2017-01-11 14:11:28 +0000
commita19ef24e00ae92f5d564a101a554ca67972dae31 (patch)
tree1bbc89b060ec7d4909c4d1c1ceafa903d4eb2d0e /libexec
parent6666f619700e1195ae197f6fda756130f17c3769 (diff)
Add support for AArch64.
Diffstat (limited to 'libexec')
-rw-r--r--libexec/ld.so/aarch64/Makefile.inc6
-rw-r--r--libexec/ld.so/aarch64/archdep.h73
-rw-r--r--libexec/ld.so/aarch64/ldasm.S182
-rw-r--r--libexec/ld.so/aarch64/rtld_machine.c378
-rw-r--r--libexec/ld.so/aarch64/syscall.h62
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__*/