summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2016-09-06 16:20:14 +1000
committerChris Johns <chrisj@rtems.org>2016-09-08 16:41:59 +1000
commit11323b7da92e59ef61791e6f85d879d1d0a3f1c5 (patch)
tree64d46f64143232ef3dfdc2910f849d5c599f1942
parentstackchk: Fix stack checker thread initialization (diff)
downloadrtems-11323b7da92e59ef61791e6f85d879d1d0a3f1c5.tar.bz2
libdl: Add ARM C++ relocation record support.
Closes #2767
-rw-r--r--cpukit/libdl/include/arch/arm/machine/elf_machdep.h3
-rw-r--r--cpukit/libdl/rtl-mdreloc-arm.c17
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;