1 //===-- RegisterContextWindows_x64.cpp --------------------------*- 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 #include "lldb/lldb-private-types.h" 11 #include "lldb/Core/Error.h" 12 #include "lldb/Core/RegisterValue.h" 13 #include "lldb/Host/windows/HostThreadWindows.h" 14 #include "lldb/Host/windows/windows.h" 15 16 #include "lldb-x86-register-enums.h" 17 #include "RegisterContext_x86.h" 18 #include "RegisterContextWindows_x64.h" 19 #include "TargetThreadWindows.h" 20 21 #include "llvm/ADT/STLExtras.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 26 #define DEFINE_GPR(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatHexUppercase 27 #define DEFINE_GPR_BIN(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatBinary 28 29 namespace 30 { 31 32 // This enum defines the layout of the global RegisterInfo array. This is necessary because 33 // lldb register sets are defined in terms of indices into the register array. As such, the 34 // order of RegisterInfos defined in global registers array must match the order defined here. 35 // When defining the register set layouts, these values can appear in an arbitrary order, and that 36 // determines the order that register values are displayed in a dump. 37 enum RegisterIndex 38 { 39 eRegisterIndexRax, 40 eRegisterIndexRbx, 41 eRegisterIndexRcx, 42 eRegisterIndexRdx, 43 eRegisterIndexRdi, 44 eRegisterIndexRsi, 45 eRegisterIndexR8, 46 eRegisterIndexR9, 47 eRegisterIndexR10, 48 eRegisterIndexR11, 49 eRegisterIndexR12, 50 eRegisterIndexR13, 51 eRegisterIndexR14, 52 eRegisterIndexR15, 53 eRegisterIndexRbp, 54 eRegisterIndexRsp, 55 eRegisterIndexRip, 56 eRegisterIndexRflags 57 }; 58 59 // Array of all register information supported by Windows x86 60 RegisterInfo g_register_infos[] = { 61 // Macro auto defines most stuff eh_frame DWARF GENERIC 62 // GDB LLDB VALUE REGS INVALIDATE REGS 63 // ================================ ========================= ====================== ========================= 64 // =================== ================= ========== =============== 65 {DEFINE_GPR(rax, nullptr), 66 {dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rax_x86_64}, 67 nullptr, 68 nullptr}, 69 {DEFINE_GPR(rbx, nullptr), 70 {dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rbx_x86_64}, 71 nullptr, 72 nullptr}, 73 {DEFINE_GPR(rcx, nullptr), 74 {dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rcx_x86_64}, 75 nullptr, 76 nullptr}, 77 {DEFINE_GPR(rdx, nullptr), 78 {dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rdx_x86_64}, 79 nullptr, 80 nullptr}, 81 {DEFINE_GPR(rdi, nullptr), 82 {dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rdi_x86_64}, 83 nullptr, 84 nullptr}, 85 {DEFINE_GPR(rsi, nullptr), 86 {dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_rsi_x86_64}, 87 nullptr, 88 nullptr}, 89 {DEFINE_GPR(r8, nullptr), 90 {dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r8_x86_64}, 91 nullptr, 92 nullptr}, 93 {DEFINE_GPR(r9, nullptr), 94 {dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r9_x86_64}, 95 nullptr, 96 nullptr}, 97 {DEFINE_GPR(r10, nullptr), 98 {dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r10_x86_64}, 99 nullptr, 100 nullptr}, 101 {DEFINE_GPR(r11, nullptr), 102 {dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r11_x86_64}, 103 nullptr, 104 nullptr}, 105 {DEFINE_GPR(r12, nullptr), 106 {dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r12_x86_64}, 107 nullptr, 108 nullptr}, 109 {DEFINE_GPR(r13, nullptr), 110 {dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r13_x86_64}, 111 nullptr, 112 nullptr}, 113 {DEFINE_GPR(r14, nullptr), 114 {dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r14_x86_64}, 115 nullptr, 116 nullptr}, 117 {DEFINE_GPR(r15, nullptr), 118 {dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_r15_x86_64}, 119 nullptr, 120 nullptr}, 121 {DEFINE_GPR(rbp, "fp"), 122 {dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, lldb_rbp_x86_64}, 123 nullptr, 124 nullptr}, 125 {DEFINE_GPR(rsp, "sp"), 126 {dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, lldb_rsp_x86_64}, 127 nullptr, 128 nullptr}, 129 {DEFINE_GPR(rip, "pc"), 130 {dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, lldb_rip_x86_64}, 131 nullptr, 132 nullptr}, 133 {DEFINE_GPR_BIN(eflags, "flags"), 134 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, lldb_rflags_x86_64}, 135 nullptr, 136 nullptr}, 137 }; 138 139 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); 140 141 // Array of lldb register numbers used to define the set of all General Purpose Registers 142 uint32_t g_gpr_reg_indices[] = {eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx, eRegisterIndexRdx, 143 eRegisterIndexRdi, eRegisterIndexRsi, eRegisterIndexR8, eRegisterIndexR9, 144 eRegisterIndexR10, eRegisterIndexR11, eRegisterIndexR12, eRegisterIndexR13, 145 eRegisterIndexR14, eRegisterIndexR15, eRegisterIndexRbp, eRegisterIndexRsp, 146 eRegisterIndexRip, eRegisterIndexRflags}; 147 148 RegisterSet g_register_sets[] = { 149 {"General Purpose Registers", "gpr", llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices}, 150 }; 151 } 152 153 //------------------------------------------------------------------ 154 // Constructors and Destructors 155 //------------------------------------------------------------------ 156 RegisterContextWindows_x64::RegisterContextWindows_x64(Thread &thread, uint32_t concrete_frame_idx) 157 : RegisterContextWindows(thread, concrete_frame_idx) 158 { 159 } 160 161 RegisterContextWindows_x64::~RegisterContextWindows_x64() 162 { 163 } 164 165 size_t 166 RegisterContextWindows_x64::GetRegisterCount() 167 { 168 return llvm::array_lengthof(g_register_infos); 169 } 170 171 const RegisterInfo * 172 RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg) 173 { 174 if (reg < k_num_register_infos) 175 return &g_register_infos[reg]; 176 return NULL; 177 } 178 179 size_t 180 RegisterContextWindows_x64::GetRegisterSetCount() 181 { 182 return llvm::array_lengthof(g_register_sets); 183 } 184 185 const RegisterSet * 186 RegisterContextWindows_x64::GetRegisterSet(size_t reg_set) 187 { 188 return &g_register_sets[reg_set]; 189 } 190 191 bool 192 RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) 193 { 194 if (!CacheAllRegisterValues()) 195 return false; 196 197 switch (reg_info->kinds[eRegisterKindLLDB]) 198 { 199 case lldb_rax_x86_64: 200 reg_value.SetUInt64(m_context.Rax); 201 break; 202 case lldb_rbx_x86_64: 203 reg_value.SetUInt64(m_context.Rbx); 204 break; 205 case lldb_rcx_x86_64: 206 reg_value.SetUInt64(m_context.Rcx); 207 break; 208 case lldb_rdx_x86_64: 209 reg_value.SetUInt64(m_context.Rdx); 210 break; 211 case lldb_rdi_x86_64: 212 reg_value.SetUInt64(m_context.Rdi); 213 break; 214 case lldb_rsi_x86_64: 215 reg_value.SetUInt64(m_context.Rsi); 216 break; 217 case lldb_r8_x86_64: 218 reg_value.SetUInt64(m_context.R8); 219 break; 220 case lldb_r9_x86_64: 221 reg_value.SetUInt64(m_context.R9); 222 break; 223 case lldb_r10_x86_64: 224 reg_value.SetUInt64(m_context.R10); 225 break; 226 case lldb_r11_x86_64: 227 reg_value.SetUInt64(m_context.R11); 228 break; 229 case lldb_r12_x86_64: 230 reg_value.SetUInt64(m_context.R12); 231 break; 232 case lldb_r13_x86_64: 233 reg_value.SetUInt64(m_context.R13); 234 break; 235 case lldb_r14_x86_64: 236 reg_value.SetUInt64(m_context.R14); 237 break; 238 case lldb_r15_x86_64: 239 reg_value.SetUInt64(m_context.R15); 240 break; 241 case lldb_rbp_x86_64: 242 reg_value.SetUInt64(m_context.Rbp); 243 break; 244 case lldb_rsp_x86_64: 245 reg_value.SetUInt64(m_context.Rsp); 246 break; 247 case lldb_rip_x86_64: 248 reg_value.SetUInt64(m_context.Rip); 249 break; 250 case lldb_rflags_x86_64: 251 reg_value.SetUInt64(m_context.EFlags); 252 break; 253 } 254 return true; 255 } 256 257 bool 258 RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) 259 { 260 // Since we cannot only write a single register value to the inferior, we need to make sure 261 // our cached copy of the register values are fresh. Otherwise when writing EAX, for example, 262 // we may also overwrite some other register with a stale value. 263 if (!CacheAllRegisterValues()) 264 return false; 265 266 switch (reg_info->kinds[eRegisterKindLLDB]) 267 { 268 case lldb_rax_x86_64: 269 m_context.Rax = reg_value.GetAsUInt64(); 270 break; 271 case lldb_rbx_x86_64: 272 m_context.Rbx = reg_value.GetAsUInt64(); 273 break; 274 case lldb_rcx_x86_64: 275 m_context.Rcx = reg_value.GetAsUInt64(); 276 break; 277 case lldb_rdx_x86_64: 278 m_context.Rdx = reg_value.GetAsUInt64(); 279 break; 280 case lldb_rdi_x86_64: 281 m_context.Rdi = reg_value.GetAsUInt64(); 282 break; 283 case lldb_rsi_x86_64: 284 m_context.Rsi = reg_value.GetAsUInt64(); 285 break; 286 case lldb_r8_x86_64: 287 m_context.R8 = reg_value.GetAsUInt64(); 288 break; 289 case lldb_r9_x86_64: 290 m_context.R9 = reg_value.GetAsUInt64(); 291 break; 292 case lldb_r10_x86_64: 293 m_context.R10 = reg_value.GetAsUInt64(); 294 break; 295 case lldb_r11_x86_64: 296 m_context.R11 = reg_value.GetAsUInt64(); 297 break; 298 case lldb_r12_x86_64: 299 m_context.R12 = reg_value.GetAsUInt64(); 300 break; 301 case lldb_r13_x86_64: 302 m_context.R13 = reg_value.GetAsUInt64(); 303 break; 304 case lldb_r14_x86_64: 305 m_context.R14 = reg_value.GetAsUInt64(); 306 break; 307 case lldb_r15_x86_64: 308 m_context.R15 = reg_value.GetAsUInt64(); 309 break; 310 case lldb_rbp_x86_64: 311 m_context.Rbp = reg_value.GetAsUInt64(); 312 break; 313 case lldb_rsp_x86_64: 314 m_context.Rsp = reg_value.GetAsUInt64(); 315 break; 316 case lldb_rip_x86_64: 317 m_context.Rip = reg_value.GetAsUInt64(); 318 break; 319 case lldb_rflags_x86_64: 320 m_context.EFlags = reg_value.GetAsUInt64(); 321 break; 322 } 323 324 // Physically update the registers in the target process. 325 TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); 326 return ::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); 327 } 328