Fix thumb compilation with clang.
authorVladimir Serbinenko <phcoder@gmail.com>
Wed, 1 Feb 2017 23:59:49 +0000 (00:59 +0100)
committerVladimir Serbinenko <phcoder@gmail.com>
Wed, 1 Feb 2017 23:59:49 +0000 (00:59 +0100)
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.

grub-core/kern/arm/dl.c
util/grub-mkimagexx.c

index fe0abf9..eab9d17 100644 (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);
 
            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;
 
@@ -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);
 
+           if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
+             sym_addr |= 1;
+
            offset = sym_addr - (grub_uint32_t) target;
 
            if (!grub_arm_thm_jump19_check_offset (offset)
index 32be4bf..f8faae8 100644 (file)
@@ -1079,10 +1079,16 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
                   case R_ARM_THM_JUMP19:
                     {
                       grub_err_t err;
+                      Elf_Sym *sym;
                       grub_util_info ("  THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
                                       (unsigned long) ((char *) target
                                                        - (char *) e),
                                       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))
                         {
                           grub_uint32_t tr_addr;