1 //===-- DNBArchImplX86_64.h -------------------------------------*- C++ -*-===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Created by Greg Clayton on 6/25/07. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_X86_64_DNBARCHIMPLX86_64_H 14 #define LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_X86_64_DNBARCHIMPLX86_64_H 15 16 #if defined(__i386__) || defined(__x86_64__) 17 #include "DNBArch.h" 18 #include "MachRegisterStatesX86_64.h" 19 20 #include <map> 21 22 class MachThread; 23 24 class DNBArchImplX86_64 : public DNBArchProtocol { 25 public: 26 DNBArchImplX86_64(MachThread *thread) 27 : DNBArchProtocol(), m_thread(thread), m_state(), m_2pc_dbg_checkpoint(), 28 m_2pc_trans_state(Trans_Done), m_saved_register_states() {} 29 virtual ~DNBArchImplX86_64() {} 30 31 static void Initialize(); 32 33 bool GetRegisterValue(uint32_t set, uint32_t reg, 34 DNBRegisterValue *value) override; 35 bool SetRegisterValue(uint32_t set, uint32_t reg, 36 const DNBRegisterValue *value) override; 37 nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len) override; 38 nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len) override; 39 uint32_t SaveRegisterState() override; 40 bool RestoreRegisterState(uint32_t save_id) override; 41 42 kern_return_t GetRegisterState(int set, bool force) override; 43 kern_return_t SetRegisterState(int set) override; 44 bool RegisterSetStateIsValid(int set) const override; 45 46 uint64_t GetPC(uint64_t failValue) override; // Get program counter 47 kern_return_t SetPC(uint64_t value) override; 48 uint64_t GetSP(uint64_t failValue) override; // Get stack pointer 49 void ThreadWillResume() override; 50 bool ThreadDidStop() override; 51 bool NotifyException(MachException::Data &exc) override; 52 53 uint32_t NumSupportedHardwareBreakpoints() override; 54 uint32_t NumSupportedHardwareWatchpoints() override; 55 56 uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size, 57 bool also_set_on_task) override; 58 bool DisableHardwareBreakpoint(uint32_t hw_break_index, 59 bool also_set_on_task) override; 60 uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, 61 bool read, bool write, 62 bool also_set_on_task) override; 63 bool DisableHardwareWatchpoint(uint32_t hw_break_index, 64 bool also_set_on_task) override; 65 uint32_t GetHardwareWatchpointHit(nub_addr_t &addr) override; 66 67 protected: 68 kern_return_t EnableHardwareSingleStep(bool enable); 69 70 typedef __x86_64_thread_state_t GPR; 71 typedef __x86_64_float_state_t FPU; 72 typedef __x86_64_exception_state_t EXC; 73 typedef __x86_64_avx_state_t AVX; 74 typedef __x86_64_debug_state_t DBG; 75 76 static const DNBRegisterInfo g_gpr_registers[]; 77 static const DNBRegisterInfo g_fpu_registers_no_avx[]; 78 static const DNBRegisterInfo g_fpu_registers_avx[]; 79 static const DNBRegisterInfo g_exc_registers[]; 80 static const DNBRegisterSetInfo g_reg_sets_no_avx[]; 81 static const DNBRegisterSetInfo g_reg_sets_avx[]; 82 static const size_t k_num_gpr_registers; 83 static const size_t k_num_fpu_registers_no_avx; 84 static const size_t k_num_fpu_registers_avx; 85 static const size_t k_num_exc_registers; 86 static const size_t k_num_all_registers_no_avx; 87 static const size_t k_num_all_registers_avx; 88 static const size_t k_num_register_sets; 89 90 typedef __x86_64_avx512f_state_t AVX512F; 91 static const DNBRegisterInfo g_fpu_registers_avx512f[]; 92 static const DNBRegisterSetInfo g_reg_sets_avx512f[]; 93 static const size_t k_num_fpu_registers_avx512f; 94 static const size_t k_num_all_registers_avx512f; 95 96 enum RegisterSet { 97 e_regSetALL = REGISTER_SET_ALL, 98 e_regSetGPR, 99 e_regSetFPU, 100 e_regSetEXC, 101 e_regSetDBG, 102 kNumRegisterSets 103 }; 104 105 enum RegisterSetWordSize { 106 e_regSetWordSizeGPR = (sizeof(GPR) - 32) / sizeof(int), 107 e_regSetWordSizeGPRFull = sizeof(GPR) / sizeof(int), 108 e_regSetWordSizeFPU = sizeof(FPU) / sizeof(int), 109 e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int), 110 e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int), 111 e_regSetWordSizeAVX512f = sizeof(AVX512F) / sizeof(int), 112 e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int) 113 }; 114 115 enum { Read = 0, Write = 1, kNumErrors = 2 }; 116 117 struct Context { 118 GPR gpr; 119 union { 120 FPU no_avx; 121 AVX avx; 122 AVX512F avx512f; 123 } fpu; 124 EXC exc; 125 DBG dbg; 126 }; 127 128 struct State { 129 Context context; 130 kern_return_t gpr_errs[2]; // Read/Write errors 131 kern_return_t fpu_errs[2]; // Read/Write errors 132 kern_return_t exc_errs[2]; // Read/Write errors 133 kern_return_t dbg_errs[2]; // Read/Write errors 134 bool hasFullGPRState; 135 136 State() { 137 uint32_t i; 138 for (i = 0; i < kNumErrors; i++) { 139 gpr_errs[i] = -1; 140 fpu_errs[i] = -1; 141 exc_errs[i] = -1; 142 dbg_errs[i] = -1; 143 } 144 } 145 146 void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); } 147 148 kern_return_t GetError(int flavor, uint32_t err_idx) const { 149 if (err_idx < kNumErrors) { 150 switch (flavor) { 151 // When getting all errors, just OR all values together to see if 152 // we got any kind of error. 153 case e_regSetALL: 154 return gpr_errs[err_idx] | fpu_errs[err_idx] | exc_errs[err_idx]; 155 case e_regSetGPR: 156 return gpr_errs[err_idx]; 157 case e_regSetFPU: 158 return fpu_errs[err_idx]; 159 case e_regSetEXC: 160 return exc_errs[err_idx]; 161 case e_regSetDBG: 162 return dbg_errs[err_idx]; 163 default: 164 break; 165 } 166 } 167 return -1; 168 } 169 170 bool SetError(int flavor, uint32_t err_idx, kern_return_t err) { 171 if (err_idx < kNumErrors) { 172 switch (flavor) { 173 case e_regSetALL: 174 gpr_errs[err_idx] = fpu_errs[err_idx] = exc_errs[err_idx] = 175 dbg_errs[err_idx] = err; 176 return true; 177 178 case e_regSetGPR: 179 gpr_errs[err_idx] = err; 180 return true; 181 182 case e_regSetFPU: 183 fpu_errs[err_idx] = err; 184 return true; 185 186 case e_regSetEXC: 187 exc_errs[err_idx] = err; 188 return true; 189 190 case e_regSetDBG: 191 dbg_errs[err_idx] = err; 192 return true; 193 194 default: 195 break; 196 } 197 } 198 return false; 199 } 200 201 bool RegsAreValid(int flavor) const { 202 return GetError(flavor, Read) == KERN_SUCCESS; 203 } 204 }; 205 206 kern_return_t GetGPRState(bool force); 207 kern_return_t GetFPUState(bool force); 208 kern_return_t GetEXCState(bool force); 209 kern_return_t GetDBGState(bool force); 210 211 kern_return_t SetGPRState(); 212 kern_return_t SetFPUState(); 213 kern_return_t SetEXCState(); 214 kern_return_t SetDBGState(bool also_set_on_task); 215 216 static DNBArchProtocol *Create(MachThread *thread); 217 218 static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); 219 220 static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); 221 222 static uint32_t GetRegisterContextSize(); 223 224 static void SetHardwareBreakpoint(DBG &debug_state, uint32_t hw_index, 225 nub_addr_t addr, nub_size_t size); 226 227 // Helper functions for watchpoint manipulations. 228 static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, 229 nub_addr_t addr, nub_size_t size, bool read, 230 bool write); 231 static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index); 232 static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); 233 static void ClearWatchpointHits(DBG &debug_state); 234 static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); 235 static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); 236 237 bool StartTransForHWP() override; 238 bool RollbackTransForHWP() override; 239 bool FinishTransForHWP() override; 240 DBG GetDBGCheckpoint(); 241 242 MachThread *m_thread; 243 State m_state; 244 DBG m_2pc_dbg_checkpoint; 245 uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning 246 // (0), Done (1), or Rolled Back (2)? 247 typedef std::map<uint32_t, Context> SaveRegisterStates; 248 SaveRegisterStates m_saved_register_states; 249 }; 250 251 #endif // #if defined (__i386__) || defined (__x86_64__) 252 #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_X86_64_DNBARCHIMPLX86_64_H 253