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>
This commit is contained in:
parent
016875dd52
commit
c0f529ea67
3 changed files with 59 additions and 0 deletions
|
@ -205,6 +205,21 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
|
||||||
*/
|
*/
|
||||||
case R_ARM_V4BX:
|
case R_ARM_V4BX:
|
||||||
break;
|
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:
|
case R_ARM_THM_JUMP19:
|
||||||
{
|
{
|
||||||
/* Thumb instructions can be 16-bit aligned */
|
/* Thumb instructions can be 16-bit aligned */
|
||||||
|
|
|
@ -25,6 +25,20 @@
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/arm/reloc.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
|
* R_ARM_ABS32
|
||||||
*
|
*
|
||||||
|
@ -214,3 +228,28 @@ grub_arm_jump24_set_offset (grub_uint32_t *target,
|
||||||
|
|
||||||
*target = grub_cpu_to_le32 (insword);
|
*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_arm_jump24_set_offset (grub_uint32_t *target,
|
||||||
grub_int32_t offset);
|
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
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue