]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.h
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / tools / debugserver / source / MacOSX / arm64 / DNBArchImplARM64.h
1 //===-- DNBArchMachARM64.h --------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef __DNBArchImplARM64_h__
11 #define __DNBArchImplARM64_h__
12
13 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
14
15 #include <mach/thread_status.h>
16 #include <map>
17
18 #if defined(ARM_THREAD_STATE64_COUNT)
19
20 #include "DNBArch.h"
21
22 class MachThread;
23
24 class DNBArchMachARM64 : public DNBArchProtocol {
25 public:
26   enum { kMaxNumThumbITBreakpoints = 4 };
27
28   DNBArchMachARM64(MachThread *thread)
29       : m_thread(thread), m_state(), m_disabled_watchpoints(),
30         m_watchpoint_hw_index(-1), 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     memset(&m_dbg_save, 0, sizeof(m_dbg_save));
35   }
36
37   virtual ~DNBArchMachARM64() {}
38
39   static void Initialize();
40   static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets);
41
42   virtual bool GetRegisterValue(uint32_t set, uint32_t reg,
43                                 DNBRegisterValue *value);
44   virtual bool SetRegisterValue(uint32_t set, uint32_t reg,
45                                 const DNBRegisterValue *value);
46   virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len);
47   virtual nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len);
48   virtual uint32_t SaveRegisterState();
49   virtual bool RestoreRegisterState(uint32_t save_id);
50
51   virtual kern_return_t GetRegisterState(int set, bool force);
52   virtual kern_return_t SetRegisterState(int set);
53   virtual bool RegisterSetStateIsValid(int set) const;
54
55   virtual uint64_t GetPC(uint64_t failValue); // Get program counter
56   virtual kern_return_t SetPC(uint64_t value);
57   virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer
58   virtual void ThreadWillResume();
59   virtual bool ThreadDidStop();
60   virtual bool NotifyException(MachException::Data &exc);
61
62   static DNBArchProtocol *Create(MachThread *thread);
63   static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size);
64   static uint32_t GetCPUType();
65
66   virtual uint32_t NumSupportedHardwareWatchpoints();
67   virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size,
68                                             bool read, bool write,
69                                             bool also_set_on_task);
70   virtual bool DisableHardwareWatchpoint(uint32_t hw_break_index,
71                                          bool also_set_on_task);
72   virtual bool DisableHardwareWatchpoint_helper(uint32_t hw_break_index,
73                                                 bool also_set_on_task);
74
75 protected:
76   kern_return_t EnableHardwareSingleStep(bool enable);
77   static bool FixGenericRegisterNumber(uint32_t &set, uint32_t &reg);
78
79   typedef enum RegisterSetTag {
80     e_regSetALL = REGISTER_SET_ALL,
81     e_regSetGPR, // ARM_THREAD_STATE64,
82     e_regSetVFP, // ARM_NEON_STATE64,
83     e_regSetEXC, // ARM_EXCEPTION_STATE64,
84     e_regSetDBG, // ARM_DEBUG_STATE64,
85     kNumRegisterSets
86   } RegisterSet;
87
88   enum {
89     e_regSetGPRCount = ARM_THREAD_STATE64_COUNT,
90     e_regSetVFPCount = ARM_NEON_STATE64_COUNT,
91     e_regSetEXCCount = ARM_EXCEPTION_STATE64_COUNT,
92     e_regSetDBGCount = ARM_DEBUG_STATE64_COUNT,
93   };
94
95   enum { Read = 0, Write = 1, kNumErrors = 2 };
96
97   typedef arm_thread_state64_t GPR;
98   typedef arm_neon_state64_t FPU;
99   typedef arm_exception_state64_t EXC;
100
101   static const DNBRegisterInfo g_gpr_registers[];
102   static const DNBRegisterInfo g_vfp_registers[];
103   static const DNBRegisterInfo g_exc_registers[];
104   static const DNBRegisterSetInfo g_reg_sets[];
105
106   static const size_t k_num_gpr_registers;
107   static const size_t k_num_vfp_registers;
108   static const size_t k_num_exc_registers;
109   static const size_t k_num_all_registers;
110   static const size_t k_num_register_sets;
111
112   struct Context {
113     GPR gpr;
114     FPU vfp;
115     EXC exc;
116   };
117
118   struct State {
119     Context context;
120     arm_debug_state64_t dbg;
121     kern_return_t gpr_errs[2]; // Read/Write errors
122     kern_return_t vfp_errs[2]; // Read/Write errors
123     kern_return_t exc_errs[2]; // Read/Write errors
124     kern_return_t dbg_errs[2]; // Read/Write errors
125     State() {
126       uint32_t i;
127       for (i = 0; i < kNumErrors; i++) {
128         gpr_errs[i] = -1;
129         vfp_errs[i] = -1;
130         exc_errs[i] = -1;
131         dbg_errs[i] = -1;
132       }
133     }
134     void InvalidateRegisterSetState(int set) { SetError(set, Read, -1); }
135
136     void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); }
137
138     kern_return_t GetError(int set, uint32_t err_idx) const {
139       if (err_idx < kNumErrors) {
140         switch (set) {
141         // When getting all errors, just OR all values together to see if
142         // we got any kind of error.
143         case e_regSetALL:
144           return gpr_errs[err_idx] | vfp_errs[err_idx] | exc_errs[err_idx] |
145                  dbg_errs[err_idx];
146         case e_regSetGPR:
147           return gpr_errs[err_idx];
148         case e_regSetVFP:
149           return vfp_errs[err_idx];
150         case e_regSetEXC:
151           return exc_errs[err_idx];
152         // case e_regSetDBG:   return dbg_errs[err_idx];
153         default:
154           break;
155         }
156       }
157       return -1;
158     }
159     bool SetError(int set, uint32_t err_idx, kern_return_t err) {
160       if (err_idx < kNumErrors) {
161         switch (set) {
162         case e_regSetALL:
163           gpr_errs[err_idx] = err;
164           vfp_errs[err_idx] = err;
165           dbg_errs[err_idx] = err;
166           exc_errs[err_idx] = err;
167           return true;
168
169         case e_regSetGPR:
170           gpr_errs[err_idx] = err;
171           return true;
172
173         case e_regSetVFP:
174           vfp_errs[err_idx] = err;
175           return true;
176
177         case e_regSetEXC:
178           exc_errs[err_idx] = err;
179           return true;
180
181         //                case e_regSetDBG:
182         //                    dbg_errs[err_idx] = err;
183         //                    return true;
184         default:
185           break;
186         }
187       }
188       return false;
189     }
190     bool RegsAreValid(int set) const {
191       return GetError(set, Read) == KERN_SUCCESS;
192     }
193   };
194
195   kern_return_t GetGPRState(bool force);
196   kern_return_t GetVFPState(bool force);
197   kern_return_t GetEXCState(bool force);
198   kern_return_t GetDBGState(bool force);
199
200   kern_return_t SetGPRState();
201   kern_return_t SetVFPState();
202   kern_return_t SetEXCState();
203   kern_return_t SetDBGState(bool also_set_on_task);
204
205   // Helper functions for watchpoint implementaions.
206
207   typedef arm_debug_state64_t DBG;
208
209   void ClearWatchpointOccurred();
210   bool HasWatchpointOccurred();
211   bool IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index);
212   nub_addr_t GetWatchpointAddressByIndex(uint32_t hw_index);
213   nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index);
214   virtual bool ReenableHardwareWatchpoint(uint32_t hw_break_index);
215   virtual bool ReenableHardwareWatchpoint_helper(uint32_t hw_break_index);
216   virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr);
217
218   class disabled_watchpoint {
219   public:
220     disabled_watchpoint() {
221       addr = 0;
222       control = 0;
223     }
224     nub_addr_t addr;
225     uint32_t control;
226   };
227
228 protected:
229   MachThread *m_thread;
230   State m_state;
231   arm_debug_state64_t m_dbg_save;
232
233   // arm64 doesn't keep the disabled watchpoint values in the debug register
234   // context like armv7;
235   // we need to save them aside when we disable them temporarily.
236   std::vector<disabled_watchpoint> m_disabled_watchpoints;
237
238   // The following member variables should be updated atomically.
239   int32_t m_watchpoint_hw_index;
240   bool m_watchpoint_did_occur;
241   bool m_watchpoint_resume_single_step_enabled;
242
243   typedef std::map<uint32_t, Context> SaveRegisterStates;
244   SaveRegisterStates m_saved_register_states;
245 };
246
247 #endif // #if defined (ARM_THREAD_STATE64_COUNT)
248 #endif // #if defined (__arm__)
249 #endif // #ifndef __DNBArchImplARM64_h__