1 //===-- RegisterContextDarwin_arm64.cpp ---------------------------*- C++
4 // The LLVM Compiler Infrastructure
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
9 //===----------------------------------------------------------------------===//
11 #include "RegisterContextDarwin_arm64.h"
12 #include "RegisterContextDarwinConstants.h"
15 // Other libraries and framework includes
16 #include "lldb/Core/RegisterValue.h"
17 #include "lldb/Core/Scalar.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/Thread.h"
20 #include "lldb/Utility/DataBufferHeap.h"
21 #include "lldb/Utility/DataExtractor.h"
22 #include "lldb/Utility/Endian.h"
23 #include "lldb/Utility/Log.h"
24 #include "llvm/ADT/STLExtras.h"
25 #include "llvm/Support/Compiler.h"
27 #include "Plugins/Process/Utility/InstructionUtils.h"
29 // Support building against older versions of LLVM, this macro was added
31 #ifndef LLVM_EXTENSION
32 #define LLVM_EXTENSION
36 #include "Utility/ARM64_DWARF_Registers.h"
39 using namespace lldb_private;
41 #define GPR_OFFSET(idx) ((idx)*8)
42 #define GPR_OFFSET_NAME(reg) \
43 (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::GPR, reg))
45 #define FPU_OFFSET(idx) ((idx)*16 + sizeof(RegisterContextDarwin_arm64::GPR))
46 #define FPU_OFFSET_NAME(reg) \
47 (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::FPU, reg))
49 #define EXC_OFFSET_NAME(reg) \
50 (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::EXC, reg) + \
51 sizeof(RegisterContextDarwin_arm64::GPR) + \
52 sizeof(RegisterContextDarwin_arm64::FPU))
53 #define DBG_OFFSET_NAME(reg) \
54 (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::DBG, reg) + \
55 sizeof(RegisterContextDarwin_arm64::GPR) + \
56 sizeof(RegisterContextDarwin_arm64::FPU) + \
57 sizeof(RegisterContextDarwin_arm64::EXC))
59 #define DEFINE_DBG(reg, i) \
61 sizeof(((RegisterContextDarwin_arm64::DBG *) NULL)->reg[i]), \
62 DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, \
63 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
64 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
65 LLDB_INVALID_REGNUM }, \
67 #define REG_CONTEXT_SIZE \
68 (sizeof(RegisterContextDarwin_arm64::GPR) + \
69 sizeof(RegisterContextDarwin_arm64::FPU) + \
70 sizeof(RegisterContextDarwin_arm64::EXC))
72 //-----------------------------------------------------------------------------
73 // Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure.
74 //-----------------------------------------------------------------------------
75 #define DECLARE_REGISTER_INFOS_ARM64_STRUCT
76 #include "RegisterInfos_arm64.h"
77 #undef DECLARE_REGISTER_INFOS_ARM64_STRUCT
79 // General purpose registers
80 static uint32_t g_gpr_regnums[] = {
81 gpr_x0, gpr_x1, gpr_x2, gpr_x3, gpr_x4, gpr_x5, gpr_x6,
82 gpr_x7, gpr_x8, gpr_x9, gpr_x10, gpr_x11, gpr_x12, gpr_x13,
83 gpr_x14, gpr_x15, gpr_x16, gpr_x17, gpr_x18, gpr_x19, gpr_x20,
84 gpr_x21, gpr_x22, gpr_x23, gpr_x24, gpr_x25, gpr_x26, gpr_x27,
85 gpr_x28, gpr_fp, gpr_lr, gpr_sp, gpr_pc, gpr_cpsr};
87 // Floating point registers
88 static uint32_t g_fpu_regnums[] = {
89 fpu_v0, fpu_v1, fpu_v2, fpu_v3, fpu_v4, fpu_v5, fpu_v6,
90 fpu_v7, fpu_v8, fpu_v9, fpu_v10, fpu_v11, fpu_v12, fpu_v13,
91 fpu_v14, fpu_v15, fpu_v16, fpu_v17, fpu_v18, fpu_v19, fpu_v20,
92 fpu_v21, fpu_v22, fpu_v23, fpu_v24, fpu_v25, fpu_v26, fpu_v27,
93 fpu_v28, fpu_v29, fpu_v30, fpu_v31, fpu_fpsr, fpu_fpcr};
95 // Exception registers
97 static uint32_t g_exc_regnums[] = {exc_far, exc_esr, exc_exception};
99 static size_t k_num_register_infos =
100 llvm::array_lengthof(g_register_infos_arm64_le);
102 RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(
103 Thread &thread, uint32_t concrete_frame_idx)
104 : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() {
106 for (i = 0; i < kNumErrors; i++) {
113 RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() {}
115 void RegisterContextDarwin_arm64::InvalidateAllRegisters() {
116 InvalidateAllRegisterStates();
119 size_t RegisterContextDarwin_arm64::GetRegisterCount() {
120 assert(k_num_register_infos == k_num_registers);
121 return k_num_registers;
125 RegisterContextDarwin_arm64::GetRegisterInfoAtIndex(size_t reg) {
126 assert(k_num_register_infos == k_num_registers);
127 if (reg < k_num_registers)
128 return &g_register_infos_arm64_le[reg];
132 size_t RegisterContextDarwin_arm64::GetRegisterInfosCount() {
133 return k_num_register_infos;
136 const RegisterInfo *RegisterContextDarwin_arm64::GetRegisterInfos() {
137 return g_register_infos_arm64_le;
140 // Number of registers in each register set
141 const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
142 const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
143 const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
145 //----------------------------------------------------------------------
146 // Register set definitions. The first definitions at register set index of
147 // zero is for all registers, followed by other registers sets. The register
148 // information for the all register set need not be filled in.
149 //----------------------------------------------------------------------
150 static const RegisterSet g_reg_sets[] = {
152 "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums,
154 {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums},
155 {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}};
157 const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
159 size_t RegisterContextDarwin_arm64::GetRegisterSetCount() {
160 return k_num_regsets;
163 const RegisterSet *RegisterContextDarwin_arm64::GetRegisterSet(size_t reg_set) {
164 if (reg_set < k_num_regsets)
165 return &g_reg_sets[reg_set];
169 //----------------------------------------------------------------------
170 // Register information definitions for arm64
171 //----------------------------------------------------------------------
172 int RegisterContextDarwin_arm64::GetSetForNativeRegNum(int reg) {
175 else if (reg < exc_far)
177 else if (reg < k_num_registers)
182 int RegisterContextDarwin_arm64::ReadGPR(bool force) {
184 if (force || !RegisterSetIsCached(set)) {
185 SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
187 return GetError(GPRRegSet, Read);
190 int RegisterContextDarwin_arm64::ReadFPU(bool force) {
192 if (force || !RegisterSetIsCached(set)) {
193 SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
195 return GetError(FPURegSet, Read);
198 int RegisterContextDarwin_arm64::ReadEXC(bool force) {
200 if (force || !RegisterSetIsCached(set)) {
201 SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
203 return GetError(EXCRegSet, Read);
206 int RegisterContextDarwin_arm64::ReadDBG(bool force) {
208 if (force || !RegisterSetIsCached(set)) {
209 SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));
211 return GetError(DBGRegSet, Read);
214 int RegisterContextDarwin_arm64::WriteGPR() {
216 if (!RegisterSetIsCached(set)) {
217 SetError(set, Write, -1);
218 return KERN_INVALID_ARGUMENT;
220 SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));
221 SetError(set, Read, -1);
222 return GetError(GPRRegSet, Write);
225 int RegisterContextDarwin_arm64::WriteFPU() {
227 if (!RegisterSetIsCached(set)) {
228 SetError(set, Write, -1);
229 return KERN_INVALID_ARGUMENT;
231 SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu));
232 SetError(set, Read, -1);
233 return GetError(FPURegSet, Write);
236 int RegisterContextDarwin_arm64::WriteEXC() {
238 if (!RegisterSetIsCached(set)) {
239 SetError(set, Write, -1);
240 return KERN_INVALID_ARGUMENT;
242 SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));
243 SetError(set, Read, -1);
244 return GetError(EXCRegSet, Write);
247 int RegisterContextDarwin_arm64::WriteDBG() {
249 if (!RegisterSetIsCached(set)) {
250 SetError(set, Write, -1);
251 return KERN_INVALID_ARGUMENT;
253 SetError(set, Write, DoWriteDBG(GetThreadID(), set, dbg));
254 SetError(set, Read, -1);
255 return GetError(DBGRegSet, Write);
258 int RegisterContextDarwin_arm64::ReadRegisterSet(uint32_t set, bool force) {
261 return ReadGPR(force);
263 return ReadFPU(force);
265 return ReadEXC(force);
267 return ReadDBG(force);
271 return KERN_INVALID_ARGUMENT;
274 int RegisterContextDarwin_arm64::WriteRegisterSet(uint32_t set) {
275 // Make sure we have a valid context to set.
276 if (RegisterSetIsCached(set)) {
290 return KERN_INVALID_ARGUMENT;
293 void RegisterContextDarwin_arm64::LogDBGRegisters(Log *log, const DBG &dbg) {
295 for (uint32_t i = 0; i < 16; i++)
296 log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64
297 " } WVR%-2u/WCR%-2u "
298 "= { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 " }",
299 i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]);
303 bool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info,
304 RegisterValue &value) {
305 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
306 int set = RegisterContextDarwin_arm64::GetSetForNativeRegNum(reg);
311 if (ReadRegisterSet(set, false) != KERN_SUCCESS)
349 value.SetUInt64(gpr.x[reg - gpr_x0]);
381 ProcessSP process_sp(m_thread.GetProcess());
382 if (process_sp.get()) {
383 DataExtractor regdata(&gpr.x[reg - gpr_w0], 8, process_sp->GetByteOrder(),
384 process_sp->GetAddressByteSize());
386 uint64_t retval = regdata.GetMaxU64(&offset, 8);
387 uint32_t retval_lower32 = static_cast<uint32_t>(retval & 0xffffffff);
388 value.SetUInt32(retval_lower32);
424 value.SetBytes(fpu.v[reg].bytes.buffer, reg_info->byte_size,
425 endian::InlHostByteOrder());
460 ProcessSP process_sp(m_thread.GetProcess());
461 if (process_sp.get()) {
462 DataExtractor regdata(&fpu.v[reg - fpu_s0], 4, process_sp->GetByteOrder(),
463 process_sp->GetAddressByteSize());
465 value.SetFloat(regdata.GetFloat(&offset));
501 ProcessSP process_sp(m_thread.GetProcess());
502 if (process_sp.get()) {
503 DataExtractor regdata(&fpu.v[reg - fpu_s0], 8, process_sp->GetByteOrder(),
504 process_sp->GetAddressByteSize());
506 value.SetDouble(regdata.GetDouble(&offset));
511 value.SetUInt32(fpu.fpsr);
515 value.SetUInt32(fpu.fpcr);
519 value.SetUInt32(exc.exception);
522 value.SetUInt32(exc.esr);
525 value.SetUInt64(exc.far);
529 value.SetValueToInvalid();
535 bool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info,
536 const RegisterValue &value) {
537 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
538 int set = GetSetForNativeRegNum(reg);
543 if (ReadRegisterSet(set, false) != KERN_SUCCESS)
581 gpr.x[reg - gpr_x0] = value.GetAsUInt64();
616 ::memcpy(fpu.v[reg].bytes.buffer, value.GetBytes(), value.GetByteSize());
620 fpu.fpsr = value.GetAsUInt32();
624 fpu.fpcr = value.GetAsUInt32();
628 exc.exception = value.GetAsUInt32();
631 exc.esr = value.GetAsUInt32();
634 exc.far = value.GetAsUInt64();
640 return WriteRegisterSet(set) == KERN_SUCCESS;
643 bool RegisterContextDarwin_arm64::ReadAllRegisterValues(
644 lldb::DataBufferSP &data_sp) {
645 data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
646 if (data_sp && ReadGPR(false) == KERN_SUCCESS &&
647 ReadFPU(false) == KERN_SUCCESS && ReadEXC(false) == KERN_SUCCESS) {
648 uint8_t *dst = data_sp->GetBytes();
649 ::memcpy(dst, &gpr, sizeof(gpr));
652 ::memcpy(dst, &fpu, sizeof(fpu));
655 ::memcpy(dst, &exc, sizeof(exc));
661 bool RegisterContextDarwin_arm64::WriteAllRegisterValues(
662 const lldb::DataBufferSP &data_sp) {
663 if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
664 const uint8_t *src = data_sp->GetBytes();
665 ::memcpy(&gpr, src, sizeof(gpr));
668 ::memcpy(&fpu, src, sizeof(fpu));
671 ::memcpy(&exc, src, sizeof(exc));
672 uint32_t success_count = 0;
673 if (WriteGPR() == KERN_SUCCESS)
675 if (WriteFPU() == KERN_SUCCESS)
677 if (WriteEXC() == KERN_SUCCESS)
679 return success_count == 3;
684 uint32_t RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber(
685 RegisterKind kind, uint32_t reg) {
686 if (kind == eRegisterKindGeneric) {
688 case LLDB_REGNUM_GENERIC_PC:
690 case LLDB_REGNUM_GENERIC_SP:
692 case LLDB_REGNUM_GENERIC_FP:
694 case LLDB_REGNUM_GENERIC_RA:
696 case LLDB_REGNUM_GENERIC_FLAGS:
701 } else if (kind == eRegisterKindDWARF) {
703 case arm64_dwarf::x0:
705 case arm64_dwarf::x1:
707 case arm64_dwarf::x2:
709 case arm64_dwarf::x3:
711 case arm64_dwarf::x4:
713 case arm64_dwarf::x5:
715 case arm64_dwarf::x6:
717 case arm64_dwarf::x7:
719 case arm64_dwarf::x8:
721 case arm64_dwarf::x9:
723 case arm64_dwarf::x10:
725 case arm64_dwarf::x11:
727 case arm64_dwarf::x12:
729 case arm64_dwarf::x13:
731 case arm64_dwarf::x14:
733 case arm64_dwarf::x15:
735 case arm64_dwarf::x16:
737 case arm64_dwarf::x17:
739 case arm64_dwarf::x18:
741 case arm64_dwarf::x19:
743 case arm64_dwarf::x20:
745 case arm64_dwarf::x21:
747 case arm64_dwarf::x22:
749 case arm64_dwarf::x23:
751 case arm64_dwarf::x24:
753 case arm64_dwarf::x25:
755 case arm64_dwarf::x26:
757 case arm64_dwarf::x27:
759 case arm64_dwarf::x28:
762 case arm64_dwarf::fp:
764 case arm64_dwarf::sp:
766 case arm64_dwarf::lr:
768 case arm64_dwarf::pc:
770 case arm64_dwarf::cpsr:
773 case arm64_dwarf::v0:
775 case arm64_dwarf::v1:
777 case arm64_dwarf::v2:
779 case arm64_dwarf::v3:
781 case arm64_dwarf::v4:
783 case arm64_dwarf::v5:
785 case arm64_dwarf::v6:
787 case arm64_dwarf::v7:
789 case arm64_dwarf::v8:
791 case arm64_dwarf::v9:
793 case arm64_dwarf::v10:
795 case arm64_dwarf::v11:
797 case arm64_dwarf::v12:
799 case arm64_dwarf::v13:
801 case arm64_dwarf::v14:
803 case arm64_dwarf::v15:
805 case arm64_dwarf::v16:
807 case arm64_dwarf::v17:
809 case arm64_dwarf::v18:
811 case arm64_dwarf::v19:
813 case arm64_dwarf::v20:
815 case arm64_dwarf::v21:
817 case arm64_dwarf::v22:
819 case arm64_dwarf::v23:
821 case arm64_dwarf::v24:
823 case arm64_dwarf::v25:
825 case arm64_dwarf::v26:
827 case arm64_dwarf::v27:
829 case arm64_dwarf::v28:
831 case arm64_dwarf::v29:
833 case arm64_dwarf::v30:
835 case arm64_dwarf::v31:
841 } else if (kind == eRegisterKindEHFrame) {
843 case arm64_ehframe::x0:
845 case arm64_ehframe::x1:
847 case arm64_ehframe::x2:
849 case arm64_ehframe::x3:
851 case arm64_ehframe::x4:
853 case arm64_ehframe::x5:
855 case arm64_ehframe::x6:
857 case arm64_ehframe::x7:
859 case arm64_ehframe::x8:
861 case arm64_ehframe::x9:
863 case arm64_ehframe::x10:
865 case arm64_ehframe::x11:
867 case arm64_ehframe::x12:
869 case arm64_ehframe::x13:
871 case arm64_ehframe::x14:
873 case arm64_ehframe::x15:
875 case arm64_ehframe::x16:
877 case arm64_ehframe::x17:
879 case arm64_ehframe::x18:
881 case arm64_ehframe::x19:
883 case arm64_ehframe::x20:
885 case arm64_ehframe::x21:
887 case arm64_ehframe::x22:
889 case arm64_ehframe::x23:
891 case arm64_ehframe::x24:
893 case arm64_ehframe::x25:
895 case arm64_ehframe::x26:
897 case arm64_ehframe::x27:
899 case arm64_ehframe::x28:
901 case arm64_ehframe::fp:
903 case arm64_ehframe::sp:
905 case arm64_ehframe::lr:
907 case arm64_ehframe::pc:
909 case arm64_ehframe::cpsr:
912 } else if (kind == eRegisterKindLLDB) {
915 return LLDB_INVALID_REGNUM;
918 uint32_t RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints() {
919 #if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))
920 // autodetect how many watchpoints are supported dynamically...
921 static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
922 if (g_num_supported_hw_watchpoints == UINT32_MAX) {
926 if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) {
927 g_num_supported_hw_watchpoints = n;
930 return g_num_supported_hw_watchpoints;
932 // TODO: figure out remote case here!
937 uint32_t RegisterContextDarwin_arm64::SetHardwareWatchpoint(lldb::addr_t addr,
941 // if (log) log->Printf
942 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(addr = %8.8p,
943 // size = %u, read = %u, write = %u)", addr, size, read, write);
945 const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
947 // Can't watch zero bytes
949 return LLDB_INVALID_INDEX32;
951 // We must watch for either read or write
952 if (read == false && write == false)
953 return LLDB_INVALID_INDEX32;
955 // Can't watch more than 4 bytes per WVR/WCR pair
957 return LLDB_INVALID_INDEX32;
959 // We can only watch up to four bytes that follow a 4 byte aligned address
960 // per watchpoint register pair. Since we have at most so we can only watch
961 // until the next 4 byte boundary and we need to make sure we can properly
963 uint32_t addr_word_offset = addr % 4;
964 // if (log) log->Printf
965 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() -
966 // addr_word_offset = 0x%8.8x", addr_word_offset);
968 uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
969 // if (log) log->Printf
970 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - byte_mask =
971 // 0x%8.8x", byte_mask);
972 if (byte_mask > 0xfu)
973 return LLDB_INVALID_INDEX32;
975 // Read the debug state
976 int kret = ReadDBG(false);
978 if (kret == KERN_SUCCESS) {
979 // Check to make sure we have the needed hardware support
982 for (i = 0; i < num_hw_watchpoints; ++i) {
983 if ((dbg.wcr[i] & WCR_ENABLE) == 0)
984 break; // We found an available hw breakpoint slot (in i)
987 // See if we found an available hw breakpoint slot above
988 if (i < num_hw_watchpoints) {
989 // Make the byte_mask into a valid Byte Address Select mask
990 uint32_t byte_address_select = byte_mask << 5;
991 // Make sure bits 1:0 are clear in our address
992 dbg.wvr[i] = addr & ~((lldb::addr_t)3);
993 dbg.wcr[i] = byte_address_select | // Which bytes that follow the IMVA
994 // that we will watch
995 S_USER | // Stop only in user mode
996 (read ? WCR_LOAD : 0) | // Stop on read access?
997 (write ? WCR_STORE : 0) | // Stop on write access?
998 WCR_ENABLE; // Enable this watchpoint;
1001 // if (log) log->Printf
1002 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint()
1003 // WriteDBG() => 0x%8.8x.", kret);
1005 if (kret == KERN_SUCCESS)
1008 // if (log) log->Printf
1009 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint():
1010 // All hardware resources (%u) are in use.",
1011 // num_hw_watchpoints);
1014 return LLDB_INVALID_INDEX32;
1017 bool RegisterContextDarwin_arm64::ClearHardwareWatchpoint(uint32_t hw_index) {
1018 int kret = ReadDBG(false);
1020 const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
1021 if (kret == KERN_SUCCESS) {
1022 if (hw_index < num_hw_points) {
1023 dbg.wcr[hw_index] = 0;
1024 // if (log) log->Printf
1025 // ("RegisterContextDarwin_arm64::ClearHardwareWatchpoint( %u )
1026 // - WVR%u = 0x%8.8x WCR%u = 0x%8.8x",
1029 // dbg.wvr[hw_index],
1031 // dbg.wcr[hw_index]);
1035 if (kret == KERN_SUCCESS)