arm64: Add support for relocations needed for linaro gcc
This commit is contained in:
parent
b6a03dfd32
commit
605eecc985
6 changed files with 107 additions and 1 deletions
|
@ -132,6 +132,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
|
||||||
*abs_place = (grub_uint64_t) sym_addr;
|
*abs_place = (grub_uint64_t) sym_addr;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case R_AARCH64_ADD_ABS_LO12_NC:
|
||||||
|
grub_arm64_set_abs_lo12 (place, sym_addr);
|
||||||
|
break;
|
||||||
|
case R_AARCH64_LDST64_ABS_LO12_NC:
|
||||||
|
grub_arm64_set_abs_lo12_ldst64 (place, sym_addr);
|
||||||
|
break;
|
||||||
case R_AARCH64_CALL26:
|
case R_AARCH64_CALL26:
|
||||||
case R_AARCH64_JUMP26:
|
case R_AARCH64_JUMP26:
|
||||||
{
|
{
|
||||||
|
@ -154,6 +160,18 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
|
||||||
grub_arm64_set_xxxx26_offset (place, offset);
|
grub_arm64_set_xxxx26_offset (place, offset);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case R_AARCH64_ADR_PREL_PG_HI21:
|
||||||
|
{
|
||||||
|
grub_int64_t offset = (sym_addr & ~0xfffULL) - (((grub_uint64_t) place) & ~0xfffULL);
|
||||||
|
|
||||||
|
if (!grub_arm64_check_hi21_signed (offset))
|
||||||
|
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||||
|
"HI21 out of range");
|
||||||
|
|
||||||
|
grub_arm64_set_hi21 (place, offset);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
N_("relocation 0x%x is not implemented yet"),
|
N_("relocation 0x%x is not implemented yet"),
|
||||||
|
|
|
@ -53,3 +53,43 @@ grub_arm64_set_xxxx26_offset (grub_uint32_t *place, grub_int64_t offset)
|
||||||
*place &= insmask;
|
*place &= insmask;
|
||||||
*place |= grub_cpu_to_le32 (offset >> 2) & ~insmask;
|
*place |= grub_cpu_to_le32 (offset >> 2) & ~insmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
grub_arm64_check_hi21_signed (grub_int64_t offset)
|
||||||
|
{
|
||||||
|
if (offset != (grub_int64_t)(grub_int32_t)offset)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_arm64_set_hi21 (grub_uint32_t *place, grub_int64_t offset)
|
||||||
|
{
|
||||||
|
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0x9f00001f);
|
||||||
|
grub_uint32_t val;
|
||||||
|
|
||||||
|
offset >>= 12;
|
||||||
|
|
||||||
|
val = ((offset & 3) << 29) | (((offset >> 2) & 0x7ffff) << 5);
|
||||||
|
|
||||||
|
*place &= insmask;
|
||||||
|
*place |= grub_cpu_to_le32 (val) & ~insmask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_arm64_set_abs_lo12 (grub_uint32_t *place, grub_int64_t target)
|
||||||
|
{
|
||||||
|
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff);
|
||||||
|
|
||||||
|
*place &= insmask;
|
||||||
|
*place |= grub_cpu_to_le32 (target << 10) & ~insmask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_arm64_set_abs_lo12_ldst64 (grub_uint32_t *place, grub_int64_t target)
|
||||||
|
{
|
||||||
|
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfff803ff);
|
||||||
|
|
||||||
|
*place &= insmask;
|
||||||
|
*place |= grub_cpu_to_le32 (target << 7) & ~insmask;
|
||||||
|
}
|
||||||
|
|
|
@ -22,5 +22,13 @@
|
||||||
int grub_arm_64_check_xxxx26_offset (grub_int64_t offset);
|
int grub_arm_64_check_xxxx26_offset (grub_int64_t offset);
|
||||||
void
|
void
|
||||||
grub_arm64_set_xxxx26_offset (grub_uint32_t *place, grub_int64_t offset);
|
grub_arm64_set_xxxx26_offset (grub_uint32_t *place, grub_int64_t offset);
|
||||||
|
int
|
||||||
|
grub_arm64_check_hi21_signed (grub_int64_t offset);
|
||||||
|
void
|
||||||
|
grub_arm64_set_hi21 (grub_uint32_t *place, grub_int64_t offset);
|
||||||
|
void
|
||||||
|
grub_arm64_set_abs_lo12 (grub_uint32_t *place, grub_int64_t target);
|
||||||
|
void
|
||||||
|
grub_arm64_set_abs_lo12_ldst64 (grub_uint32_t *place, grub_int64_t target);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2068,6 +2068,9 @@ typedef Elf32_Addr Elf32_Conflict;
|
||||||
#define R_AARCH64_NONE 0 /* No relocation. */
|
#define R_AARCH64_NONE 0 /* No relocation. */
|
||||||
#define R_AARCH64_ABS64 257 /* Direct 64 bit. */
|
#define R_AARCH64_ABS64 257 /* Direct 64 bit. */
|
||||||
#define R_AARCH64_ABS32 258 /* Direct 32 bit. */
|
#define R_AARCH64_ABS32 258 /* Direct 32 bit. */
|
||||||
|
#define R_AARCH64_ADR_PREL_PG_HI21 275
|
||||||
|
#define R_AARCH64_ADD_ABS_LO12_NC 277
|
||||||
|
#define R_AARCH64_LDST64_ABS_LO12_NC 286
|
||||||
#define R_AARCH64_JUMP26 282 /* 26-bit relative. */
|
#define R_AARCH64_JUMP26 282 /* 26-bit relative. */
|
||||||
#define R_AARCH64_CALL26 283 /* 26-bit relative. */
|
#define R_AARCH64_CALL26 283 /* 26-bit relative. */
|
||||||
#define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */
|
#define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */
|
||||||
|
|
|
@ -836,6 +836,14 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
|
||||||
*target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
|
*target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case R_AARCH64_ADD_ABS_LO12_NC:
|
||||||
|
grub_arm64_set_abs_lo12 ((grub_uint32_t *) target,
|
||||||
|
sym_addr);
|
||||||
|
break;
|
||||||
|
case R_AARCH64_LDST64_ABS_LO12_NC:
|
||||||
|
grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) target,
|
||||||
|
sym_addr);
|
||||||
|
break;
|
||||||
case R_AARCH64_JUMP26:
|
case R_AARCH64_JUMP26:
|
||||||
case R_AARCH64_CALL26:
|
case R_AARCH64_CALL26:
|
||||||
{
|
{
|
||||||
|
@ -848,6 +856,17 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
|
||||||
sym_addr);
|
sym_addr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case R_AARCH64_ADR_PREL_PG_HI21:
|
||||||
|
{
|
||||||
|
sym_addr &= ~0xfffULL;
|
||||||
|
sym_addr -= (offset + SUFFIX (entry_point)) & ~0xfffULL;
|
||||||
|
if (!grub_arm64_check_hi21_signed (sym_addr))
|
||||||
|
grub_util_error ("%s", "CALL26 Relocation out of range");
|
||||||
|
|
||||||
|
grub_arm64_set_hi21((grub_uint32_t *)target,
|
||||||
|
sym_addr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
grub_util_error (_("relocation 0x%x is not implemented yet"),
|
grub_util_error (_("relocation 0x%x is not implemented yet"),
|
||||||
(unsigned int) ELF_R_TYPE (info));
|
(unsigned int) ELF_R_TYPE (info));
|
||||||
|
@ -1200,6 +1219,15 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out,
|
||||||
case R_AARCH64_CALL26:
|
case R_AARCH64_CALL26:
|
||||||
case R_AARCH64_JUMP26:
|
case R_AARCH64_JUMP26:
|
||||||
break;
|
break;
|
||||||
|
/* Page-relative relocations do not require fixup entries. */
|
||||||
|
case R_AARCH64_ADR_PREL_PG_HI21:
|
||||||
|
/* We page-align the whole kernel, so no need
|
||||||
|
for fixup entries.
|
||||||
|
*/
|
||||||
|
case R_AARCH64_ADD_ABS_LO12_NC:
|
||||||
|
case R_AARCH64_LDST64_ABS_LO12_NC:
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
grub_util_error (_("relocation 0x%x is not implemented yet"),
|
grub_util_error (_("relocation 0x%x is not implemented yet"),
|
||||||
(unsigned int) ELF_R_TYPE (info));
|
(unsigned int) ELF_R_TYPE (info));
|
||||||
|
@ -1343,6 +1371,9 @@ SUFFIX (locate_sections) (const char *kernel_path,
|
||||||
Elf_Shdr *s;
|
Elf_Shdr *s;
|
||||||
|
|
||||||
*all_align = 1;
|
*all_align = 1;
|
||||||
|
/* Page-aligning simplifies relocation handling. */
|
||||||
|
if (image_target->elf_target == EM_AARCH64)
|
||||||
|
*all_align = 4096;
|
||||||
|
|
||||||
section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
|
section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
|
||||||
memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
|
memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
|
||||||
|
|
|
@ -107,7 +107,13 @@ struct grub_module_verifier_arch archs[] = {
|
||||||
R_AARCH64_CALL26,
|
R_AARCH64_CALL26,
|
||||||
R_AARCH64_JUMP26,
|
R_AARCH64_JUMP26,
|
||||||
-1
|
-1
|
||||||
} },
|
}, (int[]){
|
||||||
|
R_AARCH64_ADR_PREL_PG_HI21,
|
||||||
|
R_AARCH64_ADD_ABS_LO12_NC,
|
||||||
|
R_AARCH64_LDST64_ABS_LO12_NC,
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue