ARM64: Add sign extended 21-bit ADR support

This commit is contained in:
Katy Coe
2019-10-27 22:34:32 +01:00
parent adb26aef9b
commit 3abf5a9409

View File

@@ -29,6 +29,22 @@ namespace Il2CppInspector
return (reg, page + addend); return (reg, page + addend);
} }
// https://static.docs.arm.com/100878/0100/fundamentals_of_armv8_a_100878_0100_en.pdf states:
// Unlike ARMv7-A, there is no implied offset of 4 or 8 bytes
private (uint reg, ulong addr)? getAdr(uint inst, ulong pc) {
if (inst.Bits(24, 5) != 0b10000 || inst.Bits(31, 1) != 0)
return null;
ulong imm = (inst.Bits(5, 19) << 2) + inst.Bits(29, 2);
// Sign extend the 21-bit number to 64 bits
imm = (imm & (1 << 20)) == 0 ? imm : imm | unchecked((ulong) -(1 << 21));
var reg = inst.Bits(0, 5);
return (reg, pc + imm);
}
private (uint reg_n, uint reg_d, uint imm)? getAdd64(uint inst) { private (uint reg_n, uint reg_d, uint imm)? getAdd64(uint inst) {
if (inst.Bits(22, 10) != 0b_1001_0001_00) if (inst.Bits(22, 10) != 0b_1001_0001_00)
return null; return null;
@@ -70,6 +86,13 @@ namespace Il2CppInspector
regs.Add(reg, page); regs.Add(reg, page);
} }
if (getAdr(inst, pc) is (uint reg_adr, ulong addr)) {
if (regs.ContainsKey(reg_adr))
regs[reg_adr] = addr;
else
regs.Add(reg_adr, addr);
}
// Is it an ADD Xm, Xn, #offset? // Is it an ADD Xm, Xn, #offset?
if (getAdd64(inst) is (uint reg_n, uint reg_d, uint imm)) { if (getAdd64(inst) is (uint reg_n, uint reg_d, uint imm)) {
// We are only interested in registers that have already had an ADRP, and the ADD must be to itself // We are only interested in registers that have already had an ADRP, and the ADD must be to itself