ia64: Add support for R_IA64_GPREL64I.

Recent GCC generates those relocations, so we need to support them.
This commit is contained in:
Vladimir Serbinenko 2017-01-31 12:39:01 +01:00
parent 255b9e0bea
commit a134ef1ab9
5 changed files with 45 additions and 0 deletions

View file

@ -104,6 +104,9 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
case R_IA64_PCREL64LSB: case R_IA64_PCREL64LSB:
*(grub_uint64_t *) addr += value - addr; *(grub_uint64_t *) addr += value - addr;
break; break;
case R_IA64_GPREL64I:
grub_ia64_set_immu64 (addr, value - (grub_addr_t) mod->base);
break;
case R_IA64_GPREL22: case R_IA64_GPREL22:
if ((value - (grub_addr_t) mod->base) & ~MASK20) if ((value - (grub_addr_t) mod->base) & ~MASK20)
return grub_error (GRUB_ERR_BAD_MODULE, return grub_error (GRUB_ERR_BAD_MODULE,

View file

@ -30,6 +30,40 @@
#define MASK20 ((1 << 20) - 1) #define MASK20 ((1 << 20) - 1)
#define MASK3 (~(grub_addr_t) 3) #define MASK3 (~(grub_addr_t) 3)
void
grub_ia64_set_immu64 (grub_addr_t addr, grub_uint64_t val)
{
/* Copied from binutils. */
grub_uint64_t *ptr = ((grub_uint64_t *) (addr & MASK3));
grub_uint64_t t0, t1;
t0 = grub_le_to_cpu64 (ptr[0]);
t1 = grub_le_to_cpu64 (ptr[1]);
/* tmpl/s: bits 0.. 5 in t0
slot 0: bits 5..45 in t0
slot 1: bits 46..63 in t0, bits 0..22 in t1
slot 2: bits 23..63 in t1 */
/* First, clear the bits that form the 64 bit constant. */
t0 &= ~(0x3ffffLL << 46);
t1 &= ~(0x7fffffLL
| (( (0x07fLL << 13) | (0x1ffLL << 27)
| (0x01fLL << 22) | (0x001LL << 21)
| (0x001LL << 36)) << 23));
t0 |= ((val >> 22) & 0x03ffffLL) << 46; /* 18 lsbs of imm41 */
t1 |= ((val >> 40) & 0x7fffffLL) << 0; /* 23 msbs of imm41 */
t1 |= ( (((val >> 0) & 0x07f) << 13) /* imm7b */
| (((val >> 7) & 0x1ff) << 27) /* imm9d */
| (((val >> 16) & 0x01f) << 22) /* imm5c */
| (((val >> 21) & 0x001) << 21) /* ic */
| (((val >> 63) & 0x001) << 36)) << 23; /* i */
ptr[0] = t0;
ptr[1] = t1;
}
void void
grub_ia64_add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value) grub_ia64_add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value)
{ {

View file

@ -26,6 +26,8 @@ grub_ia64_add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value);
void void
grub_ia64_add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value); grub_ia64_add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value);
void void
grub_ia64_set_immu64 (grub_addr_t addr, grub_uint64_t value);
void
grub_ia64_make_trampoline (struct grub_ia64_trampoline *tr, grub_uint64_t addr); grub_ia64_make_trampoline (struct grub_ia64_trampoline *tr, grub_uint64_t addr);
struct grub_ia64_trampoline struct grub_ia64_trampoline

View file

@ -920,6 +920,10 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
grub_ia64_add_value_to_slot_21 ((grub_addr_t) target, grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
addend + sym_addr); addend + sym_addr);
break; break;
case R_IA64_GPREL64I:
grub_ia64_set_immu64 ((grub_addr_t) target,
addend + sym_addr);
break;
case R_IA64_PCREL64LSB: case R_IA64_PCREL64LSB:
*target = grub_host_to_target64 (grub_target_to_host64 (*target) *target = grub_host_to_target64 (grub_target_to_host64 (*target)
+ addend + sym_addr + addend + sym_addr
@ -1286,6 +1290,7 @@ translate_relocation_pe (struct translate_context *ctx,
case R_IA64_LTOFF22X: case R_IA64_LTOFF22X:
case R_IA64_LTOFF22: case R_IA64_LTOFF22:
case R_IA64_GPREL22: case R_IA64_GPREL22:
case R_IA64_GPREL64I:
case R_IA64_SEGREL64LSB: case R_IA64_SEGREL64LSB:
break; break;

View file

@ -60,6 +60,7 @@ struct grub_module_verifier_arch archs[] = {
R_IA64_PCREL64LSB, R_IA64_PCREL64LSB,
R_IA64_LTOFF22X, R_IA64_LTOFF22X,
R_IA64_LTOFF22, R_IA64_LTOFF22,
R_IA64_GPREL64I,
R_IA64_LTOFF_FPTR22, R_IA64_LTOFF_FPTR22,
R_IA64_LDXMOV, R_IA64_LDXMOV,
-1 -1