@@ -205,6 +205,21 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
*/
case R_ARM_V4BX:
break;
+ case R_ARM_THM_MOVW_ABS_NC:
+ case R_ARM_THM_MOVT_ABS:
+ {
+ grub_uint32_t offset;
+ offset = grub_arm_thm_movw_movt_get_value((grub_uint16_t *) target);
+ offset += sym_addr;
+
+ if (ELF_R_TYPE (rel->r_info) == R_ARM_THM_MOVT_ABS)
+ offset >>= 16;
+ else
+ offset &= 0xffff;
+
+ grub_arm_thm_movw_movt_set_value((grub_uint16_t *) target, offset);
+ }
+ break;
case R_ARM_THM_JUMP19:
{
/* Thumb instructions can be 16-bit aligned */
@@ -25,6 +25,20 @@
#include <grub/i18n.h>
#include <grub/arm/reloc.h>
+static inline grub_uint32_t
+thumb_get_instruction_word(grub_uint16_t *target)
+{
+ /* Extract instruction word in alignment-safe manner */
+ return grub_le_to_cpu16 ((*target)) << 16 | grub_le_to_cpu16 (*(target + 1));
+}
+
+static inline void
+thumb_set_instruction_word(grub_uint16_t *target, grub_uint32_t insword)
+{
+ *target = grub_cpu_to_le16 (insword >> 16);
+ *(target + 1) = grub_cpu_to_le16 (insword & 0xffff);
+}
+
/*
* R_ARM_ABS32
*
@@ -214,3 +228,28 @@ grub_arm_jump24_set_offset (grub_uint32_t *target,
*target = grub_cpu_to_le32 (insword);
}
+
+grub_uint16_t
+grub_arm_thm_movw_movt_get_value (grub_uint16_t *target)
+{
+ grub_uint32_t insword;
+
+ insword = thumb_get_instruction_word (target);
+
+ return ((insword & 0xf0000) >> 4) | ((insword & 0x04000000) >> 15) | \
+ ((insword & 0x7000) >> 4) | (insword & 0xff);
+}
+
+void
+grub_arm_thm_movw_movt_set_value (grub_uint16_t *target, grub_uint16_t value)
+{
+ grub_uint32_t insword;
+
+ insword = thumb_get_instruction_word (target);
+ insword &= 0xfbf08f00;
+
+ insword |= ((value & 0xf000) << 4) | ((value & 0x0800) << 15) | \
+ ((value & 0x0700) << 4) | (value & 0xff);
+
+ thumb_set_instruction_word (target, insword);
+}
@@ -43,4 +43,9 @@ void
grub_arm_jump24_set_offset (grub_uint32_t *target,
grub_int32_t offset);
+grub_uint16_t
+grub_arm_thm_movw_movt_get_value (grub_uint16_t *target);
+void
+grub_arm_thm_movw_movt_set_value (grub_uint16_t *target, grub_uint16_t value);
+
#endif
GCC 4.9 also generates R_ARM_THM_MOVW_ABS_NC and R_ARM_THM_MOVT_ABS, as an alternative to ABS32. Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org> --- grub-core/kern/arm/dl.c | 15 +++++++++++++++ grub-core/kern/arm/dl_helper.c | 39 +++++++++++++++++++++++++++++++++++++++ include/grub/arm/reloc.h | 5 +++++ 3 files changed, 59 insertions(+)