mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 07:15:46 +00:00
Bug 1747783
- Add support for aarch64 to elfhack. r=gsvelto
Differential Revision: https://phabricator.services.mozilla.com/D134764
This commit is contained in:
parent
837162a71b
commit
523b1551b3
@ -109,6 +109,9 @@ class ElfRelHackCode_Section : public ElfSection {
|
|||||||
case EM_ARM:
|
case EM_ARM:
|
||||||
file += "arm";
|
file += "arm";
|
||||||
break;
|
break;
|
||||||
|
case EM_AARCH64:
|
||||||
|
file += "aarch64";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("unsupported architecture");
|
throw std::runtime_error("unsupported architecture");
|
||||||
}
|
}
|
||||||
@ -269,10 +272,13 @@ class ElfRelHackCode_Section : public ElfSection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: sort out which non-aarch64 relocation types should be using
|
||||||
|
// `value` (even though in practice it's either 0 or the same as addend)
|
||||||
class pc32_relocation {
|
class pc32_relocation {
|
||||||
public:
|
public:
|
||||||
Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
|
Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
|
||||||
Elf64_Sxword addend, unsigned int addr) {
|
Elf64_Sxword addend, unsigned int addr,
|
||||||
|
Elf64_Word value) {
|
||||||
return addr + addend - offset - base_addr;
|
return addr + addend - offset - base_addr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -280,7 +286,8 @@ class ElfRelHackCode_Section : public ElfSection {
|
|||||||
class arm_plt32_relocation {
|
class arm_plt32_relocation {
|
||||||
public:
|
public:
|
||||||
Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
|
Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
|
||||||
Elf64_Sxword addend, unsigned int addr) {
|
Elf64_Sxword addend, unsigned int addr,
|
||||||
|
Elf64_Word value) {
|
||||||
// We don't care about sign_extend because the only case where this is
|
// We don't care about sign_extend because the only case where this is
|
||||||
// going to be used only jumps forward.
|
// going to be used only jumps forward.
|
||||||
Elf32_Addr tmp = (Elf32_Addr)(addr - offset - base_addr) >> 2;
|
Elf32_Addr tmp = (Elf32_Addr)(addr - offset - base_addr) >> 2;
|
||||||
@ -292,7 +299,8 @@ class ElfRelHackCode_Section : public ElfSection {
|
|||||||
class arm_thm_jump24_relocation {
|
class arm_thm_jump24_relocation {
|
||||||
public:
|
public:
|
||||||
Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
|
Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
|
||||||
Elf64_Sxword addend, unsigned int addr) {
|
Elf64_Sxword addend, unsigned int addr,
|
||||||
|
Elf64_Word value) {
|
||||||
/* Follows description of b.w and bl instructions as per
|
/* Follows description of b.w and bl instructions as per
|
||||||
ARM Architecture Reference Manual ARM® v7-A and ARM® v7-R edition,
|
ARM Architecture Reference Manual ARM® v7-A and ARM® v7-R edition,
|
||||||
A8.6.16 We limit ourselves to Encoding T4 of b.w and Encoding T1 of bl.
|
A8.6.16 We limit ourselves to Encoding T4 of b.w and Encoding T1 of bl.
|
||||||
@ -345,18 +353,66 @@ class ElfRelHackCode_Section : public ElfSection {
|
|||||||
class gotoff_relocation {
|
class gotoff_relocation {
|
||||||
public:
|
public:
|
||||||
Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
|
Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
|
||||||
Elf64_Sxword addend, unsigned int addr) {
|
Elf64_Sxword addend, unsigned int addr,
|
||||||
|
Elf64_Word value) {
|
||||||
return addr + addend;
|
return addr + addend;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <int start, int end>
|
||||||
|
class abs_lo12_nc_relocation {
|
||||||
|
public:
|
||||||
|
Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
|
||||||
|
Elf64_Sxword addend, unsigned int addr,
|
||||||
|
Elf64_Word value) {
|
||||||
|
// Fill the bits [end:start] of the immediate value in an ADD, LDR or STR
|
||||||
|
// instruction, at bits [21:10].
|
||||||
|
// per ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture
|
||||||
|
// profile C5.6.4, C5.6.83 or C5.6.178 and ELF for the ARM® 64-bit
|
||||||
|
// Architecture (AArch64) 4.6.6, Table 4-9.
|
||||||
|
Elf64_Word mask = (1 << (end + 1)) - 1;
|
||||||
|
return value | (((((addr + addend) & mask) >> start) & 0xfff) << 10);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class adr_prel_pg_hi21_relocation {
|
||||||
|
public:
|
||||||
|
Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
|
||||||
|
Elf64_Sxword addend, unsigned int addr,
|
||||||
|
Elf64_Word value) {
|
||||||
|
// Fill the bits [32:12] of the immediate value in a ADRP instruction,
|
||||||
|
// at bits [23:5]+[30:29].
|
||||||
|
// per ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture
|
||||||
|
// profile C5.6.10 and ELF for the ARM® 64-bit Architecture
|
||||||
|
// (AArch64) 4.6.6, Table 4-9.
|
||||||
|
Elf64_Word imm = ((addr + addend) >> 12) - ((base_addr + offset) >> 12);
|
||||||
|
Elf64_Word immLo = (imm & 0x3) << 29;
|
||||||
|
Elf64_Word immHi = (imm & 0x1ffffc) << 3;
|
||||||
|
return value & 0x9f00001f | immLo | immHi;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class call26_relocation {
|
||||||
|
public:
|
||||||
|
Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
|
||||||
|
Elf64_Sxword addend, unsigned int addr,
|
||||||
|
Elf64_Word value) {
|
||||||
|
// Fill the bits [27:2] of the immediate value in a BL instruction,
|
||||||
|
// at bits [25:0].
|
||||||
|
// per ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture
|
||||||
|
// profile C5.6.26 and ELF for the ARM® 64-bit Architecture
|
||||||
|
// (AArch64) 4.6.6, Table 4-10.
|
||||||
|
return value | (((addr + addend - offset - base_addr) & 0x0ffffffc) >> 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <class relocation_type>
|
template <class relocation_type>
|
||||||
void apply_relocation(ElfSection* the_code, char* base, Elf_Rel* r,
|
void apply_relocation(ElfSection* the_code, char* base, Elf_Rel* r,
|
||||||
unsigned int addr) {
|
unsigned int addr) {
|
||||||
relocation_type relocation;
|
relocation_type relocation;
|
||||||
Elf32_Addr value;
|
Elf32_Addr value;
|
||||||
memcpy(&value, base + r->r_offset, 4);
|
memcpy(&value, base + r->r_offset, 4);
|
||||||
value = relocation(the_code->getAddr(), r->r_offset, value, addr);
|
value = relocation(the_code->getAddr(), r->r_offset, value, addr, value);
|
||||||
memcpy(base + r->r_offset, &value, 4);
|
memcpy(base + r->r_offset, &value, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,9 +420,11 @@ class ElfRelHackCode_Section : public ElfSection {
|
|||||||
void apply_relocation(ElfSection* the_code, char* base, Elf_Rela* r,
|
void apply_relocation(ElfSection* the_code, char* base, Elf_Rela* r,
|
||||||
unsigned int addr) {
|
unsigned int addr) {
|
||||||
relocation_type relocation;
|
relocation_type relocation;
|
||||||
Elf32_Addr value =
|
Elf64_Word value;
|
||||||
relocation(the_code->getAddr(), r->r_offset, r->r_addend, addr);
|
memcpy(&value, base + r->r_offset, 4);
|
||||||
memcpy(base + r->r_offset, &value, 4);
|
Elf32_Addr new_value =
|
||||||
|
relocation(the_code->getAddr(), r->r_offset, r->r_addend, addr, value);
|
||||||
|
memcpy(base + r->r_offset, &new_value, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Rel_Type>
|
template <typename Rel_Type>
|
||||||
@ -429,6 +487,7 @@ class ElfRelHackCode_Section : public ElfSection {
|
|||||||
case REL(386, GOTPC):
|
case REL(386, GOTPC):
|
||||||
case REL(ARM, GOTPC):
|
case REL(ARM, GOTPC):
|
||||||
case REL(ARM, REL32):
|
case REL(ARM, REL32):
|
||||||
|
case REL(AARCH64, PREL32):
|
||||||
apply_relocation<pc32_relocation>(the_code, buf, &*r, addr);
|
apply_relocation<pc32_relocation>(the_code, buf, &*r, addr);
|
||||||
break;
|
break;
|
||||||
case REL(ARM, CALL):
|
case REL(ARM, CALL):
|
||||||
@ -444,6 +503,25 @@ class ElfRelHackCode_Section : public ElfSection {
|
|||||||
case REL(ARM, GOTOFF):
|
case REL(ARM, GOTOFF):
|
||||||
apply_relocation<gotoff_relocation>(the_code, buf, &*r, addr);
|
apply_relocation<gotoff_relocation>(the_code, buf, &*r, addr);
|
||||||
break;
|
break;
|
||||||
|
case REL(AARCH64, ADD_ABS_LO12_NC):
|
||||||
|
apply_relocation<abs_lo12_nc_relocation<0, 11>>(the_code, buf, &*r,
|
||||||
|
addr);
|
||||||
|
break;
|
||||||
|
case REL(AARCH64, ADR_PREL_PG_HI21):
|
||||||
|
apply_relocation<adr_prel_pg_hi21_relocation>(the_code, buf, &*r,
|
||||||
|
addr);
|
||||||
|
break;
|
||||||
|
case REL(AARCH64, LDST32_ABS_LO12_NC):
|
||||||
|
apply_relocation<abs_lo12_nc_relocation<2, 11>>(the_code, buf, &*r,
|
||||||
|
addr);
|
||||||
|
break;
|
||||||
|
case REL(AARCH64, LDST64_ABS_LO12_NC):
|
||||||
|
apply_relocation<abs_lo12_nc_relocation<3, 11>>(the_code, buf, &*r,
|
||||||
|
addr);
|
||||||
|
break;
|
||||||
|
case REL(AARCH64, CALL26):
|
||||||
|
apply_relocation<call26_relocation>(the_code, buf, &*r, addr);
|
||||||
|
break;
|
||||||
case REL(ARM, V4BX):
|
case REL(ARM, V4BX):
|
||||||
// Ignore R_ARM_V4BX relocations
|
// Ignore R_ARM_V4BX relocations
|
||||||
break;
|
break;
|
||||||
@ -1233,6 +1311,12 @@ void do_file(const char* name, bool backup = false, bool force = false) {
|
|||||||
exit = do_relocation_section<Elf_Rel>(&elf, R_ARM_RELATIVE, R_ARM_ABS32,
|
exit = do_relocation_section<Elf_Rel>(&elf, R_ARM_RELATIVE, R_ARM_ABS32,
|
||||||
force);
|
force);
|
||||||
break;
|
break;
|
||||||
|
case EM_AARCH64:
|
||||||
|
exit = do_relocation_section<Elf_Rela>(&elf, R_AARCH64_RELATIVE,
|
||||||
|
R_AARCH64_ABS64, force);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("unsupported architecture");
|
||||||
}
|
}
|
||||||
if (exit == 0) {
|
if (exit == 0) {
|
||||||
if (!force && (elf.getSize() >= size)) {
|
if (!force && (elf.getSize() >= size)) {
|
||||||
|
@ -1256,7 +1256,7 @@ with only_when("--enable-compile-environment"):
|
|||||||
return (
|
return (
|
||||||
target.kernel == "Linux"
|
target.kernel == "Linux"
|
||||||
and host.kernel == "Linux"
|
and host.kernel == "Linux"
|
||||||
and target.cpu in ("arm", "x86", "x86_64")
|
and target.cpu in ("arm", "aarch64", "x86", "x86_64")
|
||||||
)
|
)
|
||||||
|
|
||||||
@depends("--enable-release", enable_linker)
|
@depends("--enable-release", enable_linker)
|
||||||
|
Loading…
Reference in New Issue
Block a user