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