Index: source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp =================================================================== --- source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -21,8 +21,25 @@ #include "Plugins/Process/Utility/ARMDefines.h" #include "Plugins/Process/Utility/ARMUtils.h" -#include "Utility/ARM64_DWARF_Registers.h" +#include "Plugins/Process/Utility/lldb-arm64-register-enums.h" +#define GPR_OFFSET(idx) ((idx)*8) +#define GPR_OFFSET_NAME(reg) 0 +#define FPU_OFFSET(idx) ((idx)*16) +#define FPU_OFFSET_NAME(reg) 0 +#define EXC_OFFSET_NAME(reg) 0 +#define DBG_OFFSET_NAME(reg) 0 +#define DBG_OFFSET_NAME(reg) 0 +#define DEFINE_DBG(re, y) \ + "na", nullptr, 8, 0, lldb::eEncodingUint, lldb::eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, \ + nullptr, nullptr, nullptr, 0 + +#define DECLARE_REGISTER_INFOS_ARM64_STRUCT + +#include "Plugins/Process/Utility/RegisterInfos_arm64.h" + #include "llvm/ADT/STLExtras.h" #include "llvm/Support/MathExtras.h" // for SignExtend32 template function // and CountTrailingZeros_32 function @@ -32,6 +49,13 @@ using namespace lldb; using namespace lldb_private; +static bool LLDBTableGetRegisterInfo(uint32_t reg_num, RegisterInfo ®_info) { + if (reg_num >= llvm::array_lengthof(g_register_infos_arm64_le)) + return false; + reg_info = g_register_infos_arm64_le[reg_num]; + return true; +} + #define No_VFP 0 #define VFPv1 (1u << 1) #define VFPv2 (1u << 2) @@ -168,33 +192,25 @@ if (reg_kind == eRegisterKindGeneric) { switch (reg_num) { case LLDB_REGNUM_GENERIC_PC: - reg_kind = eRegisterKindDWARF; - reg_num = arm64_dwarf::pc; + reg_kind = eRegisterKindLLDB; + reg_num = gpr_pc_arm64; break; case LLDB_REGNUM_GENERIC_SP: - reg_kind = eRegisterKindDWARF; - reg_num = arm64_dwarf::sp; + reg_kind = eRegisterKindLLDB; + reg_num = gpr_sp_arm64; break; case LLDB_REGNUM_GENERIC_FP: - reg_kind = eRegisterKindDWARF; - reg_num = arm64_dwarf::fp; + reg_kind = eRegisterKindLLDB; + reg_num = gpr_fp_arm64; break; case LLDB_REGNUM_GENERIC_RA: - reg_kind = eRegisterKindDWARF; - reg_num = arm64_dwarf::lr; + reg_kind = eRegisterKindLLDB; + reg_num = gpr_lr_arm64; break; case LLDB_REGNUM_GENERIC_FLAGS: - // There is no DWARF register number for the CPSR right now... - reg_info.name = "cpsr"; - reg_info.alt_name = NULL; - reg_info.byte_size = 4; - reg_info.byte_offset = 0; - reg_info.encoding = eEncodingUint; - reg_info.format = eFormatHex; - for (uint32_t i = 0; i < lldb::kNumRegisterKinds; ++i) - reg_info.kinds[reg_kind] = LLDB_INVALID_REGNUM; - reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; - return true; + reg_kind = eRegisterKindLLDB; + reg_num = gpr_cpsr_arm64; + break; default: return false; @@ -201,8 +217,8 @@ } } - if (reg_kind == eRegisterKindDWARF) - return arm64_dwarf::GetRegisterInfo(reg_num, reg_info); + if (reg_kind == eRegisterKindLLDB) + return LLDBTableGetRegisterInfo(reg_num, reg_info); return false; } @@ -430,11 +446,8 @@ // if (m_opcode_cpsr == 0 || m_ignore_conditions == false) // { // m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, - // // use eRegisterKindDWARF is we ever get a cpsr DWARF register - // number // LLDB_REGNUM_GENERIC_FLAGS, - // // use arm64_dwarf::cpsr if we - // ever get one + // gpr_cpsr_arm64 // 0, // &success); // } @@ -447,7 +460,7 @@ uint32_t orig_pc_value = 0; if (auto_advance_pc) { orig_pc_value = - ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::pc, 0, &success); + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success); if (!success) return false; } @@ -459,7 +472,7 @@ if (auto_advance_pc) { uint32_t new_pc_value = - ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::pc, 0, &success); + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success); if (!success) return false; @@ -467,7 +480,7 @@ EmulateInstruction::Context context; context.type = eContextAdvancePC; context.SetNoArgs(); - if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, arm64_dwarf::pc, + if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_pc_arm64, orig_pc_value + 4)) return false; } @@ -478,18 +491,18 @@ bool EmulateInstructionARM64::CreateFunctionEntryUnwind( UnwindPlan &unwind_plan) { unwind_plan.Clear(); - unwind_plan.SetRegisterKind(eRegisterKindDWARF); + unwind_plan.SetRegisterKind(eRegisterKindLLDB); UnwindPlan::RowSP row(new UnwindPlan::Row); // Our previous Call Frame Address is the stack pointer - row->GetCFAValue().SetIsRegisterPlusOffset(arm64_dwarf::sp, 0); + row->GetCFAValue().SetIsRegisterPlusOffset(gpr_sp_arm64, 0); unwind_plan.AppendRow(row); unwind_plan.SetSourceName("EmulateInstructionARM64"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); - unwind_plan.SetReturnAddressRegister(arm64_dwarf::lr); + unwind_plan.SetReturnAddressRegister(gpr_lr_arm64); return true; } @@ -497,7 +510,7 @@ if (m_arch.GetTriple().isAndroid()) return LLDB_INVALID_REGNUM; // Don't use frame pointer on android - return arm64_dwarf::fp; + return gpr_fp_arm64; } bool EmulateInstructionARM64::UsingAArch32() { @@ -664,8 +677,8 @@ return false; // UNDEFINED; } uint64_t result; - uint64_t operand1 = ReadRegisterUnsigned(eRegisterKindDWARF, - arm64_dwarf::x0 + n, 0, &success); + uint64_t operand1 = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success); uint64_t operand2 = imm; bit carry_in; @@ -690,18 +703,17 @@ Context context; RegisterInfo reg_info_Rn; - if (arm64_dwarf::GetRegisterInfo(n, reg_info_Rn)) + if (GetRegisterInfo(eRegisterKindLLDB, n, reg_info_Rn)) context.SetRegisterPlusOffset(reg_info_Rn, imm); - if (n == GetFramePointerRegisterNumber() && d == arm64_dwarf::sp && - !setflags) { + if (n == GetFramePointerRegisterNumber() && d == gpr_sp_arm64 && !setflags) { // 'mov sp, fp' - common epilogue instruction, CFA is now in terms // of the stack pointer, instead of frame pointer. context.type = EmulateInstruction::eContextRestoreStackPointer; - } else if ((n == arm64_dwarf::sp || n == GetFramePointerRegisterNumber()) && - d == arm64_dwarf::sp && !setflags) { + } else if ((n == gpr_sp_arm64 || n == GetFramePointerRegisterNumber()) && + d == gpr_sp_arm64 && !setflags) { context.type = EmulateInstruction::eContextAdjustStackPointer; - } else if (d == GetFramePointerRegisterNumber() && n == arm64_dwarf::sp && + } else if (d == GetFramePointerRegisterNumber() && n == gpr_sp_arm64 && !setflags) { context.type = EmulateInstruction::eContextSetFramePointer; } else { @@ -708,10 +720,9 @@ context.type = EmulateInstruction::eContextImmediate; } - // If setflags && d == arm64_dwarf::sp then d = WZR/XZR. See CMN, CMP - if (!setflags || d != arm64_dwarf::sp) - WriteRegisterUnsigned(context, eRegisterKindDWARF, arm64_dwarf::x0 + d, - result); + // If setflags && d == gpr_sp_arm64 then d = WZR/XZR. See CMN, CMP + if (!setflags || d != gpr_sp_arm64) + WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_x0_arm64 + d, result); return false; } @@ -804,19 +815,18 @@ RegisterInfo reg_info_base; RegisterInfo reg_info_Rt; RegisterInfo reg_info_Rt2; - if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::x0 + n, reg_info_base)) + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base)) return false; if (vector) { - if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::v0 + n, reg_info_Rt)) + if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t, reg_info_Rt)) return false; - if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::v0 + n, reg_info_Rt2)) + if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2, reg_info_Rt2)) return false; } else { - if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::x0 + t, reg_info_Rt)) + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt)) return false; - if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::x0 + t2, - reg_info_Rt2)) + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2, reg_info_Rt2)) return false; } @@ -824,10 +834,10 @@ if (n == 31) { // CheckSPAlignment(); address = - ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::sp, 0, &success); + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success); } else - address = ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, - &success); + address = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success); wb_address = address + idx; if (a_mode != AddrMode_POST) @@ -991,10 +1001,10 @@ if (n == 31) address = - ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::sp, 0, &success); + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success); else - address = ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, - &success); + address = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success); if (!success) return false; @@ -1003,11 +1013,11 @@ address += offset; RegisterInfo reg_info_base; - if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::x0 + n, reg_info_base)) + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base)) return false; RegisterInfo reg_info_Rt; - if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::x0 + t, reg_info_Rt)) + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt)) return false; Context context; @@ -1096,8 +1106,7 @@ switch (branch_type) { case BranchType_CALL: { addr_t x30 = pc + 4; - if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, arm64_dwarf::x30, - x30)) + if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_lr_arm64, x30)) return false; } break; case BranchType_JMP: @@ -1158,8 +1167,8 @@ bool is_zero = Bit32(opcode, 24) == 0; int32_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2); - const uint64_t operand = ReadRegisterUnsigned( - eRegisterKindDWARF, arm64_dwarf::x0 + t, 0, &success); + const uint64_t operand = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success); if (!success) return false; @@ -1194,8 +1203,8 @@ uint32_t bit_val = Bit32(opcode, 24); int64_t offset = llvm::SignExtend64<16>(Bits32(opcode, 18, 5) << 2); - const uint64_t operand = ReadRegisterUnsigned( - eRegisterKindDWARF, arm64_dwarf::x0 + t, 0, &success); + const uint64_t operand = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success); if (!success) return false; Index: unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp =================================================================== --- unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp +++ unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp @@ -14,7 +14,6 @@ #include #include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h" -#include "Utility/ARM64_DWARF_Registers.h" #include "lldb/Core/Address.h" #include "lldb/Core/AddressRange.h" @@ -24,6 +23,7 @@ #include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h" #include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h" +#include "Plugins/Process/Utility/lldb-arm64-register-enums.h" #include "llvm/Support/TargetSelect.h" using namespace lldb; @@ -93,7 +93,7 @@ // CFA=sp +0 row_sp = unwind_plan.GetRowForFunctionOffset(0); EXPECT_EQ(0ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); @@ -100,15 +100,15 @@ // CFA=sp+16 => fp=[CFA-16] lr=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); @@ -115,15 +115,15 @@ // CFA=fp+16 => fp=[CFA-16] lr=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(8); EXPECT_EQ(8ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); @@ -130,15 +130,15 @@ // CFA=sp+16 => fp=[CFA-16] lr=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(16); EXPECT_EQ(16ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); @@ -145,7 +145,7 @@ // CFA=sp +0 => fp= lr= row_sp = unwind_plan.GetRowForFunctionOffset(20); EXPECT_EQ(20ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); } @@ -210,7 +210,7 @@ // 0: CFA=sp +0 => row_sp = unwind_plan.GetRowForFunctionOffset(0); EXPECT_EQ(0ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); @@ -217,14 +217,14 @@ // 4: CFA=sp+48 => x21=[CFA-40] x22=[CFA-48] row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x21, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x21_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-40, regloc.GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x22, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x22_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-48, regloc.GetOffset()); @@ -231,14 +231,14 @@ // 8: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] row_sp = unwind_plan.GetRowForFunctionOffset(8); EXPECT_EQ(8ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x19, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x19_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-24, regloc.GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-32, regloc.GetOffset()); @@ -246,14 +246,14 @@ // fp=[CFA-16] lr=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(12); EXPECT_EQ(12ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); @@ -261,7 +261,7 @@ // fp=[CFA-16] lr=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(16); EXPECT_EQ(16ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); @@ -269,7 +269,7 @@ // fp=[CFA-16] lr=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(28); EXPECT_EQ(28ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset()); @@ -280,10 +280,10 @@ // I'd prefer if these restored registers were cleared entirely instead of set // to IsSame... - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); EXPECT_TRUE(regloc.IsSame()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); EXPECT_TRUE(regloc.IsSame()); // 36: CFA=sp+48 => x19= x20= x21=[CFA-40] x22=[CFA-48] fp= @@ -291,10 +291,10 @@ row_sp = unwind_plan.GetRowForFunctionOffset(36); EXPECT_EQ(36ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x19, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x19_arm64, regloc)); EXPECT_TRUE(regloc.IsSame()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc)); EXPECT_TRUE(regloc.IsSame()); // 40: CFA=sp +0 => x19= x20= x21= x22= fp= @@ -301,14 +301,14 @@ // lr= row_sp = unwind_plan.GetRowForFunctionOffset(40); EXPECT_EQ(40ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x21, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x21_arm64, regloc)); EXPECT_TRUE(regloc.IsSame()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x22, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x22_arm64, regloc)); EXPECT_TRUE(regloc.IsSame()); } @@ -364,45 +364,45 @@ // 0: CFA=sp +0 => row_sp = unwind_plan.GetRowForFunctionOffset(0); EXPECT_EQ(0ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); row_sp = unwind_plan.GetRowForFunctionOffset(32); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); - EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x19, regloc)); - EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc)); - EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x21, regloc)); - EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x22, regloc)); - EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x23, regloc)); - EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x24, regloc)); - EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x25, regloc)); - EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x26, regloc)); - EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x27, regloc)); - EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x28, regloc)); - EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc)); - EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x19_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x21_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x22_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x23_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x24_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x25_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x26_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x27_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x28_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc)); + EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc)); row_sp = unwind_plan.GetRowForFunctionOffset(36); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); row_sp = unwind_plan.GetRowForFunctionOffset(52); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); row_sp = unwind_plan.GetRowForFunctionOffset(56); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); row_sp = unwind_plan.GetRowForFunctionOffset(60); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); } @@ -490,21 +490,183 @@ row_sp = unwind_plan.GetRowForFunctionOffset(36); EXPECT_EQ(28ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-32, regloc.GetOffset()); row_sp = unwind_plan.GetRowForFunctionOffset(40); EXPECT_EQ(28ull, row_sp->GetOffset()); - EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); - EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc)); + EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-32, regloc.GetOffset()); } + +TEST_F(TestArm64InstEmulation, TestRegisterDoubleSpills) { + ArchSpec arch("arm64-apple-ios10", nullptr); + UnwindAssemblyInstEmulation *engine = + static_cast( + UnwindAssemblyInstEmulation::CreateInstance(arch)); + ASSERT_NE(nullptr, engine); + + UnwindPlan::RowSP row_sp; + AddressRange sample_range; + UnwindPlan unwind_plan(eRegisterKindLLDB); + UnwindPlan::Row::RegisterLocation regloc; + + // this file built with clang for iOS arch arm64 optimization -Os + // #include + // double foo(double in) { + // double arr[32]; + // for (int i = 0; i < 32; i++) + // arr[i] = in + i; + // for (int i = 2; i < 30; i++) + // arr[i] = ((((arr[i - 1] * arr[i - 2] * 0.2) + (0.7 * arr[i])) / + // ((((arr[i] * 0.73) + 0.65) * (arr[i - 1] + 0.2)) - ((arr[i + 1] + (arr[i] + // * 0.32) + 0.52) / 0.3) + (0.531 * arr[i - 2]))) + ((arr[i - 1] + 5) / + // ((arr[i + 2] + 0.4) / arr[i])) + (arr[5] * (0.17 + arr[7] * arr[i])) + + // ((i > 5 ? (arr[i - 3]) : arr[i - 1]) * 0.263) + (((arr[i - 2] + arr[i - + // 1]) * 0.3252) + 3.56) - (arr[i + 1] * 0.852311)) * ((arr[i] * 85234.1345) + // + (77342.451324 / (arr[i - 2] + arr[i - 1] - 73425341.33455))) + (arr[i] + // * 875712013.55) - (arr[i - 1] * 0.5555) - ((arr[i] * (arr[i + 1] + + // 17342834.44) / 8688200123.555)) + (arr[i - 2] + 8888.888); + // return arr[16]; + //} + // int main(int argc, char **argv) { printf("%g\n", foo(argc)); } + + // so function foo() uses enough registers that it spills the callee-saved + // floating point registers. + uint8_t data[] = { + // prologue + 0xef, 0x3b, 0xba, 0x6d, // 0: 0x6dba3bef stp d15, d14, [sp, #-0x60]! + 0xed, 0x33, 0x01, 0x6d, // 4: 0x6d0133ed stp d13, d12, [sp, #0x10] + 0xeb, 0x2b, 0x02, 0x6d, // 8: 0x6d022beb stp d11, d10, [sp, #0x20] + 0xe9, 0x23, 0x03, 0x6d, // 12: 0x6d0323e9 stp d9, d8, [sp, #0x30] + 0xfc, 0x6f, 0x04, 0xa9, // 16: 0xa9046ffc stp x28, x27, [sp, #0x40] + 0xfd, 0x7b, 0x05, 0xa9, // 20: 0xa9057bfd stp x29, x30, [sp, #0x50] + 0xfd, 0x43, 0x01, 0x91, // 24: 0x910143fd add x29, sp, #0x50 + 0xff, 0x43, 0x04, 0xd1, // 28: 0xd10443ff sub sp, sp, #0x110 + + // epilogue + 0xbf, 0x43, 0x01, 0xd1, // 32: 0xd10143bf sub sp, x29, #0x50 + 0xfd, 0x7b, 0x45, 0xa9, // 36: 0xa9457bfd ldp x29, x30, [sp, #0x50] + 0xfc, 0x6f, 0x44, 0xa9, // 40: 0xa9446ffc ldp x28, x27, [sp, #0x40] + 0xe9, 0x23, 0x43, 0x6d, // 44: 0x6d4323e9 ldp d9, d8, [sp, #0x30] + 0xeb, 0x2b, 0x42, 0x6d, // 48: 0x6d422beb ldp d11, d10, [sp, #0x20] + 0xed, 0x33, 0x41, 0x6d, // 52: 0x6d4133ed ldp d13, d12, [sp, #0x10] + 0xef, 0x3b, 0xc6, 0x6c, // 56: 0x6cc63bef ldp d15, d14, [sp], #0x60 + 0xc0, 0x03, 0x5f, 0xd6, // 60: 0xd65f03c0 ret + }; + + // UnwindPlan we expect: + // 0: CFA=sp +0 => + // 4: CFA=sp+96 => d14=[CFA-88] d15=[CFA-96] + // 8: CFA=sp+96 => d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 12: CFA=sp+96 => d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80] + // d14=[CFA-88] d15=[CFA-96] + // 16: CFA=sp+96 => d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] + // d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 20: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] d8=[CFA-40] d9=[CFA-48] + // d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] + // d15=[CFA-96] + // 24: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8] + // d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] + // d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 28: CFA=fp+16 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8] + // d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] + // d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 36: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8] + // d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] + // d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 40: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] d8=[CFA-40] d9=[CFA-48] + // d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] + // d15=[CFA-96] + // 44: CFA=sp+96 => d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] + // d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 48: CFA=sp+96 => d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80] + // d14=[CFA-88] d15=[CFA-96] + // 52: CFA=sp+96 => d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + // 56: CFA=sp+96 => d14=[CFA-88] d15=[CFA-96] + // 60: CFA=sp +0 => + + sample_range = AddressRange(0x1000, sizeof(data)); + + EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( + sample_range, data, sizeof(data), unwind_plan)); + + // 28: CFA=fp+16 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8] + // d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] + // d13=[CFA-80] d14=[CFA-88] d15=[CFA-96] + row_sp = unwind_plan.GetRowForFunctionOffset(28); + EXPECT_EQ(28ull, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d15_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-96, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d14_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-88, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d13_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-80, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d12_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-72, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d11_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-64, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d10_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-56, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d9_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-48, regloc.GetOffset()); + + EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d8_arm64, regloc)); + EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); + EXPECT_EQ(-40, regloc.GetOffset()); + + // 60: CFA=sp +0 => + row_sp = unwind_plan.GetRowForFunctionOffset(60); + EXPECT_EQ(60ull, row_sp->GetOffset()); + EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64); + EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); + EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset()); + + if (row_sp->GetRegisterInfo(fpu_d8_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d9_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d10_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d11_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d12_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d13_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d14_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(fpu_d15_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(gpr_x27_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); + if (row_sp->GetRegisterInfo(gpr_x28_arm64, regloc)) + EXPECT_TRUE(regloc.IsSame()); +}