summaryrefslogtreecommitdiffstats
path: root/cpukit/libdl
diff options
context:
space:
mode:
authorKinsey Moore <kinsey.moore@oarcorp.com>2023-01-12 15:45:46 -0600
committerJoel Sherrill <joel@rtems.org>2023-01-20 08:26:35 -0600
commitd3662980d0ae736f8f98b18742bcd2cd8a25e1b7 (patch)
tree48a4825f8ab4a7fecc871ea91935c01f37c92c71 /cpukit/libdl
parentcpukit/libdl: Print the missing AArch64 reloc type (diff)
downloadrtems-d3662980d0ae736f8f98b18742bcd2cd8a25e1b7.tar.bz2
cpukit/libdl: Add AArch64 TLS reloc support
This adds basic TLS relocation support for AArch64 to libdl. This lets loadable modules use TLS symbols hosted in the main binary. This does not allow loadable modules to host their own TLS symbols.
Diffstat (limited to 'cpukit/libdl')
-rw-r--r--cpukit/libdl/rtl-mdreloc-aarch64.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/cpukit/libdl/rtl-mdreloc-aarch64.c b/cpukit/libdl/rtl-mdreloc-aarch64.c
index 4c51d97a78..e44238e636 100644
--- a/cpukit/libdl/rtl-mdreloc-aarch64.c
+++ b/cpukit/libdl/rtl-mdreloc-aarch64.c
@@ -79,6 +79,7 @@ __RCSID("$NetBSD: mdreloc.c,v 1.14 2020/06/16 21:01:30 joerg Exp $");
#include "rtl-error.h"
#include <rtems/rtl/rtl-trace.h>
#include "rtl-unwind-arm.h"
+#include <rtems/score/tls.h>
struct tls_data {
size_t td_tlsindex;
@@ -237,6 +238,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):
@@ -286,6 +288,42 @@ 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: %ld\n", ELF_R_TYPE(rela->r_info));
+ break;
+ }
+
+ if (!parsing) {
+ target = (Elf_Addr)symvalue + rela->r_addend;
+ /* Calculate offset accounting for the DTV */
+ target -= (uintptr_t)_TLS_Data_begin;
+ target += sizeof(TLS_Dynamic_thread_vector);
+
+ 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: