summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorRyan Long <ryan.long@oarcorp.com>2022-07-19 12:20:31 -0500
committerJoel Sherrill <joel@rtems.org>2022-07-29 08:32:47 -0500
commit0bd6514aa249322edbd52026ebfc2675a1685ead (patch)
tree06d2f0b44ec9db5a4a8433d1d264f1d7c0f1d53b /cpukit
parentlibdl/rtl-elf.h: Fix aarch64 define (diff)
downloadrtems-0bd6514aa249322edbd52026ebfc2675a1685ead.tar.bz2
cpukit/libdl: Add support for AArch64
rtl-mdreloc-aarch64.c and elf_machdep.h came from NetBSD. Updates #4682
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/libdl/rtl-mdreloc-aarch64.c599
-rw-r--r--cpukit/score/cpu/aarch64/include/machine/elf_machdep.h256
2 files changed, 855 insertions, 0 deletions
diff --git a/cpukit/libdl/rtl-mdreloc-aarch64.c b/cpukit/libdl/rtl-mdreloc-aarch64.c
new file mode 100644
index 0000000000..41147e285c
--- /dev/null
+++ b/cpukit/libdl/rtl-mdreloc-aarch64.c
@@ -0,0 +1,599 @@
+/*
+ * Taken from NetBSD and stripped of the relocations not needed on RTEMS.
+ */
+
+/* $NetBSD: mdreloc.c,v 1.14 2020/06/16 21:01:30 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas of 3am Software Foundry.
+ *
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+/*-
+ * Copyright (c) 2014-2015 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by Andrew Turner
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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 AND CONTRIBUTORS ``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 CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: mdreloc.c,v 1.14 2020/06/16 21:01:30 joerg Exp $");
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <string.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+#include <sys/endian.h>
+#include <unwind.h>
+
+#include <rtems/rtl/rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include <rtems/rtl/rtl-trace.h>
+#include "rtl-unwind.h"
+
+typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
+typedef _Unwind_Word _uw;
+
+struct tls_data {
+ size_t td_tlsindex;
+ Elf_Addr td_tlsoffs;
+};
+
+rtems_rtl_elf_rel_status
+rtems_rtl_elf_reloc_rela (
+ rtems_rtl_obj* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue,
+ const bool parsing
+);
+
+#define __BITS(hi,lo) ((~((~(Elf_Addr)0)<<((hi)+1)))&((~(Elf_Addr)0)<<(lo)))
+#define WIDTHMASK(w) (0xffffffffffffffffUL >> (64 - (w)))
+
+static inline bool
+checkoverflow(Elf_Addr addr, int bitwidth, Elf_Addr targetaddr,
+ const char *bitscale, void *where, Elf64_Addr off)
+{
+ const Elf_Addr mask = ~__BITS(bitwidth - 1, 0);
+
+ if (((addr & mask) != 0) && ((addr & mask) != mask)) {
+ printf("kobj_reloc: Relocation 0x%jx too far from %p"
+ " (base+0x%jx) for %dbit%s\n",
+ (uintptr_t)targetaddr, where, off, bitwidth, bitscale);
+ return true;
+ }
+
+ return false;
+}
+
+static inline bool
+checkalign(Elf_Addr addr, int alignbyte, void *where, Elf64_Addr off)
+{
+ if ((addr & (alignbyte - 1)) != 0) {
+ printf("kobj_reloc: Relocation 0x%jx unaligned at %p"
+ " (base+0x%jx). must be aligned %d\n",
+ (uintptr_t)addr, where, off, alignbyte);
+ return true;
+ }
+ return false;
+}
+
+/*
+ * Set to 1 to allow untested relocations. If you tested one and it
+ * works or you fixed the relocation please remove the guard.
+ */
+#define ALLOW_UNTESTED_RELOCS 1
+
+static void*
+set_veneer(void* tramopline, Elf_Addr target)
+{
+ /*
+ * http://shell-storm.org/online/Online-Assembler-and-Disassembler/
+ *
+ * ldr x9, #8
+ * br x9
+ *
+ */
+ uint64_t* tramp = (uint64_t*) tramopline;
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ *tramp++ = 0xd61f012058000049;
+#else
+ *tramp++ = 0xd61f012058000049; /* not tested */
+#endif
+ *tramp++ = (uint64_t) target;
+ return tramp;
+}
+
+static size_t
+get_veneer_size(int type)
+{
+ (void) type;
+ return 16;
+}
+
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+ return 16;
+}
+
+uint32_t
+rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
+ const Elf_Shdr* shdr)
+{
+ return 0;
+}
+
+uint32_t
+rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
+ int section,
+ const char* name,
+ const Elf_Shdr* shdr,
+ const uint32_t flags)
+{
+ (void) obj;
+ (void) section;
+ (void) name;
+ (void) shdr;
+ return flags;
+}
+
+bool
+rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
+bool
+rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
+{
+ return true;
+}
+
+rtems_rtl_elf_rel_status
+rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue,
+ const bool parsing)
+{
+ Elf64_Addr *where;
+ Elf32_Addr *where32;
+ Elf_Addr off = rela->r_offset;
+ Elf_Addr target;
+ Elf_Addr raddr;
+ uint32_t *insn, immhi, immlo, shift;
+
+ where = (Elf_Addr *)(sect->base + rela->r_offset);
+ where32 = (void *)where;
+
+ insn = (uint32_t *)where;
+
+ /*
+ * S - the address of the symbol
+ * A - the addend of the reolcation
+ * P - the address of the place being relocated (derived from r_offset)
+ * Page(expr) - the page address of the expression expr, defined as (expr & ~0xFFF).
+ */
+ switch (ELF_R_TYPE(rela->r_info)) {
+ case R_TYPE(NONE):
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+ printf ("rtl: NONE %p in %s\n", where, rtems_rtl_obj_oname (obj));
+ }
+ break;
+
+ case R_TYPE(ABS64): /* word S + A */
+ case R_TYPE(GLOB_DAT): /* word S + A */
+ if (!parsing) {
+ target = (Elf_Addr)symvalue + rela->r_addend;
+
+ if (*where != target)
+ *where = target;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc 64/GLOB_DAT in %s --> %p in %s\n",
+ sect->name, (void *)*where,
+ rtems_rtl_obj_oname (obj));
+ }
+ break;
+
+ /*
+ * If S is a normal symbol, resolves to the difference between the static
+ * link address of S and the execution address of S. If S is the null symbol
+ * (ELF symbol index 0), resolves to the difference between the static link
+ * address of P and the execution address of P.
+ */
+ case R_TYPE(RELATIVE): /* Delta(S) + A */
+ if (!parsing) {
+ *where = (Elf_Addr)(sect->base + rela->r_addend);
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc RELATIVE in %s --> %p in %s\n",
+ sect->name, (void *)*where,
+ rtems_rtl_obj_oname (obj));
+ }
+ break;
+
+ case R_TYPE(COPY):
+ /*
+ * These are deferred until all other relocations have
+ * been done. All we do here is make sure that the
+ * COPY relocation is not in a shared library. They
+ * are allowed only in executable files.
+ */
+ printf("rtl: reloc COPY (please report)\n");
+ break;
+
+ case R_AARCH64_ADD_ABS_LO12_NC: /* S + A */
+ case R_AARCH64_LDST8_ABS_LO12_NC:
+ case R_AARCH_LDST16_ABS_LO12_NC:
+ case R_AARCH_LDST32_ABS_LO12_NC:
+ case R_AARCH_LDST64_ABS_LO12_NC:
+ switch (ELF_R_TYPE(rela->r_info)) {
+ case R_AARCH64_ADD_ABS_LO12_NC:
+ case R_AARCH64_LDST8_ABS_LO12_NC:
+ shift = 0;
+ break;
+ case R_AARCH_LDST16_ABS_LO12_NC:
+ shift = 1;
+ break;
+ case R_AARCH_LDST32_ABS_LO12_NC:
+ shift = 2;
+ break;
+ case R_AARCH_LDST64_ABS_LO12_NC:
+ shift = 3;
+ break;
+ default:
+ printf("illegal rtype: %ld\n", ELF_R_TYPE(rela->r_info));
+ break;
+ }
+
+ /*
+ * S + A
+ * e.g.) add x0,x0,#:lo12:<sym>+<addend>
+ * ldrb w0,[x0,#:lo12:<sym>+<addend>]
+ * ldrh w0,[x0,#:lo12:<sym>+<addend>]
+ * ldr w0,[x0,#:lo12:<sym>+<addend>]
+ * ldr x0,[x0,#:lo12:<sym>+<addend>]
+ */
+ if (!parsing) {
+ target = (Elf_Addr)symvalue + rela->r_addend;
+ if (checkalign(target, 1 << shift, where, off)) {
+ printf ("rtl: reloc checkalign failed in %s --> %p in %s\n",
+ sect->name, (void *)*where,
+ rtems_rtl_obj_oname (obj));
+ printf("ELF_R_TYPE is : %ld\n", ELF_R_TYPE(rela->r_info));
+ break;
+ }
+ target &= WIDTHMASK(12);
+ target >>= shift;
+ *insn = htole32(
+ (le32toh(*insn) & ~__BITS(21,10)) | (target << 10));
+ }
+ break;
+
+ case R_AARCH64_ADR_PREL_PG_HI21:
+ /*
+ * Page(S + A) - Page(P)
+ * e.g.) adrp x0,<sym>+<addend>
+ */
+ if (!parsing) {
+ target = (Elf_Addr)symvalue + rela->r_addend;
+ target = target >> 12;
+ raddr = target << 12;
+ target -= (uintptr_t)where >> 12;
+
+ if (checkoverflow(target, 21, raddr, " x 4k", where, off)) {
+ return rtems_rtl_elf_rel_failure;
+ }
+
+ immlo = target & WIDTHMASK(2);
+ immhi = (target >> 2) & WIDTHMASK(19);
+ *insn = htole32((le32toh(*insn) &
+ ~(__BITS(30,29) | __BITS(23,5))) |
+ (immlo << 29) | (immhi << 5));
+ }
+ break;
+
+ case R_AARCH_JUMP26:
+ case R_AARCH_CALL26:
+ /*
+ * S + A - P
+ * e.g.) b <sym>+<addend>
+ * bl <sym>+<addend>
+ */
+ if (parsing && sect->base == 0) {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: JUMP26/PC26/CALL tramp cache\n");
+ return rtems_rtl_elf_rel_tramp_cache;
+ }
+
+ raddr = (Elf_Addr)symvalue + rela->r_addend;
+ target = raddr - (uintptr_t)where;
+ if (checkalign(target, 4, where, off)) {
+ return rtems_rtl_elf_rel_failure;
+ }
+
+ target = (intptr_t)target >> 2;
+
+ if (((Elf_Sword)target > 0x1FFFFFF) || ((Elf_Sword)target < -0x2000000)) {
+ Elf_Word tramp_addr;
+ size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info));
+
+ if (parsing) {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: JUMP26/PC26/CALL tramp add\n");
+ return rtems_rtl_elf_rel_tramp_add;
+ }
+
+ if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
+ rtems_rtl_set_error (EINVAL,
+ "%s: CALL/JUMP26: overflow: no tramp memory",
+ sect->name);
+ return rtems_rtl_elf_rel_failure;
+ }
+
+ tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
+ obj->tramp_brk = set_veneer(obj->tramp_brk, symvalue);
+
+ target = tramp_addr + rela->r_addend - (uintptr_t)where;
+ target = (uintptr_t)target >> 2;
+ }
+
+ if (checkoverflow(target, 26, raddr, " word", where, off)) {
+ return rtems_rtl_elf_rel_failure;
+ }
+
+ if (!parsing) {
+ target &= WIDTHMASK(26);
+ *insn = htole32((le32toh(*insn) & ~__BITS(25,0)) | target);
+ }
+
+ break;
+
+ case R_AARCH64_PREL32:
+ /*
+ * S + A - P
+ * e.g.) 1: .word <sym>+<addend>-1b
+ */
+ if (!parsing) {
+ raddr = (Elf_Addr)symvalue + rela->r_addend;
+ target = raddr - (uintptr_t)where;
+ if (checkoverflow(target, 32, raddr, "", where, off)) {
+ return rtems_rtl_elf_rel_failure;
+ }
+ *where32 = target;
+ }
+ break;
+
+ case R_TYPE(TLSDESC):
+ printf ("rtl: reloc TLSDESC in %s --> %p in %s\n",
+ sect->name, (void *)*where,
+ rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TLS_TYPE(TLS_DTPREL):
+ printf ("rtl: reloc TLS_DTPREL in %s --> %p in %s\n",
+ sect->name, (void *)*where,
+ rtems_rtl_obj_oname (obj));
+ break;
+ case R_TLS_TYPE(TLS_DTPMOD):
+ printf ("rtl: reloc TLS_DTPMOD in %s --> %p in %s\n",
+ sect->name, (void *)*where,
+ rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TLS_TYPE(TLS_TPREL):
+ printf ("rtl: reloc TLS_TPREL in %s --> %p in %s\n",
+ sect->name, (void *)*where,
+ rtems_rtl_obj_oname (obj));
+ break;
+
+ default:
+ printf ("rtl: Unsupported relocation type in %s --> %p in %s\n",
+ sect->name, (void *)where,
+ rtems_rtl_obj_oname (obj));
+ return rtems_rtl_elf_rel_failure;
+ }
+
+ return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
+rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ return rtems_rtl_elf_reloc_rela (obj,
+ rela,
+ sect,
+ symname,
+ syminfo,
+ symvalue,
+ true);
+}
+
+rtems_rtl_elf_rel_status
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ return rtems_rtl_elf_reloc_rela (obj,
+ rela,
+ sect,
+ symname,
+ syminfo,
+ symvalue,
+ false);
+}
+
+rtems_rtl_elf_rel_status
+rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ return rtems_rtl_elf_rel_failure;
+}
+
+rtems_rtl_elf_rel_status
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ return rtems_rtl_elf_rel_failure;
+}
+
+bool
+rtems_rtl_elf_unwind_parse (const rtems_rtl_obj* obj,
+ const char* name,
+ uint32_t flags)
+{
+ /*
+ * We location the EH sections in section flags.
+ */
+ return false;
+}
+
+bool
+rtems_rtl_elf_unwind_register (rtems_rtl_obj* obj)
+{
+ return true;
+}
+
+bool
+rtems_rtl_elf_unwind_deregister (rtems_rtl_obj* obj)
+{
+ obj->loader = NULL;
+ return true;
+}
+
+/* An exception index table entry. */
+typedef struct __EIT_entry
+{
+ _uw fnoffset;
+ _uw content;
+} __EIT_entry;
+
+/* The exception index table location in the base module */
+extern __EIT_entry __exidx_start;
+extern __EIT_entry __exidx_end;
+
+/*
+ * A weak reference is in libgcc, provide a real version and provide a way to
+ * manage loaded modules.
+ *
+ * Passed in the return address and a reference to the number of records
+ * found. We set the start of the exidx data and the number of records.
+ */
+_Unwind_Ptr __gnu_Unwind_Find_exidx (_Unwind_Ptr return_address,
+ int* nrec) __attribute__ ((__noinline__,
+ __used__,
+ __noclone__));
+
+_Unwind_Ptr __gnu_Unwind_Find_exidx (_Unwind_Ptr return_address,
+ int* nrec)
+{
+ rtems_rtl_data* rtl;
+ rtems_chain_node* node;
+ __EIT_entry* exidx_start = &__exidx_start;
+ __EIT_entry* exidx_end = &__exidx_end;
+
+ rtl = rtems_rtl_lock ();
+
+ node = rtems_chain_first (&rtl->objects);
+ while (!rtems_chain_is_tail (&rtl->objects, node)) {
+ rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
+ if (rtems_rtl_obj_text_inside (obj, (void*) return_address)) {
+ exidx_start = (__EIT_entry*) obj->eh_base;
+ exidx_end = (__EIT_entry*) (obj->eh_base + obj->eh_size);
+ break;
+ }
+ node = rtems_chain_next (node);
+ }
+
+ rtems_rtl_unlock ();
+
+ *nrec = exidx_end - exidx_start;
+
+ return (_Unwind_Ptr) exidx_start;
+}
diff --git a/cpukit/score/cpu/aarch64/include/machine/elf_machdep.h b/cpukit/score/cpu/aarch64/include/machine/elf_machdep.h
new file mode 100644
index 0000000000..c1d219d715
--- /dev/null
+++ b/cpukit/score/cpu/aarch64/include/machine/elf_machdep.h
@@ -0,0 +1,256 @@
+/* $NetBSD: elf_machdep.h,v 1.4 2018/10/12 01:28:58 ryo Exp $ */
+
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas of 3am Software Foundry.
+ *
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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_ELF_MACHDEP_H_
+#define _AARCH64_ELF_MACHDEP_H_
+
+#ifdef __aarch64__
+
+#if defined(__AARCH64EB__)
+#define ELF64_MACHDEP_ENDIANNESS ELFDATA2MSB
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB
+#else
+#define ELF64_MACHDEP_ENDIANNESS ELFDATA2LSB
+#define ELF32_MACHDEP_ENDIANNESS ELFDATA2LSB
+#endif
+
+/* Processor specific flags for the ELF header e_flags field. */
+#define EF_ARM_RELEXEC 0x00000001
+#define EF_ARM_HASENTRY 0x00000002
+#define EF_ARM_INTERWORK 0x00000004 /* GNU binutils 000413 */
+#define EF_ARM_SYMSARESORTED 0x00000004 /* ARM ELF A08 */
+#define EF_ARM_APCS_26 0x00000008 /* GNU binutils 000413 */
+#define EF_ARM_DYNSYMSUSESEGIDX 0x00000008 /* ARM ELF B01 */
+#define EF_ARM_APCS_FLOAT 0x00000010 /* GNU binutils 000413 */
+#define EF_ARM_MAPSYMSFIRST 0x00000010 /* ARM ELF B01 */
+#define EF_ARM_PIC 0x00000020
+#define EF_ARM_ALIGN8 0x00000040 /* 8-bit structure alignment. */
+#define EF_ARM_NEW_ABI 0x00000080
+#define EF_ARM_OLD_ABI 0x00000100
+#define EF_ARM_SOFT_FLOAT 0x00000200
+#define EF_ARM_BE8 0x00800000
+#define EF_ARM_EABIMASK 0xff000000
+#define EF_ARM_EABI_VER1 0x01000000
+#define EF_ARM_EABI_VER2 0x02000000
+#define EF_ARM_EABI_VER3 0x03000000
+#define EF_ARM_EABI_VER4 0x04000000
+#define EF_ARM_EABI_VER5 0x05000000
+
+#define ELF32_MACHDEP_ID_CASES \
+ case EM_ARM: \
+ break;
+
+#define ELF64_MACHDEP_ID_CASES \
+ case EM_AARCH64: \
+ break;
+
+#define ELF64_MACHDEP_ID EM_AARCH64
+#define ELF32_MACHDEP_ID EM_ARM
+
+#define KERN_ELFSIZE 64
+#define ARCH_ELFSIZE 64 /* MD native binary size */
+
+/* Processor specific relocation types */
+
+#define R_AARCH64_NONE 0
+#define R_AARCH64_NONE2 256
+
+#define R_AARCH64_ABS64 257 /* S + A */
+#define R_AARCH64_ABS32 258 /* S + A */
+#define R_AARCH64_ABS16 259 /* S + A */
+#define R_AARCH64_PREL64 260 /* S + A - P */
+#define R_AARCH64_PREL32 261 /* S + A - P */
+#define R_AARCH64_PREL16 262 /* S + A - P */
+#define R_AARCH64_MOVW_UABS_G0 263 /* S + A [bits 0..15] */
+#define R_AARCH64_MOVW_UABS_G0_NC 264 /* S + A [bits 0..15] */
+#define R_AARCH64_MOVW_UABS_G1 265 /* S + A [bits 16..31] */
+#define R_AARCH64_MOVW_UABS_G1_NC 266 /* S + A [bits 16..31] */
+#define R_AARCH64_MOVW_UABS_G2 267 /* S + A [bits 32..47] */
+#define R_AARCH64_MOVW_UABS_G2_NC 268 /* S + A [bits 32..47] */
+#define R_AARCH64_MOVW_UABS_G3 269 /* S + A [bits 48..63] */
+#define R_AARCH64_MOVW_SABS_G0 270 /* S + A [bits 0..15] */
+#define R_AARCH64_MOVW_SABS_G1 271 /* S + A [bits 16..31] */
+#define R_AARCH64_MOVW_SABS_G2 272 /* S + A [bits 32..47] */
+#define R_AARCH64_LD_PREL_LO19 273 /* S + A - P */
+#define R_AARCH64_ADR_PREL_LO21 274 /* S + A - P */
+#define R_AARCH64_ADR_PREL_PG_HI21 275 /* Page(S + A) - Page(P) */
+#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Page(S + A) - Page(P) */
+#define R_AARCH64_ADD_ABS_LO12_NC 277 /* S + A */
+#define R_AARCH64_LDST8_ABS_LO12_NC 278 /* S + A */
+#define R_AARCH_TSTBR14 279 /* S + A - P */
+#define R_AARCH_CONDBR19 281 /* S + A - P */
+#define R_AARCH_JUMP26 282 /* S + A - P */
+#define R_AARCH_CALL26 283 /* S + A - P */
+#define R_AARCH_LDST16_ABS_LO12_NC 284 /* S + A */
+#define R_AARCH_LDST32_ABS_LO12_NC 285 /* S + A */
+#define R_AARCH_LDST64_ABS_LO12_NC 286 /* S + A */
+#define R_AARCH64_MOVW_PREL_G0 287 /* S + A - P */
+#define R_AARCH64_MOVW_PREL_G0_NC 288 /* S + A - P */
+#define R_AARCH64_MOVW_PREL_G1 289 /* S + A - P */
+#define R_AARCH64_MOVW_PREL_G1_NC 290 /* S + A - P */
+#define R_AARCH64_MOVW_PREL_G2 291 /* S + A - P */
+#define R_AARCH64_MOVW_PREL_G2_NC 292 /* S + A - P */
+#define R_AARCH64_MOVW_PREL_G3 293 /* S + A - P */
+
+#define R_AARCH64_LDST128_ABS_LO12_NC 299 /* S + A */
+#define R_AARCH64_MOVW_GOTOFF_G0 300 /* G(GDAT(S + A)) - GOT */
+#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 /* G(GDAT(S + A)) - GOT */
+#define R_AARCH64_MOVW_GOTOFF_G1 302 /* G(GDAT(S + A)) - GOT */
+#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 /* G(GDAT(S + A)) - GOT */
+#define R_AARCH64_MOVW_GOTOFF_G2 304 /* G(GDAT(S + A)) - GOT */
+#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 /* G(GDAT(S + A)) - GOT */
+#define R_AARCH64_MOVW_GOTOFF_G3 306 /* G(GDAT(S + A)) - GOT */
+#define R_AARCH64_GOTREL64 307 /* S + A - GOT */
+#define R_AARCH64_GOTREL32 308 /* S + A - GOT */
+#define R_AARCH64_GOT_LD_PREL19 309 /* G(GDAT(S + A)) - P */
+#define R_AARCH64_LD64_GOTOFF_LO15 310 /* G(GDAT(S + A)) - GOT */
+#define R_AARCH64_ADR_GOT_PAGE 311 /* Page(G(GDAT(S + A))) - Page(GOT) */
+#define R_AARCH64_LD64_GOT_LO12_NC 312 /* G(GDAT(S + A)) */
+#define R_AARCH64_LD64_GOTPAGE_LO15 313 /* G(GDAT(S + A)) - Page(GOT) */
+
+#define R_AARCH64_TLSGD_ADR_PREL21 512 /* G(GTLSIDX(S,A)) - P */
+#define R_AARCH64_TLSGD_ADR_PAGE21 513 /* Page(G(GTLSIDX(S,A))) - Page(P) */
+#define R_AARCH64_TLSGD_ADD_LO12_NC 514 /* G(GTLSIDX(S,A)) */
+#define R_AARCH64_TLSGD_MOVW_G1 515 /* G(GTLSIDX(S,A)) - GOT */
+#define R_AARCH64_TLSGD_MOVW_G0_NV 516 /* G(GTLSIDX(S,A)) - GOT */
+#define R_AARCH64_TLSLD_ADR_PREL21 517 /* G(GLDM(S,A)) - P */
+#define R_AARCH64_TLSLD_ADR_PAGE21 518 /* Page(G(GLDM(S))) - Page(P) */
+#define R_AARCH64_TLSLD_ADD_LO12_NC 519 /* G(GLDM(S)) */
+#define R_AARCH64_TLSLD_MOVW_G1 520 /* G(GLDM(S)) - GOT */
+#define R_AARCH64_TLSLD_MOVW_G0_NC 521 /* G(GLDM(S)) - GOT */
+#define R_AARCH64_TLSLD_LD_PREL21 522 /* G(GLDM(S)) - P */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 528 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* DTPREL(S+A) */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* G(GTPREL(S+A)) - GOT */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* G(GTPREL(S+A)) - GOT */
+#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page(G(GTPREL(S+A))) - Page(P) */
+#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* G(GTPREL(S+A)) */
+#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* G(GTPREL(S+A)) - P */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TPREL(S+A) */
+#define R_AARCH64_MOVW_TPREL_G1 545 /* TPREL(S+A) */
+#define R_AARCH64_MOVW_TPREL_G1_NC 546 /* TPREL(S+A) */
+#define R_AARCH64_MOVW_TPREL_G0 547 /* TPREL(S+A) */
+#define R_AARCH64_MOVW_TPREL_G0_NC 548 /* TPREL(S+A) */
+#define R_AARCH64_ADD_TPREL_HI12 549 /* TPREL(S+A) */
+#define R_AARCH64_ADD_TPREL_LO12 550 /* TPREL(S+A) */
+#define R_AARCH64_ADD_TPREL_LO12_NC 551 /* TPREL(S+A) */
+#define R_AARCH64_LDST8_TPREL_LO12 552 /* TPREL(S+A) */
+#define R_AARCH64_LDST8_TPREL_LO12_NC 553 /* TPREL(S+A) */
+#define R_AARCH64_LDST16_TPREL_LO12 554 /* TPREL(S+A) */
+#define R_AARCH64_LDST16_TPREL_LO12_NC 555 /* TPREL(S+A) */
+#define R_AARCH64_LDST32_TPREL_LO12 556 /* TPREL(S+A) */
+#define R_AARCH64_LDST32_TPREL_LO12_NC 557 /* TPREL(S+A) */
+#define R_AARCH64_LDST64_TPREL_LO12 558 /* TPREL(S+A) */
+#define R_AARCH64_LDST64_TPREL_LO12_NC 559 /* TPREL(S+A) */
+#define R_AARCH64_TLSDESC_LD_PREL19 560 /* G(GTLSDESC(S+A)) - P */
+#define R_AARCH64_TLSDESC_LD_PREL21 561 /* G(GTLSDESC(S+A)) - P */
+#define R_AARCH64_TLSDESC_LD_PAGE21 562 /* Page(G(GTLSDESC(S+A))) - Page(P) */
+#define R_AARCH64_TLSDESC_LD64_LO12 563 /* G(GTLSDESC(S+A)) */
+#define R_AARCH64_TLSDESC_ADD_LO12 564 /* G(GTLSDESC(S+A)) */
+#define R_AARCH64_TLSDESC_OFF_G1 565 /* G(GTLSDESC(S+A)) - GOT */
+#define R_AARCH64_TLSDESC_OFF_G0_NC 566 /* G(GTLSDESC(S+A)) - GOT */
+#define R_AARCH64_TLSDESC_LDR 567 /* */
+#define R_AARCH64_TLSDESC_ADD 568 /* */
+#define R_AARCH64_TLSDESC_CALL 569 /* */
+#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 /* TPREL(S+A) */
+#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 /* TPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 /* DTPREL(S+A) */
+#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 572 /* DTPREL(S+A) */
+
+/* Dynamic Relocations */
+#define R_AARCH64_P32_COPY 180
+#define R_AARCH64_P32_GLOB_DAT 181 /* S + A */
+#define R_AARCH64_P32_JUMP_SLOT 182 /* S + A */
+#define R_AARCH64_P32_RELATIVE 183 /* Delta(S) + A */
+#define R_AARCH64_P32_TLS_DTPREL 184 /* DTPREL(S+A) */
+#define R_AARCH64_P32_TLS_DTPMOD 185 /* LBM(S) */
+#define R_AARCH64_P32_TLS_TPREL 186 /* TPREL(S+A) */
+#define R_AARCH64_P32_TLSDESC 187 /* TLSDESC(S+A) */
+#define R_AARCH64_P32_IRELATIVE 188 /* Indirect(Delta(S) + A) */
+
+#define R_AARCH64_COPY 1024
+#define R_AARCH64_GLOB_DAT 1025 /* S + A */
+#define R_AARCH64_JUMP_SLOT 1026 /* S + A */
+#define R_AARCH64_RELATIVE 1027 /* Delta(S) + A */
+#define R_AARCH64_TLS_DTPREL64 1028 /* DTPREL(S+A) */
+#define R_AARCH64_TLS_DTPMOD64 1029 /* LBM(S) */
+#define R_AARCH64_TLS_TPREL64 1030 /* TPREL(S+A) */
+#define R_AARCH64_TLSDESC 1031 /* TLSDESC(S+A) */
+#define R_AARCH64_IRELATIVE 1032 /* Indirect(Delta(S) + A) */
+
+#define R_TYPE(name) R_AARCH64_ ## name
+#define R_TLS_TYPE(name) R_AARCH64_ ## name ## 64
+
+/* Processor specific program header types */
+#define PT_AARCH64_ARCHEXT (PT_LOPROC + 0)
+#define PT_AARCH64_UNWIND (PT_LOPROC + 1)
+
+/* Processor specific section header flags */
+#define SHF_ENTRYSECT 0x10000000
+#define SHF_COMDEF 0x80000000
+
+#define SHT_AARCH64_ATTRIBUTES (SHT_LOPROC + 3)
+
+#ifdef _KERNEL
+#ifdef ELFSIZE
+#define ELF_MD_PROBE_FUNC ELFNAME2(aarch64_netbsd,probe)
+#endif
+
+struct exec_package;
+
+int aarch64_netbsd_elf64_probe(struct lwp *, struct exec_package *, void *,
+ char *, vaddr_t *);
+int aarch64_netbsd_elf32_probe(struct lwp *, struct exec_package *, void *,
+ char *, vaddr_t *);
+#endif
+
+#elif defined(__arm__)
+
+#include <arm/elf_machdep.h>
+
+#endif
+
+#endif /* _AARCH64_ELF_MACHDEP_H_ */