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: DNBArchImplX86_64(MachThread * thread)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() {} ~DNBArchImplX86_64()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) / sizeof(int), 107 e_regSetWordSizeFPU = sizeof(FPU) / sizeof(int), 108 e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int), 109 e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int), 110 e_regSetWordSizeAVX512f = sizeof(AVX512F) / sizeof(int), 111 e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int) 112 }; 113 114 enum { Read = 0, Write = 1, kNumErrors = 2 }; 115 116 struct Context { 117 GPR gpr; 118 union { 119 FPU no_avx; 120 AVX avx; 121 AVX512F avx512f; 122 } fpu; 123 EXC exc; 124 DBG dbg; 125 }; 126 127 struct State { 128 Context context; 129 kern_return_t gpr_errs[2]; // Read/Write errors 130 kern_return_t fpu_errs[2]; // Read/Write errors 131 kern_return_t exc_errs[2]; // Read/Write errors 132 kern_return_t dbg_errs[2]; // Read/Write errors 133 StateState134 State() { 135 uint32_t i; 136 for (i = 0; i < kNumErrors; i++) { 137 gpr_errs[i] = -1; 138 fpu_errs[i] = -1; 139 exc_errs[i] = -1; 140 dbg_errs[i] = -1; 141 } 142 } 143 InvalidateAllRegisterStatesState144 void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); } 145 GetErrorState146 kern_return_t GetError(int flavor, uint32_t err_idx) const { 147 if (err_idx < kNumErrors) { 148 switch (flavor) { 149 // When getting all errors, just OR all values together to see if 150 // we got any kind of error. 151 case e_regSetALL: 152 return gpr_errs[err_idx] | fpu_errs[err_idx] | exc_errs[err_idx]; 153 case e_regSetGPR: 154 return gpr_errs[err_idx]; 155 case e_regSetFPU: 156 return fpu_errs[err_idx]; 157 case e_regSetEXC: 158 return exc_errs[err_idx]; 159 case e_regSetDBG: 160 return dbg_errs[err_idx]; 161 default: 162 break; 163 } 164 } 165 return -1; 166 } 167 SetErrorState168 bool SetError(int flavor, uint32_t err_idx, kern_return_t err) { 169 if (err_idx < kNumErrors) { 170 switch (flavor) { 171 case e_regSetALL: 172 gpr_errs[err_idx] = fpu_errs[err_idx] = exc_errs[err_idx] = 173 dbg_errs[err_idx] = err; 174 return true; 175 176 case e_regSetGPR: 177 gpr_errs[err_idx] = err; 178 return true; 179 180 case e_regSetFPU: 181 fpu_errs[err_idx] = err; 182 return true; 183 184 case e_regSetEXC: 185 exc_errs[err_idx] = err; 186 return true; 187 188 case e_regSetDBG: 189 dbg_errs[err_idx] = err; 190 return true; 191 192 default: 193 break; 194 } 195 } 196 return false; 197 } 198 RegsAreValidState199 bool RegsAreValid(int flavor) const { 200 return GetError(flavor, Read) == KERN_SUCCESS; 201 } 202 }; 203 204 kern_return_t GetGPRState(bool force); 205 kern_return_t GetFPUState(bool force); 206 kern_return_t GetEXCState(bool force); 207 kern_return_t GetDBGState(bool force); 208 209 kern_return_t SetGPRState(); 210 kern_return_t SetFPUState(); 211 kern_return_t SetEXCState(); 212 kern_return_t SetDBGState(bool also_set_on_task); 213 214 static DNBArchProtocol *Create(MachThread *thread); 215 216 static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); 217 218 static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); 219 220 static uint32_t GetRegisterContextSize(); 221 222 static void SetHardwareBreakpoint(DBG &debug_state, uint32_t hw_index, 223 nub_addr_t addr, nub_size_t size); 224 225 // Helper functions for watchpoint manipulations. 226 static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, 227 nub_addr_t addr, nub_size_t size, bool read, 228 bool write); 229 static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index); 230 static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); 231 static void ClearWatchpointHits(DBG &debug_state); 232 static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); 233 static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); 234 235 bool StartTransForHWP() override; 236 bool RollbackTransForHWP() override; 237 bool FinishTransForHWP() override; 238 DBG GetDBGCheckpoint(); 239 240 MachThread *m_thread; 241 State m_state; 242 DBG m_2pc_dbg_checkpoint; 243 uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning 244 // (0), Done (1), or Rolled Back (2)? 245 typedef std::map<uint32_t, Context> SaveRegisterStates; 246 SaveRegisterStates m_saved_register_states; 247 }; 248 249 #endif // #if defined (__i386__) || defined (__x86_64__) 250 #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_X86_64_DNBARCHIMPLX86_64_H 251