1 //===-- RegisterContextDarwin_arm64.cpp ---------------------------*- C++
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #include "RegisterContextDarwin_arm64.h"
11 #include "RegisterContextDarwinConstants.h"
13 #include "lldb/Target/Process.h"
14 #include "lldb/Target/Thread.h"
15 #include "lldb/Utility/DataBufferHeap.h"
16 #include "lldb/Utility/DataExtractor.h"
17 #include "lldb/Utility/Endian.h"
18 #include "lldb/Utility/Log.h"
19 #include "lldb/Utility/RegisterValue.h"
20 #include "lldb/Utility/Scalar.h"
21 #include "llvm/ADT/STLExtras.h"
22 #include "llvm/Support/Compiler.h"
24 #include "Plugins/Process/Utility/InstructionUtils.h"
28 #if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))
29 #include <sys/types.h>
30 #include <sys/sysctl.h>
33 #include "Utility/ARM64_DWARF_Registers.h"
36 using namespace lldb_private;
38 #define GPR_OFFSET(idx) ((idx)*8)
39 #define GPR_OFFSET_NAME(reg) \
40 (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::GPR, reg))
42 #define FPU_OFFSET(idx) ((idx)*16 + sizeof(RegisterContextDarwin_arm64::GPR))
43 #define FPU_OFFSET_NAME(reg) \
44 (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::FPU, reg))
46 #define EXC_OFFSET_NAME(reg) \
47 (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::EXC, reg) + \
48 sizeof(RegisterContextDarwin_arm64::GPR) + \
49 sizeof(RegisterContextDarwin_arm64::FPU))
50 #define DBG_OFFSET_NAME(reg) \
51 (LLVM_EXTENSION offsetof(RegisterContextDarwin_arm64::DBG, reg) + \
52 sizeof(RegisterContextDarwin_arm64::GPR) + \
53 sizeof(RegisterContextDarwin_arm64::FPU) + \
54 sizeof(RegisterContextDarwin_arm64::EXC))
56 #define DEFINE_DBG(reg, i) \
58 sizeof(((RegisterContextDarwin_arm64::DBG *) NULL)->reg[i]), \
59 DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, \
60 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
61 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
62 LLDB_INVALID_REGNUM }, \
64 #define REG_CONTEXT_SIZE \
65 (sizeof(RegisterContextDarwin_arm64::GPR) + \
66 sizeof(RegisterContextDarwin_arm64::FPU) + \
67 sizeof(RegisterContextDarwin_arm64::EXC))
69 // Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure.
70 #define DECLARE_REGISTER_INFOS_ARM64_STRUCT
71 #include "RegisterInfos_arm64.h"
72 #undef DECLARE_REGISTER_INFOS_ARM64_STRUCT
74 // General purpose registers
75 static uint32_t g_gpr_regnums[] = {
76 gpr_x0, gpr_x1, gpr_x2, gpr_x3, gpr_x4, gpr_x5, gpr_x6,
77 gpr_x7, gpr_x8, gpr_x9, gpr_x10, gpr_x11, gpr_x12, gpr_x13,
78 gpr_x14, gpr_x15, gpr_x16, gpr_x17, gpr_x18, gpr_x19, gpr_x20,
79 gpr_x21, gpr_x22, gpr_x23, gpr_x24, gpr_x25, gpr_x26, gpr_x27,
80 gpr_x28, gpr_fp, gpr_lr, gpr_sp, gpr_pc, gpr_cpsr};
82 // Floating point registers
83 static uint32_t g_fpu_regnums[] = {
84 fpu_v0, fpu_v1, fpu_v2, fpu_v3, fpu_v4, fpu_v5, fpu_v6,
85 fpu_v7, fpu_v8, fpu_v9, fpu_v10, fpu_v11, fpu_v12, fpu_v13,
86 fpu_v14, fpu_v15, fpu_v16, fpu_v17, fpu_v18, fpu_v19, fpu_v20,
87 fpu_v21, fpu_v22, fpu_v23, fpu_v24, fpu_v25, fpu_v26, fpu_v27,
88 fpu_v28, fpu_v29, fpu_v30, fpu_v31, fpu_fpsr, fpu_fpcr};
90 // Exception registers
92 static uint32_t g_exc_regnums[] = {exc_far, exc_esr, exc_exception};
94 static size_t k_num_register_infos =
95 llvm::array_lengthof(g_register_infos_arm64_le);
97 RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(
98 Thread &thread, uint32_t concrete_frame_idx)
99 : RegisterContext(thread, concrete_frame_idx), gpr(), fpu(), exc() {
101 for (i = 0; i < kNumErrors; i++) {
108 RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() {}
110 void RegisterContextDarwin_arm64::InvalidateAllRegisters() {
111 InvalidateAllRegisterStates();
114 size_t RegisterContextDarwin_arm64::GetRegisterCount() {
115 assert(k_num_register_infos == k_num_registers);
116 return k_num_registers;
120 RegisterContextDarwin_arm64::GetRegisterInfoAtIndex(size_t reg) {
121 assert(k_num_register_infos == k_num_registers);
122 if (reg < k_num_registers)
123 return &g_register_infos_arm64_le[reg];
127 size_t RegisterContextDarwin_arm64::GetRegisterInfosCount() {
128 return k_num_register_infos;
131 const RegisterInfo *RegisterContextDarwin_arm64::GetRegisterInfos() {
132 return g_register_infos_arm64_le;
135 // Number of registers in each register set
136 const size_t k_num_gpr_registers = llvm::array_lengthof(g_gpr_regnums);
137 const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
138 const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
140 // Register set definitions. The first definitions at register set index of
141 // zero is for all registers, followed by other registers sets. The register
142 // information for the all register set need not be filled in.
143 static const RegisterSet g_reg_sets[] = {
145 "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums,
147 {"Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums},
148 {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums}};
150 const size_t k_num_regsets = llvm::array_lengthof(g_reg_sets);
152 size_t RegisterContextDarwin_arm64::GetRegisterSetCount() {
153 return k_num_regsets;
156 const RegisterSet *RegisterContextDarwin_arm64::GetRegisterSet(size_t reg_set) {
157 if (reg_set < k_num_regsets)
158 return &g_reg_sets[reg_set];
162 // Register information definitions for arm64
163 int RegisterContextDarwin_arm64::GetSetForNativeRegNum(int reg) {
166 else if (reg < exc_far)
168 else if (reg < k_num_registers)
173 int RegisterContextDarwin_arm64::ReadGPR(bool force) {
175 if (force || !RegisterSetIsCached(set)) {
176 SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
178 return GetError(GPRRegSet, Read);
181 int RegisterContextDarwin_arm64::ReadFPU(bool force) {
183 if (force || !RegisterSetIsCached(set)) {
184 SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
186 return GetError(FPURegSet, Read);
189 int RegisterContextDarwin_arm64::ReadEXC(bool force) {
191 if (force || !RegisterSetIsCached(set)) {
192 SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
194 return GetError(EXCRegSet, Read);
197 int RegisterContextDarwin_arm64::ReadDBG(bool force) {
199 if (force || !RegisterSetIsCached(set)) {
200 SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));
202 return GetError(DBGRegSet, Read);
205 int RegisterContextDarwin_arm64::WriteGPR() {
207 if (!RegisterSetIsCached(set)) {
208 SetError(set, Write, -1);
209 return KERN_INVALID_ARGUMENT;
211 SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));
212 SetError(set, Read, -1);
213 return GetError(GPRRegSet, Write);
216 int RegisterContextDarwin_arm64::WriteFPU() {
218 if (!RegisterSetIsCached(set)) {
219 SetError(set, Write, -1);
220 return KERN_INVALID_ARGUMENT;
222 SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpu));
223 SetError(set, Read, -1);
224 return GetError(FPURegSet, Write);
227 int RegisterContextDarwin_arm64::WriteEXC() {
229 if (!RegisterSetIsCached(set)) {
230 SetError(set, Write, -1);
231 return KERN_INVALID_ARGUMENT;
233 SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));
234 SetError(set, Read, -1);
235 return GetError(EXCRegSet, Write);
238 int RegisterContextDarwin_arm64::WriteDBG() {
240 if (!RegisterSetIsCached(set)) {
241 SetError(set, Write, -1);
242 return KERN_INVALID_ARGUMENT;
244 SetError(set, Write, DoWriteDBG(GetThreadID(), set, dbg));
245 SetError(set, Read, -1);
246 return GetError(DBGRegSet, Write);
249 int RegisterContextDarwin_arm64::ReadRegisterSet(uint32_t set, bool force) {
252 return ReadGPR(force);
254 return ReadFPU(force);
256 return ReadEXC(force);
258 return ReadDBG(force);
262 return KERN_INVALID_ARGUMENT;
265 int RegisterContextDarwin_arm64::WriteRegisterSet(uint32_t set) {
266 // Make sure we have a valid context to set.
267 if (RegisterSetIsCached(set)) {
281 return KERN_INVALID_ARGUMENT;
284 void RegisterContextDarwin_arm64::LogDBGRegisters(Log *log, const DBG &dbg) {
286 for (uint32_t i = 0; i < 16; i++)
288 "BVR%-2u/BCR%-2u = { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64
289 " } WVR%-2u/WCR%-2u "
290 "= { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 " }",
291 i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]);
295 bool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info,
296 RegisterValue &value) {
297 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
298 int set = RegisterContextDarwin_arm64::GetSetForNativeRegNum(reg);
303 if (ReadRegisterSet(set, false) != KERN_SUCCESS)
336 value.SetUInt64(gpr.x[reg - gpr_x0]);
339 value.SetUInt64(gpr.fp);
342 value.SetUInt64(gpr.sp);
345 value.SetUInt64(gpr.lr);
348 value.SetUInt64(gpr.pc);
351 value.SetUInt64(gpr.cpsr);
383 ProcessSP process_sp(m_thread.GetProcess());
384 if (process_sp.get()) {
385 DataExtractor regdata(&gpr.x[reg - gpr_w0], 8, process_sp->GetByteOrder(),
386 process_sp->GetAddressByteSize());
388 uint64_t retval = regdata.GetMaxU64(&offset, 8);
389 uint32_t retval_lower32 = static_cast<uint32_t>(retval & 0xffffffff);
390 value.SetUInt32(retval_lower32);
426 value.SetBytes(fpu.v[reg - fpu_v0].bytes, reg_info->byte_size,
427 endian::InlHostByteOrder());
462 ProcessSP process_sp(m_thread.GetProcess());
463 if (process_sp.get()) {
464 DataExtractor regdata(&fpu.v[reg - fpu_s0], 4, process_sp->GetByteOrder(),
465 process_sp->GetAddressByteSize());
467 value.SetFloat(regdata.GetFloat(&offset));
503 ProcessSP process_sp(m_thread.GetProcess());
504 if (process_sp.get()) {
505 DataExtractor regdata(&fpu.v[reg - fpu_d0], 8, process_sp->GetByteOrder(),
506 process_sp->GetAddressByteSize());
508 value.SetDouble(regdata.GetDouble(&offset));
513 value.SetUInt32(fpu.fpsr);
517 value.SetUInt32(fpu.fpcr);
521 value.SetUInt32(exc.exception);
524 value.SetUInt32(exc.esr);
527 value.SetUInt64(exc.far);
531 value.SetValueToInvalid();
537 bool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info,
538 const RegisterValue &value) {
539 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
540 int set = GetSetForNativeRegNum(reg);
545 if (ReadRegisterSet(set, false) != KERN_SUCCESS)
583 gpr.x[reg - gpr_x0] = value.GetAsUInt64();
618 ::memcpy(fpu.v[reg - fpu_v0].bytes, value.GetBytes(),
619 value.GetByteSize());
623 fpu.fpsr = value.GetAsUInt32();
627 fpu.fpcr = value.GetAsUInt32();
631 exc.exception = value.GetAsUInt32();
634 exc.esr = value.GetAsUInt32();
637 exc.far = value.GetAsUInt64();
643 return WriteRegisterSet(set) == KERN_SUCCESS;
646 bool RegisterContextDarwin_arm64::ReadAllRegisterValues(
647 lldb::DataBufferSP &data_sp) {
648 data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
649 if (ReadGPR(false) == KERN_SUCCESS && ReadFPU(false) == KERN_SUCCESS &&
650 ReadEXC(false) == KERN_SUCCESS) {
651 uint8_t *dst = data_sp->GetBytes();
652 ::memcpy(dst, &gpr, sizeof(gpr));
655 ::memcpy(dst, &fpu, sizeof(fpu));
658 ::memcpy(dst, &exc, sizeof(exc));
664 bool RegisterContextDarwin_arm64::WriteAllRegisterValues(
665 const lldb::DataBufferSP &data_sp) {
666 if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
667 const uint8_t *src = data_sp->GetBytes();
668 ::memcpy(&gpr, src, sizeof(gpr));
671 ::memcpy(&fpu, src, sizeof(fpu));
674 ::memcpy(&exc, src, sizeof(exc));
675 uint32_t success_count = 0;
676 if (WriteGPR() == KERN_SUCCESS)
678 if (WriteFPU() == KERN_SUCCESS)
680 if (WriteEXC() == KERN_SUCCESS)
682 return success_count == 3;
687 uint32_t RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber(
688 RegisterKind kind, uint32_t reg) {
689 if (kind == eRegisterKindGeneric) {
691 case LLDB_REGNUM_GENERIC_PC:
693 case LLDB_REGNUM_GENERIC_SP:
695 case LLDB_REGNUM_GENERIC_FP:
697 case LLDB_REGNUM_GENERIC_RA:
699 case LLDB_REGNUM_GENERIC_FLAGS:
704 } else if (kind == eRegisterKindDWARF) {
706 case arm64_dwarf::x0:
708 case arm64_dwarf::x1:
710 case arm64_dwarf::x2:
712 case arm64_dwarf::x3:
714 case arm64_dwarf::x4:
716 case arm64_dwarf::x5:
718 case arm64_dwarf::x6:
720 case arm64_dwarf::x7:
722 case arm64_dwarf::x8:
724 case arm64_dwarf::x9:
726 case arm64_dwarf::x10:
728 case arm64_dwarf::x11:
730 case arm64_dwarf::x12:
732 case arm64_dwarf::x13:
734 case arm64_dwarf::x14:
736 case arm64_dwarf::x15:
738 case arm64_dwarf::x16:
740 case arm64_dwarf::x17:
742 case arm64_dwarf::x18:
744 case arm64_dwarf::x19:
746 case arm64_dwarf::x20:
748 case arm64_dwarf::x21:
750 case arm64_dwarf::x22:
752 case arm64_dwarf::x23:
754 case arm64_dwarf::x24:
756 case arm64_dwarf::x25:
758 case arm64_dwarf::x26:
760 case arm64_dwarf::x27:
762 case arm64_dwarf::x28:
765 case arm64_dwarf::fp:
767 case arm64_dwarf::sp:
769 case arm64_dwarf::lr:
771 case arm64_dwarf::pc:
773 case arm64_dwarf::cpsr:
776 case arm64_dwarf::v0:
778 case arm64_dwarf::v1:
780 case arm64_dwarf::v2:
782 case arm64_dwarf::v3:
784 case arm64_dwarf::v4:
786 case arm64_dwarf::v5:
788 case arm64_dwarf::v6:
790 case arm64_dwarf::v7:
792 case arm64_dwarf::v8:
794 case arm64_dwarf::v9:
796 case arm64_dwarf::v10:
798 case arm64_dwarf::v11:
800 case arm64_dwarf::v12:
802 case arm64_dwarf::v13:
804 case arm64_dwarf::v14:
806 case arm64_dwarf::v15:
808 case arm64_dwarf::v16:
810 case arm64_dwarf::v17:
812 case arm64_dwarf::v18:
814 case arm64_dwarf::v19:
816 case arm64_dwarf::v20:
818 case arm64_dwarf::v21:
820 case arm64_dwarf::v22:
822 case arm64_dwarf::v23:
824 case arm64_dwarf::v24:
826 case arm64_dwarf::v25:
828 case arm64_dwarf::v26:
830 case arm64_dwarf::v27:
832 case arm64_dwarf::v28:
834 case arm64_dwarf::v29:
836 case arm64_dwarf::v30:
838 case arm64_dwarf::v31:
844 } else if (kind == eRegisterKindEHFrame) {
846 case arm64_ehframe::x0:
848 case arm64_ehframe::x1:
850 case arm64_ehframe::x2:
852 case arm64_ehframe::x3:
854 case arm64_ehframe::x4:
856 case arm64_ehframe::x5:
858 case arm64_ehframe::x6:
860 case arm64_ehframe::x7:
862 case arm64_ehframe::x8:
864 case arm64_ehframe::x9:
866 case arm64_ehframe::x10:
868 case arm64_ehframe::x11:
870 case arm64_ehframe::x12:
872 case arm64_ehframe::x13:
874 case arm64_ehframe::x14:
876 case arm64_ehframe::x15:
878 case arm64_ehframe::x16:
880 case arm64_ehframe::x17:
882 case arm64_ehframe::x18:
884 case arm64_ehframe::x19:
886 case arm64_ehframe::x20:
888 case arm64_ehframe::x21:
890 case arm64_ehframe::x22:
892 case arm64_ehframe::x23:
894 case arm64_ehframe::x24:
896 case arm64_ehframe::x25:
898 case arm64_ehframe::x26:
900 case arm64_ehframe::x27:
902 case arm64_ehframe::x28:
904 case arm64_ehframe::fp:
906 case arm64_ehframe::sp:
908 case arm64_ehframe::lr:
910 case arm64_ehframe::pc:
912 case arm64_ehframe::cpsr:
915 } else if (kind == eRegisterKindLLDB) {
918 return LLDB_INVALID_REGNUM;
921 uint32_t RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints() {
922 #if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))
923 // autodetect how many watchpoints are supported dynamically...
924 static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
925 if (g_num_supported_hw_watchpoints == UINT32_MAX) {
929 if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) {
930 g_num_supported_hw_watchpoints = n;
933 return g_num_supported_hw_watchpoints;
935 // TODO: figure out remote case here!
940 uint32_t RegisterContextDarwin_arm64::SetHardwareWatchpoint(lldb::addr_t addr,
944 // if (log) log->Printf
945 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint(addr = %8.8p,
946 // size = %u, read = %u, write = %u)", addr, size, read, write);
948 const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
950 // Can't watch zero bytes
952 return LLDB_INVALID_INDEX32;
954 // We must watch for either read or write
956 return LLDB_INVALID_INDEX32;
958 // Can't watch more than 4 bytes per WVR/WCR pair
960 return LLDB_INVALID_INDEX32;
962 // We can only watch up to four bytes that follow a 4 byte aligned address
963 // per watchpoint register pair. Since we have at most so we can only watch
964 // until the next 4 byte boundary and we need to make sure we can properly
966 uint32_t addr_word_offset = addr % 4;
967 // if (log) log->Printf
968 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() -
969 // addr_word_offset = 0x%8.8x", addr_word_offset);
971 uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
972 // if (log) log->Printf
973 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint() - byte_mask =
974 // 0x%8.8x", byte_mask);
975 if (byte_mask > 0xfu)
976 return LLDB_INVALID_INDEX32;
978 // Read the debug state
979 int kret = ReadDBG(false);
981 if (kret == KERN_SUCCESS) {
982 // Check to make sure we have the needed hardware support
985 for (i = 0; i < num_hw_watchpoints; ++i) {
986 if ((dbg.wcr[i] & WCR_ENABLE) == 0)
987 break; // We found an available hw breakpoint slot (in i)
990 // See if we found an available hw breakpoint slot above
991 if (i < num_hw_watchpoints) {
992 // Make the byte_mask into a valid Byte Address Select mask
993 uint32_t byte_address_select = byte_mask << 5;
994 // Make sure bits 1:0 are clear in our address
995 dbg.wvr[i] = addr & ~((lldb::addr_t)3);
996 dbg.wcr[i] = byte_address_select | // Which bytes that follow the IMVA
997 // that we will watch
998 S_USER | // Stop only in user mode
999 (read ? WCR_LOAD : 0) | // Stop on read access?
1000 (write ? WCR_STORE : 0) | // Stop on write access?
1001 WCR_ENABLE; // Enable this watchpoint;
1004 // if (log) log->Printf
1005 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint()
1006 // WriteDBG() => 0x%8.8x.", kret);
1008 if (kret == KERN_SUCCESS)
1011 // if (log) log->Printf
1012 // ("RegisterContextDarwin_arm64::EnableHardwareWatchpoint():
1013 // All hardware resources (%u) are in use.",
1014 // num_hw_watchpoints);
1017 return LLDB_INVALID_INDEX32;
1020 bool RegisterContextDarwin_arm64::ClearHardwareWatchpoint(uint32_t hw_index) {
1021 int kret = ReadDBG(false);
1023 const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
1024 if (kret == KERN_SUCCESS) {
1025 if (hw_index < num_hw_points) {
1026 dbg.wcr[hw_index] = 0;
1027 // if (log) log->Printf
1028 // ("RegisterContextDarwin_arm64::ClearHardwareWatchpoint( %u )
1029 // - WVR%u = 0x%8.8x WCR%u = 0x%8.8x",
1032 // dbg.wvr[hw_index],
1034 // dbg.wcr[hw_index]);
1038 if (kret == KERN_SUCCESS)