summaryrefslogtreecommitdiffstats
path: root/cpukit/libdl/rtl-mdreloc-aarch64.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libdl/rtl-mdreloc-aarch64.c')
-rw-r--r--cpukit/libdl/rtl-mdreloc-aarch64.c161
1 files changed, 77 insertions, 84 deletions
diff --git a/cpukit/libdl/rtl-mdreloc-aarch64.c b/cpukit/libdl/rtl-mdreloc-aarch64.c
index 41147e285c..1eb1d1e87d 100644
--- a/cpukit/libdl/rtl-mdreloc-aarch64.c
+++ b/cpukit/libdl/rtl-mdreloc-aarch64.c
@@ -73,16 +73,15 @@ __RCSID("$NetBSD: mdreloc.c,v 1.14 2020/06/16 21:01:30 joerg Exp $");
#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"
+#include <rtems/score/tls.h>
-typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
-typedef _Unwind_Word _uw;
+#include "rtl-unwind.h"
+#include "rtl-unwind-dw2.h"
struct tls_data {
size_t td_tlsindex;
@@ -110,7 +109,7 @@ checkoverflow(Elf_Addr addr, int bitwidth, Elf_Addr targetaddr,
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"
+ printf("kobj_reloc: Relocation 0x%" PRIxPTR " too far from %p"
" (base+0x%jx) for %dbit%s\n",
(uintptr_t)targetaddr, where, off, bitwidth, bitscale);
return true;
@@ -123,7 +122,7 @@ 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"
+ printf("kobj_reloc: Relocation 0x%" PRIxPTR " unaligned at %p"
" (base+0x%jx). must be aligned %d\n",
(uintptr_t)addr, where, off, alignbyte);
return true;
@@ -164,6 +163,12 @@ get_veneer_size(int type)
return 16;
}
+uint32_t rtems_rtl_obj_tramp_alignment (const rtems_rtl_obj* obj)
+{
+ (void) obj;
+ return sizeof(uint64_t);
+}
+
size_t
rtems_rtl_elf_relocate_tramp_max_size (void)
{
@@ -241,6 +246,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
* 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).
+ * TPREL(expr) - the thread pointer offset of the expression expr
*/
switch (ELF_R_TYPE(rela->r_info)) {
case R_TYPE(NONE):
@@ -259,7 +265,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: reloc 64/GLOB_DAT in %s --> %p in %s\n",
- sect->name, (void *)*where,
+ sect->name, (void *)(uintptr_t)*where,
rtems_rtl_obj_oname (obj));
}
break;
@@ -272,10 +278,10 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
*/
case R_TYPE(RELATIVE): /* Delta(S) + A */
if (!parsing) {
- *where = (Elf_Addr)(sect->base + rela->r_addend);
+ *where = (Elf_Addr)(uintptr_t)(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,
+ sect->name, (void *)(uintptr_t)*where,
rtems_rtl_obj_oname (obj));
}
break;
@@ -290,11 +296,44 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
printf("rtl: reloc COPY (please report)\n");
break;
+ case R_AARCH64_ADD_TPREL_HI12: /* TPREL(S + A) */
+ case R_AARCH64_ADD_TPREL_LO12:
+ case R_AARCH64_ADD_TPREL_LO12_NC:
+ uint32_t of_check = 0;
+ switch (ELF_R_TYPE(rela->r_info)) {
+ case R_AARCH64_ADD_TPREL_LO12:
+ of_check = 212;
+ /* fallthrough */
+ case R_AARCH64_ADD_TPREL_LO12_NC:
+ shift = 0;
+ break;
+ case R_AARCH64_ADD_TPREL_HI12:
+ of_check = 224;
+ shift = 12;
+ break;
+ default:
+ printf("illegal rtype: %" PRIu64 "\n", ELF_R_TYPE(rela->r_info));
+ break;
+ }
+
+ if (!parsing) {
+ target = (Elf_Addr)symvalue;
+ target >>= shift;
+ target &= WIDTHMASK(12);
+ if (of_check && target >= of_check) {
+ return rtems_rtl_elf_rel_failure;
+ }
+ *insn = htole32(
+ (le32toh(*insn) & ~__BITS(21,10)) | (target << 10));
+ }
+ 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:
+ case R_AARCH64_LDST128_ABS_LO12_NC:
switch (ELF_R_TYPE(rela->r_info)) {
case R_AARCH64_ADD_ABS_LO12_NC:
case R_AARCH64_LDST8_ABS_LO12_NC:
@@ -309,8 +348,11 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
case R_AARCH_LDST64_ABS_LO12_NC:
shift = 3;
break;
+ case R_AARCH64_LDST128_ABS_LO12_NC:
+ shift = 4;
+ break;
default:
- printf("illegal rtype: %ld\n", ELF_R_TYPE(rela->r_info));
+ printf("illegal rtype: %" PRIu64 "\n", ELF_R_TYPE(rela->r_info));
break;
}
@@ -326,9 +368,9 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
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,
+ sect->name, (void *)(uintptr_t)*where,
rtems_rtl_obj_oname (obj));
- printf("ELF_R_TYPE is : %ld\n", ELF_R_TYPE(rela->r_info));
+ printf("ELF_R_TYPE is : %" PRIu64 "\n", ELF_R_TYPE(rela->r_info));
break;
}
target &= WIDTHMASK(12);
@@ -350,6 +392,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
target -= (uintptr_t)where >> 12;
if (checkoverflow(target, 21, raddr, " x 4k", where, off)) {
+ printf("]] %d\n", __LINE__);
return rtems_rtl_elf_rel_failure;
}
@@ -380,6 +423,13 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
return rtems_rtl_elf_rel_failure;
}
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf (
+ "rtl: JUMP26/PC26/CALL: insn=%p where=%p target=%p raddr=%p parsing=%d\n",
+ insn, (void*) where, (void*)(uintptr_t) target, (void*)(uintptr_t) raddr,
+ parsing
+ );
+
target = (intptr_t)target >> 2;
if (((Elf_Sword)target > 0x1FFFFFF) || ((Elf_Sword)target < -0x2000000)) {
@@ -399,9 +449,8 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
return rtems_rtl_elf_rel_failure;
}
- tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
+ tramp_addr = ((Elf_Addr)(uintptr_t) 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;
}
@@ -426,6 +475,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
raddr = (Elf_Addr)symvalue + rela->r_addend;
target = raddr - (uintptr_t)where;
if (checkoverflow(target, 32, raddr, "", where, off)) {
+ printf("]] %d\n", __LINE__);
return rtems_rtl_elf_rel_failure;
}
*where32 = target;
@@ -434,30 +484,31 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
case R_TYPE(TLSDESC):
printf ("rtl: reloc TLSDESC in %s --> %p in %s\n",
- sect->name, (void *)*where,
+ sect->name, (void *)(uintptr_t)*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,
+ sect->name, (void *)(uintptr_t)*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,
+ sect->name, (void *)(uintptr_t)*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,
+ sect->name, (void *)(uintptr_t)*where,
rtems_rtl_obj_oname (obj));
break;
default:
- printf ("rtl: Unsupported relocation type in %s --> %p in %s\n",
- sect->name, (void *)where,
+ printf ("rtl: Unsupported relocation type (%" PRIu64
+ ") in %s --> %p in %s\n",
+ ELF_R_TYPE(rela->r_info), sect->name, (void *)where,
rtems_rtl_obj_oname (obj));
return rtems_rtl_elf_rel_failure;
}
@@ -526,74 +577,16 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
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;
+ uint32_t flags) {
+ return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags);
}
bool
-rtems_rtl_elf_unwind_register (rtems_rtl_obj* obj)
-{
- return true;
+rtems_rtl_elf_unwind_register (rtems_rtl_obj* obj) {
+ return rtems_rtl_elf_unwind_dw2_register (obj);
}
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;
+rtems_rtl_elf_unwind_deregister (rtems_rtl_obj* obj) {
+ return rtems_rtl_elf_unwind_dw2_deregister (obj);
}