1 //===-- DNBArchImplI386.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_I386_DNBARCHIMPLI386_H 14 #define LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_I386_DNBARCHIMPLI386_H 15 16 #if defined(__i386__) || defined(__x86_64__) 17 18 #include "DNBArch.h" 19 #include "MachRegisterStatesI386.h" 20 21 #include <map> 22 23 class MachThread; 24 25 class DNBArchImplI386 : public DNBArchProtocol { 26 public: DNBArchImplI386(MachThread * thread)27 DNBArchImplI386(MachThread *thread) 28 : DNBArchProtocol(), m_thread(thread), m_state(), m_2pc_dbg_checkpoint(), 29 m_2pc_trans_state(Trans_Done), m_saved_register_states() {} ~DNBArchImplI386()30 virtual ~DNBArchImplI386() {} 31 32 static void Initialize(); 33 34 bool GetRegisterValue(uint32_t set, uint32_t reg, 35 DNBRegisterValue *value) override; 36 bool SetRegisterValue(uint32_t set, uint32_t reg, 37 const DNBRegisterValue *value) override; 38 nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len) override; 39 nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len) override; 40 uint32_t SaveRegisterState() override; 41 bool RestoreRegisterState(uint32_t save_id) override; 42 43 kern_return_t GetRegisterState(int set, bool force) override; 44 kern_return_t SetRegisterState(int set) override; 45 bool RegisterSetStateIsValid(int set) const override; 46 47 uint64_t GetPC(uint64_t failValue) override; // Get program counter 48 kern_return_t SetPC(uint64_t value) override; 49 uint64_t GetSP(uint64_t failValue) override; // Get stack pointer 50 void ThreadWillResume() override; 51 bool ThreadDidStop() override; 52 bool NotifyException(MachException::Data &exc) override; 53 54 uint32_t NumSupportedHardwareBreakpoints() override; 55 uint32_t NumSupportedHardwareWatchpoints() override; 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_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 __i386_thread_state_t GPR; 71 typedef __i386_float_state_t FPU; 72 typedef __i386_exception_state_t EXC; 73 typedef __i386_avx_state_t AVX; 74 typedef __i386_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 __i386_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 } InvalidateAllRegisterStatesState143 void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); } GetErrorState144 kern_return_t GetError(int flavor, uint32_t err_idx) const { 145 if (err_idx < kNumErrors) { 146 switch (flavor) { 147 // When getting all errors, just OR all values together to see if 148 // we got any kind of error. 149 case e_regSetALL: 150 return gpr_errs[err_idx] | fpu_errs[err_idx] | exc_errs[err_idx]; 151 case e_regSetGPR: 152 return gpr_errs[err_idx]; 153 case e_regSetFPU: 154 return fpu_errs[err_idx]; 155 case e_regSetEXC: 156 return exc_errs[err_idx]; 157 case e_regSetDBG: 158 return dbg_errs[err_idx]; 159 default: 160 break; 161 } 162 } 163 return -1; 164 } SetErrorState165 bool SetError(int flavor, uint32_t err_idx, kern_return_t err) { 166 if (err_idx < kNumErrors) { 167 switch (flavor) { 168 case e_regSetALL: 169 gpr_errs[err_idx] = fpu_errs[err_idx] = exc_errs[err_idx] = 170 dbg_errs[err_idx] = err; 171 return true; 172 173 case e_regSetGPR: 174 gpr_errs[err_idx] = err; 175 return true; 176 177 case e_regSetFPU: 178 fpu_errs[err_idx] = err; 179 return true; 180 181 case e_regSetEXC: 182 exc_errs[err_idx] = err; 183 return true; 184 185 case e_regSetDBG: 186 dbg_errs[err_idx] = err; 187 return true; 188 189 default: 190 break; 191 } 192 } 193 return false; 194 } RegsAreValidState195 bool RegsAreValid(int flavor) const { 196 return GetError(flavor, Read) == KERN_SUCCESS; 197 } 198 }; 199 200 kern_return_t GetGPRState(bool force); 201 kern_return_t GetFPUState(bool force); 202 kern_return_t GetEXCState(bool force); 203 kern_return_t GetDBGState(bool force); 204 205 kern_return_t SetGPRState(); 206 kern_return_t SetFPUState(); 207 kern_return_t SetEXCState(); 208 kern_return_t SetDBGState(bool also_set_on_task); 209 210 static DNBArchProtocol *Create(MachThread *thread); 211 212 static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); 213 214 static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); 215 216 static uint32_t GetRegisterContextSize(); 217 218 static void SetHardwareBreakpoint(DBG &debug_state, uint32_t hw_index, 219 nub_addr_t addr, nub_size_t size); 220 221 // Helper functions for watchpoint manipulations. 222 static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, 223 nub_addr_t addr, nub_size_t size, bool read, 224 bool write); 225 static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index); 226 static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); 227 static void ClearWatchpointHits(DBG &debug_state); 228 static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); 229 static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); 230 231 bool StartTransForHWP() override; 232 bool RollbackTransForHWP() override; 233 bool FinishTransForHWP() override; 234 DBG GetDBGCheckpoint(); 235 236 MachThread *m_thread; 237 State m_state; 238 DBG m_2pc_dbg_checkpoint; 239 uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning 240 // (0), Done (1), or Rolled Back (2)? 241 typedef std::map<uint32_t, Context> SaveRegisterStates; 242 SaveRegisterStates m_saved_register_states; 243 }; 244 245 #endif // #if defined (__i386__) || defined (__x86_64__) 246 #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_I386_DNBARCHIMPLI386_H 247