8c6b1ac71e
Also include some minor fixes for gcc 5.1.1 Signed-off-by: Peter Jones <pjones@redhat.com>
114 lines
3.2 KiB
Diff
114 lines
3.2 KiB
Diff
From c0f529ea679bdf48cbe1c4b3dd92fb552456a1fe Mon Sep 17 00:00:00 2001
|
|
From: Leif Lindholm <leif.lindholm@linaro.org>
|
|
Date: Tue, 3 Feb 2015 21:16:36 +0000
|
|
Subject: [PATCH 281/506] arm: implement additional relocations generated by
|
|
gcc 4.9 at -O3
|
|
|
|
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(+)
|
|
|
|
diff --git a/grub-core/kern/arm/dl.c b/grub-core/kern/arm/dl.c
|
|
index 57cac2e..5cbd65e 100644
|
|
--- a/grub-core/kern/arm/dl.c
|
|
+++ b/grub-core/kern/arm/dl.c
|
|
@@ -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 */
|
|
diff --git a/grub-core/kern/arm/dl_helper.c b/grub-core/kern/arm/dl_helper.c
|
|
index 5721939..8a72632 100644
|
|
--- a/grub-core/kern/arm/dl_helper.c
|
|
+++ b/grub-core/kern/arm/dl_helper.c
|
|
@@ -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);
|
|
+}
|
|
diff --git a/include/grub/arm/reloc.h b/include/grub/arm/reloc.h
|
|
index b938037..ae92e21 100644
|
|
--- a/include/grub/arm/reloc.h
|
|
+++ b/include/grub/arm/reloc.h
|
|
@@ -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
|
|
--
|
|
2.4.3
|
|
|