1 //===-- DNBArchImpl.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 // Created by Greg Clayton on 6/25/07.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM_DNBARCHIMPL_H
14 #define LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM_DNBARCHIMPL_H
16 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
24 class DNBArchMachARM
: public DNBArchProtocol
{
26 enum { kMaxNumThumbITBreakpoints
= 4 };
28 DNBArchMachARM(MachThread
*thread
)
29 : m_thread(thread
), m_state(), m_disabled_watchpoints(),
30 m_hw_single_chained_step_addr(INVALID_NUB_ADDRESS
),
31 m_last_decode_pc(INVALID_NUB_ADDRESS
), m_watchpoint_hw_index(-1),
32 m_watchpoint_did_occur(false),
33 m_watchpoint_resume_single_step_enabled(false),
34 m_saved_register_states() {
35 m_disabled_watchpoints
.resize(16);
36 memset(&m_dbg_save
, 0, sizeof(m_dbg_save
));
37 #if defined(USE_ARM_DISASSEMBLER_FRAMEWORK)
38 ThumbStaticsInit(&m_last_decode_thumb
);
42 virtual ~DNBArchMachARM() {}
44 static void Initialize();
45 static const DNBRegisterSetInfo
*GetRegisterSetInfo(nub_size_t
*num_reg_sets
);
47 bool GetRegisterValue(uint32_t set
, uint32_t reg
,
48 DNBRegisterValue
*value
) override
;
49 bool SetRegisterValue(uint32_t set
, uint32_t reg
,
50 const DNBRegisterValue
*value
) override
;
51 nub_size_t
GetRegisterContext(void *buf
, nub_size_t buf_len
) override
;
52 nub_size_t
SetRegisterContext(const void *buf
, nub_size_t buf_len
) override
;
53 uint32_t SaveRegisterState() override
;
54 bool RestoreRegisterState(uint32_t save_id
) override
;
56 kern_return_t
GetRegisterState(int set
, bool force
) override
;
57 kern_return_t
SetRegisterState(int set
) override
;
58 bool RegisterSetStateIsValid(int set
) const override
;
60 uint64_t GetPC(uint64_t failValue
) override
; // Get program counter
61 kern_return_t
SetPC(uint64_t value
) override
;
62 uint64_t GetSP(uint64_t failValue
) override
; // Get stack pointer
63 void ThreadWillResume() override
;
64 bool ThreadDidStop() override
;
65 bool NotifyException(MachException::Data
&exc
) override
;
67 static DNBArchProtocol
*Create(MachThread
*thread
);
68 static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size
);
69 static uint32_t GetCPUType();
71 uint32_t NumSupportedHardwareBreakpoints() override
;
72 uint32_t NumSupportedHardwareWatchpoints() override
;
73 uint32_t EnableHardwareBreakpoint(nub_addr_t addr
, nub_size_t size
,
74 bool also_set_on_task
) override
;
75 bool DisableHardwareBreakpoint(uint32_t hw_break_index
,
76 bool also_set_on_task
) override
;
78 uint32_t EnableHardwareWatchpoint(nub_addr_t addr
, nub_size_t size
, bool read
,
79 bool write
, bool also_set_on_task
) override
;
80 bool DisableHardwareWatchpoint(uint32_t hw_break_index
,
81 bool also_set_on_task
) override
;
82 virtual bool DisableHardwareWatchpoint_helper(uint32_t hw_break_index
,
83 bool also_set_on_task
);
84 virtual bool ReenableHardwareWatchpoint(uint32_t hw_break_index
);
85 virtual bool ReenableHardwareWatchpoint_helper(uint32_t hw_break_index
);
87 virtual bool StepNotComplete() override
;
88 uint32_t GetHardwareWatchpointHit(nub_addr_t
&addr
) override
;
90 #if defined(ARM_DEBUG_STATE32) && (defined(__arm64__) || defined(__aarch64__))
91 typedef arm_debug_state32_t DBG
;
93 typedef arm_debug_state_t DBG
;
97 kern_return_t
EnableHardwareSingleStep(bool enable
);
98 kern_return_t
SetSingleStepSoftwareBreakpoints();
100 bool ConditionPassed(uint8_t condition
, uint32_t cpsr
);
101 #if defined(USE_ARM_DISASSEMBLER_FRAMEWORK)
102 bool ComputeNextPC(nub_addr_t currentPC
,
103 arm_decoded_instruction_t decodedInstruction
,
104 bool currentPCIsThumb
, nub_addr_t
*targetPC
);
105 arm_error_t
DecodeInstructionUsingDisassembler(
106 nub_addr_t curr_pc
, uint32_t curr_cpsr
,
107 arm_decoded_instruction_t
*decodedInstruction
,
108 thumb_static_data_t
*thumbStaticData
, nub_addr_t
*next_pc
);
109 void DecodeITBlockInstructions(nub_addr_t curr_pc
);
111 void EvaluateNextInstructionForSoftwareBreakpointSetup(nub_addr_t currentPC
,
113 bool currentPCIsThumb
,
115 bool *nextPCIsThumb
);
118 e_regSetALL
= REGISTER_SET_ALL
,
119 e_regSetGPR
, // ARM_THREAD_STATE
120 e_regSetVFP
, // ARM_VFP_STATE (ARM_NEON_STATE if defined __arm64__)
121 e_regSetEXC
, // ARM_EXCEPTION_STATE
122 e_regSetDBG
, // ARM_DEBUG_STATE (ARM_DEBUG_STATE32 if defined __arm64__)
126 enum { Read
= 0, Write
= 1, kNumErrors
= 2 };
128 typedef arm_thread_state_t GPR
;
129 #if defined(__arm64__) || defined(__aarch64__)
130 typedef arm_neon_state_t FPU
;
132 typedef arm_vfp_state_t FPU
;
134 typedef arm_exception_state_t EXC
;
136 static const DNBRegisterInfo g_gpr_registers
[];
137 static const DNBRegisterInfo g_vfp_registers
[];
138 static const DNBRegisterInfo g_exc_registers
[];
139 static const DNBRegisterSetInfo g_reg_sets
[];
141 static const size_t k_num_gpr_registers
;
142 static const size_t k_num_vfp_registers
;
143 static const size_t k_num_exc_registers
;
144 static const size_t k_num_all_registers
;
145 static const size_t k_num_register_sets
;
156 kern_return_t gpr_errs
[2]; // Read/Write errors
157 kern_return_t vfp_errs
[2]; // Read/Write errors
158 kern_return_t exc_errs
[2]; // Read/Write errors
159 kern_return_t dbg_errs
[2]; // Read/Write errors
162 for (i
= 0; i
< kNumErrors
; i
++) {
169 void InvalidateRegisterSetState(int set
) { SetError(set
, Read
, -1); }
170 kern_return_t
GetError(int set
, uint32_t err_idx
) const {
171 if (err_idx
< kNumErrors
) {
173 // When getting all errors, just OR all values together to see if
174 // we got any kind of error.
176 return gpr_errs
[err_idx
] | vfp_errs
[err_idx
] | exc_errs
[err_idx
] |
179 return gpr_errs
[err_idx
];
181 return vfp_errs
[err_idx
];
183 return exc_errs
[err_idx
];
185 return dbg_errs
[err_idx
];
192 bool SetError(int set
, uint32_t err_idx
, kern_return_t err
) {
193 if (err_idx
< kNumErrors
) {
196 gpr_errs
[err_idx
] = err
;
197 vfp_errs
[err_idx
] = err
;
198 dbg_errs
[err_idx
] = err
;
199 exc_errs
[err_idx
] = err
;
203 gpr_errs
[err_idx
] = err
;
207 vfp_errs
[err_idx
] = err
;
211 exc_errs
[err_idx
] = err
;
215 dbg_errs
[err_idx
] = err
;
223 bool RegsAreValid(int set
) const {
224 return GetError(set
, Read
) == KERN_SUCCESS
;
228 kern_return_t
GetGPRState(bool force
);
229 kern_return_t
GetVFPState(bool force
);
230 kern_return_t
GetEXCState(bool force
);
231 kern_return_t
GetDBGState(bool force
);
233 kern_return_t
SetGPRState();
234 kern_return_t
SetVFPState();
235 kern_return_t
SetEXCState();
236 kern_return_t
SetDBGState(bool also_set_on_task
);
238 bool IsWatchpointEnabled(const DBG
&debug_state
, uint32_t hw_index
);
239 nub_addr_t
GetWatchpointAddressByIndex(uint32_t hw_index
);
240 nub_addr_t
GetWatchAddress(const DBG
&debug_state
, uint32_t hw_index
);
242 class disabled_watchpoint
{
244 disabled_watchpoint() {
253 MachThread
*m_thread
;
257 // armv8 doesn't keep the disabled watchpoint values in the debug register
258 // context like armv7;
259 // we need to save them aside when we disable them temporarily.
260 std::vector
<disabled_watchpoint
> m_disabled_watchpoints
;
262 nub_addr_t m_hw_single_chained_step_addr
;
263 nub_addr_t m_last_decode_pc
;
265 // The following member variables should be updated atomically.
266 int32_t m_watchpoint_hw_index
;
267 bool m_watchpoint_did_occur
;
268 bool m_watchpoint_resume_single_step_enabled
;
270 typedef std::map
<uint32_t, Context
> SaveRegisterStates
;
271 SaveRegisterStates m_saved_register_states
;
274 #endif // #if defined (__arm__)
275 #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM_DNBARCHIMPL_H