From 701e8b2d63159105a2e914b4dd83de508f6b9cc7 Mon Sep 17 00:00:00 2001 From: Kinsey Moore Date: Tue, 17 Sep 2024 14:43:23 -0500 Subject: [PATCH] cpukit/libdl/arm: Obey instruction encoding requirements for Thumb BLX Calls from Thumb code into ARM code require the use of a BLX instruction and an optional offset prefix instruction. The BLX instruction encoding requires that the least significant bit be 0 in all cases while the BL instruction for Thumb-to-Thumb calls includes that bit as part of the offset. This ensures that bit 0 of the BLX is set to 0 as required by the instruction encoding specification. --- cpukit/libdl/rtl-mdreloc-arm.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/cpukit/libdl/rtl-mdreloc-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c index 16efbe79da..a02916ebd8 100644 --- a/cpukit/libdl/rtl-mdreloc-arm.c +++ b/cpukit/libdl/rtl-mdreloc-arm.c @@ -470,14 +470,21 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj, } if (!parsing) { + uint16_t bl_tmp; + sign = (tmp >> 24) & 1; *(uint16_t *)where = (uint16_t)((upper_insn & 0xf800) | (sign << 10) | ((tmp >> 12) & 0x3ff)); - *((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0xd000)| - ((sign ^ (~(tmp >> 23) & 1)) << 13) | - ((sign ^ (~(tmp >> 22) & 1)) << 11) | - ((tmp >> 1) & 0x7ff)); + bl_tmp = (uint16_t)((lower_insn & 0xd000)| + ((sign ^ (~(tmp >> 23) & 1)) << 13) | + ((sign ^ (~(tmp >> 22) & 1)) << 11) | + ((tmp >> 1) & 0x7ff)); + /* Thumb jumps to ARM mode must have 0 in the LSB of the BLX */ + if ((bl_tmp & 0xf000) == 0xe000) { + bl_tmp &= 0xfffe; + } + *((uint16_t *)where + 1) = bl_tmp; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)){ printf ("rtl: THM_CALL/JUMP24 %p @ %p in %s\n",