[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] arm: implement additional relocations generated by gcc 4.9 a
From: |
Vladimir 'φ-coder/phcoder' Serbinenko |
Subject: |
Re: [PATCH] arm: implement additional relocations generated by gcc 4.9 at -O3 |
Date: |
Tue, 03 Feb 2015 23:11:44 +0100 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Icedove/31.4.0 |
Go ahead
On 03.02.2015 22:30, Leif Lindholm wrote:
> 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 <address@hidden>
> ---
> 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
>
signature.asc
Description: OpenPGP digital signature