1 //===-- DNBArchImplARM64.h --------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM64_DNBARCHIMPLARM64_H
10 #define LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM64_DNBARCHIMPLARM64_H
12 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
14 #include <mach/thread_status.h>
17 #if defined(ARM_THREAD_STATE64_COUNT)
23 class DNBArchMachARM64
: public DNBArchProtocol
{
25 enum { kMaxNumThumbITBreakpoints
= 4 };
27 DNBArchMachARM64(MachThread
*thread
)
28 : m_thread(thread
), m_state(), m_disabled_watchpoints(),
29 m_disabled_breakpoints(), m_watchpoint_hw_index(-1),
30 m_watchpoint_did_occur(false),
31 m_watchpoint_resume_single_step_enabled(false),
32 m_saved_register_states() {
33 m_disabled_watchpoints
.resize(16);
34 m_disabled_breakpoints
.resize(16);
35 memset(&m_dbg_save
, 0, sizeof(m_dbg_save
));
38 virtual ~DNBArchMachARM64() {}
40 static void Initialize();
41 static const DNBRegisterSetInfo
*GetRegisterSetInfo(nub_size_t
*num_reg_sets
);
43 bool GetRegisterValue(uint32_t set
, uint32_t reg
,
44 DNBRegisterValue
*value
) override
;
45 bool SetRegisterValue(uint32_t set
, uint32_t reg
,
46 const DNBRegisterValue
*value
) override
;
47 nub_size_t
GetRegisterContext(void *buf
, nub_size_t buf_len
) override
;
48 nub_size_t
SetRegisterContext(const void *buf
, nub_size_t buf_len
) override
;
49 uint32_t SaveRegisterState() override
;
50 bool RestoreRegisterState(uint32_t save_id
) override
;
52 kern_return_t
GetRegisterState(int set
, bool force
) override
;
53 kern_return_t
SetRegisterState(int set
) override
;
54 bool RegisterSetStateIsValid(int set
) const override
;
56 uint64_t GetPC(uint64_t failValue
) override
; // Get program counter
57 kern_return_t
SetPC(uint64_t value
) override
;
58 uint64_t GetSP(uint64_t failValue
) override
; // Get stack pointer
59 void ThreadWillResume() override
;
60 bool ThreadDidStop() override
;
61 bool NotifyException(MachException::Data
&exc
) override
;
63 static DNBArchProtocol
*Create(MachThread
*thread
);
64 static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size
);
65 static uint32_t GetCPUType();
67 uint32_t NumSupportedHardwareBreakpoints() override
;
68 uint32_t NumSupportedHardwareWatchpoints() override
;
70 uint32_t EnableHardwareBreakpoint(nub_addr_t addr
, nub_size_t size
,
71 bool also_set_on_task
) override
;
72 bool DisableHardwareBreakpoint(uint32_t hw_break_index
,
73 bool also_set_on_task
) override
;
74 uint32_t EnableHardwareWatchpoint(nub_addr_t addr
, nub_size_t size
, bool read
,
75 bool write
, bool also_set_on_task
) override
;
76 bool DisableHardwareWatchpoint(uint32_t hw_break_index
,
77 bool also_set_on_task
) override
;
78 bool DisableHardwareWatchpoint_helper(uint32_t hw_break_index
,
79 bool also_set_on_task
);
82 kern_return_t
EnableHardwareSingleStep(bool enable
);
83 static bool FixGenericRegisterNumber(uint32_t &set
, uint32_t ®
);
86 e_regSetALL
= REGISTER_SET_ALL
,
87 e_regSetGPR
, // ARM_THREAD_STATE64,
88 e_regSetVFP
, // ARM_NEON_STATE64,
89 e_regSetEXC
, // ARM_EXCEPTION_STATE64,
90 e_regSetDBG
, // ARM_DEBUG_STATE64,
95 e_regSetGPRCount
= ARM_THREAD_STATE64_COUNT
,
96 e_regSetVFPCount
= ARM_NEON_STATE64_COUNT
,
97 e_regSetEXCCount
= ARM_EXCEPTION_STATE64_COUNT
,
98 e_regSetDBGCount
= ARM_DEBUG_STATE64_COUNT
,
101 enum { Read
= 0, Write
= 1, kNumErrors
= 2 };
103 typedef arm_thread_state64_t GPR
;
104 typedef arm_neon_state64_t FPU
;
105 typedef arm_exception_state64_t EXC
;
107 static const DNBRegisterInfo g_gpr_registers
[];
108 static const DNBRegisterInfo g_vfp_registers
[];
109 static const DNBRegisterInfo g_exc_registers
[];
110 static const DNBRegisterSetInfo g_reg_sets
[];
112 static const size_t k_num_gpr_registers
;
113 static const size_t k_num_vfp_registers
;
114 static const size_t k_num_exc_registers
;
115 static const size_t k_num_all_registers
;
116 static const size_t k_num_register_sets
;
126 arm_debug_state64_t dbg
;
127 kern_return_t gpr_errs
[2]; // Read/Write errors
128 kern_return_t vfp_errs
[2]; // Read/Write errors
129 kern_return_t exc_errs
[2]; // Read/Write errors
130 kern_return_t dbg_errs
[2]; // Read/Write errors
133 for (i
= 0; i
< kNumErrors
; i
++) {
140 void InvalidateRegisterSetState(int set
) { SetError(set
, Read
, -1); }
142 void InvalidateAllRegisterStates() { SetError(e_regSetALL
, Read
, -1); }
144 kern_return_t
GetError(int set
, uint32_t err_idx
) const {
145 if (err_idx
< kNumErrors
) {
147 // When getting all errors, just OR all values together to see if
148 // we got any kind of error.
150 return gpr_errs
[err_idx
] | vfp_errs
[err_idx
] | exc_errs
[err_idx
] |
153 return gpr_errs
[err_idx
];
155 return vfp_errs
[err_idx
];
157 return exc_errs
[err_idx
];
158 // case e_regSetDBG: return dbg_errs[err_idx];
165 bool SetError(int set
, uint32_t err_idx
, kern_return_t err
) {
166 if (err_idx
< kNumErrors
) {
169 gpr_errs
[err_idx
] = err
;
170 vfp_errs
[err_idx
] = err
;
171 dbg_errs
[err_idx
] = err
;
172 exc_errs
[err_idx
] = err
;
176 gpr_errs
[err_idx
] = err
;
180 vfp_errs
[err_idx
] = err
;
184 exc_errs
[err_idx
] = err
;
188 // dbg_errs[err_idx] = err;
196 bool RegsAreValid(int set
) const {
197 return GetError(set
, Read
) == KERN_SUCCESS
;
201 kern_return_t
GetGPRState(bool force
);
202 kern_return_t
GetVFPState(bool force
);
203 kern_return_t
GetEXCState(bool force
);
204 kern_return_t
GetDBGState(bool force
);
206 kern_return_t
SetGPRState();
207 kern_return_t
SetVFPState();
208 kern_return_t
SetEXCState();
209 kern_return_t
SetDBGState(bool also_set_on_task
);
211 // Helper functions for watchpoint implementaions.
213 typedef arm_debug_state64_t DBG
;
215 void ClearWatchpointOccurred();
216 bool HasWatchpointOccurred();
217 bool IsWatchpointEnabled(const DBG
&debug_state
, uint32_t hw_index
);
218 nub_addr_t
GetWatchpointAddressByIndex(uint32_t hw_index
);
219 nub_addr_t
GetWatchAddress(const DBG
&debug_state
, uint32_t hw_index
);
220 virtual bool ReenableHardwareWatchpoint(uint32_t hw_break_index
);
221 virtual bool ReenableHardwareWatchpoint_helper(uint32_t hw_break_index
);
222 uint32_t GetHardwareWatchpointHit(nub_addr_t
&addr
) override
;
224 class disabled_watchpoint
{
226 disabled_watchpoint() {
235 MachThread
*m_thread
;
237 arm_debug_state64_t m_dbg_save
;
239 // arm64 doesn't keep the disabled watchpoint and breakpoint values in the
240 // debug register context like armv7;
241 // we need to save them aside when we disable them temporarily.
242 std::vector
<disabled_watchpoint
> m_disabled_watchpoints
;
243 std::vector
<disabled_watchpoint
> m_disabled_breakpoints
;
245 // The following member variables should be updated atomically.
246 int32_t m_watchpoint_hw_index
;
247 bool m_watchpoint_did_occur
;
248 bool m_watchpoint_resume_single_step_enabled
;
250 typedef std::map
<uint32_t, Context
> SaveRegisterStates
;
251 SaveRegisterStates m_saved_register_states
;
254 #endif // #if defined (ARM_THREAD_STATE64_COUNT)
255 #endif // #if defined (__arm__)
256 #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM64_DNBARCHIMPLARM64_H