Fix thumb compilation with clang.

According to EABI only STT_FUNC has convention of lowest bit indicating
execution mode. R_THM_{JUMP,CALL}* relocations are assumed to be pointing
to thumb mode unless they use STT_FUNC.
This commit is contained in:
Vladimir Serbinenko 2017-02-02 00:59:49 +01:00
parent 08438d783f
commit 42e24b6006
2 changed files with 11 additions and 0 deletions

View file

@ -173,6 +173,8 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
sym_addr += grub_arm_thm_call_get_offset ((grub_uint16_t *) target); sym_addr += grub_arm_thm_call_get_offset ((grub_uint16_t *) target);
grub_dprintf ("dl", " sym_addr = 0x%08x\n", sym_addr); grub_dprintf ("dl", " sym_addr = 0x%08x\n", sym_addr);
if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
sym_addr |= 1;
offset = sym_addr - (grub_uint32_t) target; offset = sym_addr - (grub_uint32_t) target;
@ -227,6 +229,9 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
sym_addr += grub_arm_thm_jump19_get_offset ((grub_uint16_t *) target); sym_addr += grub_arm_thm_jump19_get_offset ((grub_uint16_t *) target);
if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
sym_addr |= 1;
offset = sym_addr - (grub_uint32_t) target; offset = sym_addr - (grub_uint32_t) target;
if (!grub_arm_thm_jump19_check_offset (offset) if (!grub_arm_thm_jump19_check_offset (offset)

View file

@ -1079,10 +1079,16 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
case R_ARM_THM_JUMP19: case R_ARM_THM_JUMP19:
{ {
grub_err_t err; grub_err_t err;
Elf_Sym *sym;
grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
(unsigned long) ((char *) target (unsigned long) ((char *) target
- (char *) e), - (char *) e),
sym_addr); sym_addr);
sym = (Elf_Sym *) ((char *) e
+ grub_target_to_host (symtab_section->sh_offset)
+ ELF_R_SYM (info) * grub_target_to_host (symtab_section->sh_entsize));
if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
sym_addr |= 1;
if (!(sym_addr & 1)) if (!(sym_addr & 1))
{ {
grub_uint32_t tr_addr; grub_uint32_t tr_addr;