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 // Array of lldb register numbers used to define the set of all General Purpose Registers 140 uint32_t g_gpr_reg_indices[] = {eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx, eRegisterIndexRdx, 141 eRegisterIndexRdi, eRegisterIndexRsi, eRegisterIndexR8, eRegisterIndexR9, 142 eRegisterIndexR10, eRegisterIndexR11, eRegisterIndexR12, eRegisterIndexR13, 143 eRegisterIndexR14, eRegisterIndexR15, eRegisterIndexRbp, eRegisterIndexRsp, 144 eRegisterIndexRip, eRegisterIndexRflags}; 145 146 RegisterSet g_register_sets[] = { 147 {"General Purpose Registers", "gpr", llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices}, 148 }; 149 } 150 151 //------------------------------------------------------------------ 152 // Constructors and Destructors 153 //------------------------------------------------------------------ 154 RegisterContextWindows_x64::RegisterContextWindows_x64(Thread &thread, uint32_t concrete_frame_idx) 155 : RegisterContextWindows(thread, concrete_frame_idx) 156 { 157 } 158 159 RegisterContextWindows_x64::~RegisterContextWindows_x64() 160 { 161 } 162 163 size_t 164 RegisterContextWindows_x64::GetRegisterCount() 165 { 166 return llvm::array_lengthof(g_register_infos); 167 } 168 169 const RegisterInfo * 170 RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg) 171 { 172 return &g_register_infos[reg]; 173 } 174 175 size_t 176 RegisterContextWindows_x64::GetRegisterSetCount() 177 { 178 return llvm::array_lengthof(g_register_sets); 179 } 180 181 const RegisterSet * 182 RegisterContextWindows_x64::GetRegisterSet(size_t reg_set) 183 { 184 return &g_register_sets[reg_set]; 185 } 186 187 bool 188 RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) 189 { 190 if (!CacheAllRegisterValues()) 191 return false; 192 193 switch (reg_info->kinds[eRegisterKindLLDB]) 194 { 195 case lldb_rax_x86_64: 196 reg_value.SetUInt64(m_context.Rax); 197 break; 198 case lldb_rbx_x86_64: 199 reg_value.SetUInt64(m_context.Rbx); 200 break; 201 case lldb_rcx_x86_64: 202 reg_value.SetUInt64(m_context.Rcx); 203 break; 204 case lldb_rdx_x86_64: 205 reg_value.SetUInt64(m_context.Rdx); 206 break; 207 case lldb_rdi_x86_64: 208 reg_value.SetUInt64(m_context.Rdi); 209 break; 210 case lldb_rsi_x86_64: 211 reg_value.SetUInt64(m_context.Rsi); 212 break; 213 case lldb_r8_x86_64: 214 reg_value.SetUInt64(m_context.R8); 215 break; 216 case lldb_r9_x86_64: 217 reg_value.SetUInt64(m_context.R9); 218 break; 219 case lldb_r10_x86_64: 220 reg_value.SetUInt64(m_context.R10); 221 break; 222 case lldb_r11_x86_64: 223 reg_value.SetUInt64(m_context.R11); 224 break; 225 case lldb_r12_x86_64: 226 reg_value.SetUInt64(m_context.R12); 227 break; 228 case lldb_r13_x86_64: 229 reg_value.SetUInt64(m_context.R13); 230 break; 231 case lldb_r14_x86_64: 232 reg_value.SetUInt64(m_context.R14); 233 break; 234 case lldb_r15_x86_64: 235 reg_value.SetUInt64(m_context.R15); 236 break; 237 case lldb_rbp_x86_64: 238 reg_value.SetUInt64(m_context.Rbp); 239 break; 240 case lldb_rsp_x86_64: 241 reg_value.SetUInt64(m_context.Rsp); 242 break; 243 case lldb_rip_x86_64: 244 reg_value.SetUInt64(m_context.Rip); 245 break; 246 case lldb_rflags_x86_64: 247 reg_value.SetUInt64(m_context.EFlags); 248 break; 249 } 250 return true; 251 } 252 253 bool 254 RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) 255 { 256 // Since we cannot only write a single register value to the inferior, we need to make sure 257 // our cached copy of the register values are fresh. Otherwise when writing EAX, for example, 258 // we may also overwrite some other register with a stale value. 259 if (!CacheAllRegisterValues()) 260 return false; 261 262 switch (reg_info->kinds[eRegisterKindLLDB]) 263 { 264 case lldb_rax_x86_64: 265 m_context.Rax = reg_value.GetAsUInt64(); 266 break; 267 case lldb_rbx_x86_64: 268 m_context.Rbx = reg_value.GetAsUInt64(); 269 break; 270 case lldb_rcx_x86_64: 271 m_context.Rcx = reg_value.GetAsUInt64(); 272 break; 273 case lldb_rdx_x86_64: 274 m_context.Rdx = reg_value.GetAsUInt64(); 275 break; 276 case lldb_rdi_x86_64: 277 m_context.Rdi = reg_value.GetAsUInt64(); 278 break; 279 case lldb_rsi_x86_64: 280 m_context.Rsi = reg_value.GetAsUInt64(); 281 break; 282 case lldb_r8_x86_64: 283 m_context.R8 = reg_value.GetAsUInt64(); 284 break; 285 case lldb_r9_x86_64: 286 m_context.R9 = reg_value.GetAsUInt64(); 287 break; 288 case lldb_r10_x86_64: 289 m_context.R10 = reg_value.GetAsUInt64(); 290 break; 291 case lldb_r11_x86_64: 292 m_context.R11 = reg_value.GetAsUInt64(); 293 break; 294 case lldb_r12_x86_64: 295 m_context.R12 = reg_value.GetAsUInt64(); 296 break; 297 case lldb_r13_x86_64: 298 m_context.R13 = reg_value.GetAsUInt64(); 299 break; 300 case lldb_r14_x86_64: 301 m_context.R14 = reg_value.GetAsUInt64(); 302 break; 303 case lldb_r15_x86_64: 304 m_context.R15 = reg_value.GetAsUInt64(); 305 break; 306 case lldb_rbp_x86_64: 307 m_context.Rbp = reg_value.GetAsUInt64(); 308 break; 309 case lldb_rsp_x86_64: 310 m_context.Rsp = reg_value.GetAsUInt64(); 311 break; 312 case lldb_rip_x86_64: 313 m_context.Rip = reg_value.GetAsUInt64(); 314 break; 315 case lldb_rflags_x86_64: 316 m_context.EFlags = reg_value.GetAsUInt64(); 317 break; 318 } 319 320 // Physically update the registers in the target process. 321 TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); 322 return ::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); 323 } 324