1061da546Spatrick //===-- DNBArchImpl.h -------------------------------------------*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick //
9061da546Spatrick //  Created by Greg Clayton on 6/25/07.
10061da546Spatrick //
11061da546Spatrick //===----------------------------------------------------------------------===//
12061da546Spatrick 
13dda28197Spatrick #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM_DNBARCHIMPL_H
14dda28197Spatrick #define LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM_DNBARCHIMPL_H
15061da546Spatrick 
16061da546Spatrick #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
17061da546Spatrick 
18061da546Spatrick #include "DNBArch.h"
19061da546Spatrick 
20061da546Spatrick #include <map>
21061da546Spatrick 
22061da546Spatrick class MachThread;
23061da546Spatrick 
24061da546Spatrick class DNBArchMachARM : public DNBArchProtocol {
25061da546Spatrick public:
26061da546Spatrick   enum { kMaxNumThumbITBreakpoints = 4 };
27061da546Spatrick 
DNBArchMachARM(MachThread * thread)28061da546Spatrick   DNBArchMachARM(MachThread *thread)
29061da546Spatrick       : m_thread(thread), m_state(), m_disabled_watchpoints(),
30061da546Spatrick         m_hw_single_chained_step_addr(INVALID_NUB_ADDRESS),
31061da546Spatrick         m_last_decode_pc(INVALID_NUB_ADDRESS), m_watchpoint_hw_index(-1),
32061da546Spatrick         m_watchpoint_did_occur(false),
33061da546Spatrick         m_watchpoint_resume_single_step_enabled(false),
34061da546Spatrick         m_saved_register_states() {
35061da546Spatrick     m_disabled_watchpoints.resize(16);
36061da546Spatrick     memset(&m_dbg_save, 0, sizeof(m_dbg_save));
37061da546Spatrick #if defined(USE_ARM_DISASSEMBLER_FRAMEWORK)
38061da546Spatrick     ThumbStaticsInit(&m_last_decode_thumb);
39061da546Spatrick #endif
40061da546Spatrick   }
41061da546Spatrick 
~DNBArchMachARM()42061da546Spatrick   virtual ~DNBArchMachARM() {}
43061da546Spatrick 
44061da546Spatrick   static void Initialize();
45061da546Spatrick   static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets);
46061da546Spatrick 
47*be691f3bSpatrick   bool GetRegisterValue(uint32_t set, uint32_t reg,
48*be691f3bSpatrick                         DNBRegisterValue *value) override;
49*be691f3bSpatrick   bool SetRegisterValue(uint32_t set, uint32_t reg,
50*be691f3bSpatrick                         const DNBRegisterValue *value) override;
51*be691f3bSpatrick   nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len) override;
52*be691f3bSpatrick   nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len) override;
53*be691f3bSpatrick   uint32_t SaveRegisterState() override;
54*be691f3bSpatrick   bool RestoreRegisterState(uint32_t save_id) override;
55061da546Spatrick 
56*be691f3bSpatrick   kern_return_t GetRegisterState(int set, bool force) override;
57*be691f3bSpatrick   kern_return_t SetRegisterState(int set) override;
58*be691f3bSpatrick   bool RegisterSetStateIsValid(int set) const override;
59061da546Spatrick 
60*be691f3bSpatrick   uint64_t GetPC(uint64_t failValue) override; // Get program counter
61*be691f3bSpatrick   kern_return_t SetPC(uint64_t value) override;
62*be691f3bSpatrick   uint64_t GetSP(uint64_t failValue) override; // Get stack pointer
63*be691f3bSpatrick   void ThreadWillResume() override;
64*be691f3bSpatrick   bool ThreadDidStop() override;
65*be691f3bSpatrick   bool NotifyException(MachException::Data &exc) override;
66061da546Spatrick 
67061da546Spatrick   static DNBArchProtocol *Create(MachThread *thread);
68061da546Spatrick   static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size);
69061da546Spatrick   static uint32_t GetCPUType();
70061da546Spatrick 
71*be691f3bSpatrick   uint32_t NumSupportedHardwareBreakpoints() override;
72*be691f3bSpatrick   uint32_t NumSupportedHardwareWatchpoints() override;
73*be691f3bSpatrick   uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size,
74*be691f3bSpatrick                                     bool also_set_on_task) override;
75*be691f3bSpatrick   bool DisableHardwareBreakpoint(uint32_t hw_break_index,
76*be691f3bSpatrick                                  bool also_set_on_task) override;
77061da546Spatrick 
78*be691f3bSpatrick   uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, bool read,
79*be691f3bSpatrick                                     bool write, bool also_set_on_task) override;
80*be691f3bSpatrick   bool DisableHardwareWatchpoint(uint32_t hw_break_index,
81*be691f3bSpatrick                                  bool also_set_on_task) override;
82061da546Spatrick   virtual bool DisableHardwareWatchpoint_helper(uint32_t hw_break_index,
83061da546Spatrick                                                 bool also_set_on_task);
84061da546Spatrick   virtual bool ReenableHardwareWatchpoint(uint32_t hw_break_index);
85061da546Spatrick   virtual bool ReenableHardwareWatchpoint_helper(uint32_t hw_break_index);
86061da546Spatrick 
87*be691f3bSpatrick   virtual bool StepNotComplete() override;
88*be691f3bSpatrick   uint32_t GetHardwareWatchpointHit(nub_addr_t &addr) override;
89061da546Spatrick 
90061da546Spatrick #if defined(ARM_DEBUG_STATE32) && (defined(__arm64__) || defined(__aarch64__))
91061da546Spatrick   typedef arm_debug_state32_t DBG;
92061da546Spatrick #else
93061da546Spatrick   typedef arm_debug_state_t DBG;
94061da546Spatrick #endif
95061da546Spatrick 
96061da546Spatrick protected:
97061da546Spatrick   kern_return_t EnableHardwareSingleStep(bool enable);
98061da546Spatrick   kern_return_t SetSingleStepSoftwareBreakpoints();
99061da546Spatrick 
100061da546Spatrick   bool ConditionPassed(uint8_t condition, uint32_t cpsr);
101061da546Spatrick #if defined(USE_ARM_DISASSEMBLER_FRAMEWORK)
102061da546Spatrick   bool ComputeNextPC(nub_addr_t currentPC,
103061da546Spatrick                      arm_decoded_instruction_t decodedInstruction,
104061da546Spatrick                      bool currentPCIsThumb, nub_addr_t *targetPC);
105061da546Spatrick   arm_error_t DecodeInstructionUsingDisassembler(
106061da546Spatrick       nub_addr_t curr_pc, uint32_t curr_cpsr,
107061da546Spatrick       arm_decoded_instruction_t *decodedInstruction,
108061da546Spatrick       thumb_static_data_t *thumbStaticData, nub_addr_t *next_pc);
109061da546Spatrick   void DecodeITBlockInstructions(nub_addr_t curr_pc);
110061da546Spatrick #endif
111061da546Spatrick   void EvaluateNextInstructionForSoftwareBreakpointSetup(nub_addr_t currentPC,
112061da546Spatrick                                                          uint32_t cpsr,
113061da546Spatrick                                                          bool currentPCIsThumb,
114061da546Spatrick                                                          nub_addr_t *nextPC,
115061da546Spatrick                                                          bool *nextPCIsThumb);
116061da546Spatrick 
117061da546Spatrick   enum RegisterSet {
118061da546Spatrick     e_regSetALL = REGISTER_SET_ALL,
119061da546Spatrick     e_regSetGPR, // ARM_THREAD_STATE
120061da546Spatrick     e_regSetVFP, // ARM_VFP_STATE (ARM_NEON_STATE if defined __arm64__)
121061da546Spatrick     e_regSetEXC, // ARM_EXCEPTION_STATE
122061da546Spatrick     e_regSetDBG, // ARM_DEBUG_STATE (ARM_DEBUG_STATE32 if defined __arm64__)
123061da546Spatrick     kNumRegisterSets
124061da546Spatrick   };
125061da546Spatrick 
126061da546Spatrick   enum { Read = 0, Write = 1, kNumErrors = 2 };
127061da546Spatrick 
128061da546Spatrick   typedef arm_thread_state_t GPR;
129061da546Spatrick #if defined(__arm64__) || defined(__aarch64__)
130061da546Spatrick   typedef arm_neon_state_t FPU;
131061da546Spatrick #else
132061da546Spatrick   typedef arm_vfp_state_t FPU;
133061da546Spatrick #endif
134061da546Spatrick   typedef arm_exception_state_t EXC;
135061da546Spatrick 
136061da546Spatrick   static const DNBRegisterInfo g_gpr_registers[];
137061da546Spatrick   static const DNBRegisterInfo g_vfp_registers[];
138061da546Spatrick   static const DNBRegisterInfo g_exc_registers[];
139061da546Spatrick   static const DNBRegisterSetInfo g_reg_sets[];
140061da546Spatrick 
141061da546Spatrick   static const size_t k_num_gpr_registers;
142061da546Spatrick   static const size_t k_num_vfp_registers;
143061da546Spatrick   static const size_t k_num_exc_registers;
144061da546Spatrick   static const size_t k_num_all_registers;
145061da546Spatrick   static const size_t k_num_register_sets;
146061da546Spatrick 
147061da546Spatrick   struct Context {
148061da546Spatrick     GPR gpr;
149061da546Spatrick     FPU vfp;
150061da546Spatrick     EXC exc;
151061da546Spatrick   };
152061da546Spatrick 
153061da546Spatrick   struct State {
154061da546Spatrick     Context context;
155061da546Spatrick     DBG dbg;
156061da546Spatrick     kern_return_t gpr_errs[2]; // Read/Write errors
157061da546Spatrick     kern_return_t vfp_errs[2]; // Read/Write errors
158061da546Spatrick     kern_return_t exc_errs[2]; // Read/Write errors
159061da546Spatrick     kern_return_t dbg_errs[2]; // Read/Write errors
StateState160061da546Spatrick     State() {
161061da546Spatrick       uint32_t i;
162061da546Spatrick       for (i = 0; i < kNumErrors; i++) {
163061da546Spatrick         gpr_errs[i] = -1;
164061da546Spatrick         vfp_errs[i] = -1;
165061da546Spatrick         exc_errs[i] = -1;
166061da546Spatrick         dbg_errs[i] = -1;
167061da546Spatrick       }
168061da546Spatrick     }
InvalidateRegisterSetStateState169061da546Spatrick     void InvalidateRegisterSetState(int set) { SetError(set, Read, -1); }
GetErrorState170061da546Spatrick     kern_return_t GetError(int set, uint32_t err_idx) const {
171061da546Spatrick       if (err_idx < kNumErrors) {
172061da546Spatrick         switch (set) {
173061da546Spatrick         // When getting all errors, just OR all values together to see if
174061da546Spatrick         // we got any kind of error.
175061da546Spatrick         case e_regSetALL:
176061da546Spatrick           return gpr_errs[err_idx] | vfp_errs[err_idx] | exc_errs[err_idx] |
177061da546Spatrick                  dbg_errs[err_idx];
178061da546Spatrick         case e_regSetGPR:
179061da546Spatrick           return gpr_errs[err_idx];
180061da546Spatrick         case e_regSetVFP:
181061da546Spatrick           return vfp_errs[err_idx];
182061da546Spatrick         case e_regSetEXC:
183061da546Spatrick           return exc_errs[err_idx];
184061da546Spatrick         case e_regSetDBG:
185061da546Spatrick           return dbg_errs[err_idx];
186061da546Spatrick         default:
187061da546Spatrick           break;
188061da546Spatrick         }
189061da546Spatrick       }
190061da546Spatrick       return -1;
191061da546Spatrick     }
SetErrorState192061da546Spatrick     bool SetError(int set, uint32_t err_idx, kern_return_t err) {
193061da546Spatrick       if (err_idx < kNumErrors) {
194061da546Spatrick         switch (set) {
195061da546Spatrick         case e_regSetALL:
196061da546Spatrick           gpr_errs[err_idx] = err;
197061da546Spatrick           vfp_errs[err_idx] = err;
198061da546Spatrick           dbg_errs[err_idx] = err;
199061da546Spatrick           exc_errs[err_idx] = err;
200061da546Spatrick           return true;
201061da546Spatrick 
202061da546Spatrick         case e_regSetGPR:
203061da546Spatrick           gpr_errs[err_idx] = err;
204061da546Spatrick           return true;
205061da546Spatrick 
206061da546Spatrick         case e_regSetVFP:
207061da546Spatrick           vfp_errs[err_idx] = err;
208061da546Spatrick           return true;
209061da546Spatrick 
210061da546Spatrick         case e_regSetEXC:
211061da546Spatrick           exc_errs[err_idx] = err;
212061da546Spatrick           return true;
213061da546Spatrick 
214061da546Spatrick         case e_regSetDBG:
215061da546Spatrick           dbg_errs[err_idx] = err;
216061da546Spatrick           return true;
217061da546Spatrick         default:
218061da546Spatrick           break;
219061da546Spatrick         }
220061da546Spatrick       }
221061da546Spatrick       return false;
222061da546Spatrick     }
RegsAreValidState223061da546Spatrick     bool RegsAreValid(int set) const {
224061da546Spatrick       return GetError(set, Read) == KERN_SUCCESS;
225061da546Spatrick     }
226061da546Spatrick   };
227061da546Spatrick 
228061da546Spatrick   kern_return_t GetGPRState(bool force);
229061da546Spatrick   kern_return_t GetVFPState(bool force);
230061da546Spatrick   kern_return_t GetEXCState(bool force);
231061da546Spatrick   kern_return_t GetDBGState(bool force);
232061da546Spatrick 
233061da546Spatrick   kern_return_t SetGPRState();
234061da546Spatrick   kern_return_t SetVFPState();
235061da546Spatrick   kern_return_t SetEXCState();
236061da546Spatrick   kern_return_t SetDBGState(bool also_set_on_task);
237061da546Spatrick 
238061da546Spatrick   bool IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index);
239061da546Spatrick   nub_addr_t GetWatchpointAddressByIndex(uint32_t hw_index);
240061da546Spatrick   nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index);
241061da546Spatrick 
242061da546Spatrick   class disabled_watchpoint {
243061da546Spatrick   public:
disabled_watchpoint()244061da546Spatrick     disabled_watchpoint() {
245061da546Spatrick       addr = 0;
246061da546Spatrick       control = 0;
247061da546Spatrick     }
248061da546Spatrick     nub_addr_t addr;
249061da546Spatrick     uint32_t control;
250061da546Spatrick   };
251061da546Spatrick 
252061da546Spatrick protected:
253061da546Spatrick   MachThread *m_thread;
254061da546Spatrick   State m_state;
255061da546Spatrick   DBG m_dbg_save;
256061da546Spatrick 
257061da546Spatrick   // armv8 doesn't keep the disabled watchpoint values in the debug register
258061da546Spatrick   // context like armv7;
259061da546Spatrick   // we need to save them aside when we disable them temporarily.
260061da546Spatrick   std::vector<disabled_watchpoint> m_disabled_watchpoints;
261061da546Spatrick 
262061da546Spatrick   nub_addr_t m_hw_single_chained_step_addr;
263061da546Spatrick   nub_addr_t m_last_decode_pc;
264061da546Spatrick 
265061da546Spatrick   // The following member variables should be updated atomically.
266061da546Spatrick   int32_t m_watchpoint_hw_index;
267061da546Spatrick   bool m_watchpoint_did_occur;
268061da546Spatrick   bool m_watchpoint_resume_single_step_enabled;
269061da546Spatrick 
270061da546Spatrick   typedef std::map<uint32_t, Context> SaveRegisterStates;
271061da546Spatrick   SaveRegisterStates m_saved_register_states;
272061da546Spatrick };
273061da546Spatrick 
274061da546Spatrick #endif // #if defined (__arm__)
275dda28197Spatrick #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM_DNBARCHIMPL_H
276