From 11323b7da92e59ef61791e6f85d879d1d0a3f1c5 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Tue, 6 Sep 2016 16:20:14 +1000 Subject: libdl: Add ARM C++ relocation record support. Closes #2767 --- cpukit/libdl/include/arch/arm/machine/elf_machdep.h | 3 ++- cpukit/libdl/rtl-mdreloc-arm.c | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/cpukit/libdl/include/arch/arm/machine/elf_machdep.h b/cpukit/libdl/include/arch/arm/machine/elf_machdep.h index 78c88b5af8..8f01d05212 100644 --- a/cpukit/libdl/include/arch/arm/machine/elf_machdep.h +++ b/cpukit/libdl/include/arch/arm/machine/elf_machdep.h @@ -80,7 +80,8 @@ #define R_ARM_ALU_SBREL_19_12 36 #define R_ARM_ALU_SBREL_27_20 37 #define R_ARM_V4BX 40 -#define R_ARM_PREL31 41 +#define R_ARM_TARGET2 41 +#define R_ARM_PREL31 42 #define R_ARM_MOVW_ABS_NC 43 #define R_ARM_MOVT_ABS 44 diff --git a/cpukit/libdl/rtl-mdreloc-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c index 692c8297a8..84d58e3d2d 100644 --- a/cpukit/libdl/rtl-mdreloc-arm.c +++ b/cpukit/libdl/rtl-mdreloc-arm.c @@ -52,6 +52,15 @@ isThumb(Elf_Word symvalue) else return false; } +static inline Elf_SOff +sign_extend31(Elf_Addr val) +{ + if (0x40000000 & val) + return ~((Elf_Addr)0x7fffffff) | (0x7fffffff & val); + else + return 0x7fffffff & val; +} + bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type) { @@ -165,12 +174,16 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, case R_TYPE(REL32): /* word32 (S + A) | T - P */ case R_TYPE(ABS32): /* word32 (S + A) | T */ case R_TYPE(GLOB_DAT): /* word32 (S + A) | T */ + case R_TYPE(PREL31): /* word32 (S + A) | T - P */ + case R_TYPE(TARGET2): /* Equivalent to ABS32 */ if (__predict_true(RELOC_ALIGNED_P(where))) { tmp = *where + symvalue; if (isThumb(symvalue)) tmp |= 1; if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32)) tmp -= (Elf_Addr)where; + else if (ELF_R_TYPE(rel->r_info) == R_TYPE(PREL31)) + tmp -= sign_extend31((Elf_Addr)where); *where = tmp; } else { tmp = load_ptr(where) + symvalue; @@ -178,11 +191,13 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, tmp |= 1; if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32)) tmp -= (Elf_Addr)where; + else if (ELF_R_TYPE(rel->r_info) == R_TYPE(PREL31)) + tmp -= sign_extend31((Elf_Addr)where); store_ptr(where, tmp); } if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: REL32/ABS32/GLOB_DAT %p @ %p in %s", + printf ("rtl: REL32/ABS32/GLOB_DAT/PREL31/TARGET2 %p @ %p in %s", (void *)tmp, where, rtems_rtl_obj_oname (obj)); break; -- cgit v1.2.3