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 #define DEFINE_FPU_XMM(reg) \ 28 #reg, NULL, 16, 0, eEncodingUint, eFormatVectorOfUInt64, \ 29 {dwarf_##reg##_x86_64, dwarf_##reg##_x86_64, LLDB_INVALID_REGNUM, \ 30 LLDB_INVALID_REGNUM, lldb_##reg##_x86_64}, \ 31 nullptr, nullptr, nullptr, 0 32 33 namespace { 34 35 // This enum defines the layout of the global RegisterInfo array. This is 36 // necessary because lldb register sets are defined in terms of indices into 37 // the register array. As such, the order of RegisterInfos defined in global 38 // registers array must match the order defined here. When defining the 39 // register set layouts, these values can appear in an arbitrary order, and 40 // that determines the order that register values are displayed in a dump. 41 enum RegisterIndex { 42 eRegisterIndexRax, 43 eRegisterIndexRbx, 44 eRegisterIndexRcx, 45 eRegisterIndexRdx, 46 eRegisterIndexRdi, 47 eRegisterIndexRsi, 48 eRegisterIndexRbp, 49 eRegisterIndexRsp, 50 eRegisterIndexR8, 51 eRegisterIndexR9, 52 eRegisterIndexR10, 53 eRegisterIndexR11, 54 eRegisterIndexR12, 55 eRegisterIndexR13, 56 eRegisterIndexR14, 57 eRegisterIndexR15, 58 eRegisterIndexRip, 59 eRegisterIndexRflags, 60 61 eRegisterIndexXmm0, 62 eRegisterIndexXmm1, 63 eRegisterIndexXmm2, 64 eRegisterIndexXmm3, 65 eRegisterIndexXmm4, 66 eRegisterIndexXmm5, 67 eRegisterIndexXmm6, 68 eRegisterIndexXmm7, 69 eRegisterIndexXmm8, 70 eRegisterIndexXmm9, 71 eRegisterIndexXmm10, 72 eRegisterIndexXmm11, 73 eRegisterIndexXmm12, 74 eRegisterIndexXmm13, 75 eRegisterIndexXmm14, 76 eRegisterIndexXmm15 77 }; 78 79 // Array of all register information supported by Windows x86 80 RegisterInfo g_register_infos[] = { 81 // Macro auto defines most stuff eh_frame DWARF 82 // GENERIC 83 // GDB LLDB VALUE REGS INVALIDATE REGS 84 // ================================ ========================= 85 // ====================== ========================= 86 // =================== ================= ========== =============== 87 {DEFINE_GPR(rax, nullptr), 88 {dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, 89 LLDB_INVALID_REGNUM, lldb_rax_x86_64}, 90 nullptr, 91 nullptr, 92 nullptr, 93 0}, 94 {DEFINE_GPR(rbx, nullptr), 95 {dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, 96 LLDB_INVALID_REGNUM, lldb_rbx_x86_64}, 97 nullptr, 98 nullptr, 99 nullptr, 100 0}, 101 {DEFINE_GPR(rcx, nullptr), 102 {dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG1, 103 LLDB_INVALID_REGNUM, lldb_rcx_x86_64}, 104 nullptr, 105 nullptr, 106 nullptr, 107 0}, 108 {DEFINE_GPR(rdx, nullptr), 109 {dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG2, 110 LLDB_INVALID_REGNUM, lldb_rdx_x86_64}, 111 nullptr, 112 nullptr, 113 nullptr, 114 0}, 115 {DEFINE_GPR(rdi, nullptr), 116 {dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_INVALID_REGNUM, 117 LLDB_INVALID_REGNUM, lldb_rdi_x86_64}, 118 nullptr, 119 nullptr, 120 nullptr, 121 0}, 122 {DEFINE_GPR(rsi, nullptr), 123 {dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_INVALID_REGNUM, 124 LLDB_INVALID_REGNUM, lldb_rsi_x86_64}, 125 nullptr, 126 nullptr, 127 nullptr, 128 0}, 129 {DEFINE_GPR(rbp, "fp"), 130 {dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, 131 LLDB_INVALID_REGNUM, lldb_rbp_x86_64}, 132 nullptr, 133 nullptr, 134 nullptr, 135 0}, 136 {DEFINE_GPR(rsp, "sp"), 137 {dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, 138 LLDB_INVALID_REGNUM, lldb_rsp_x86_64}, 139 nullptr, 140 nullptr, 141 nullptr, 142 0}, 143 {DEFINE_GPR(r8, nullptr), 144 {dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG3, 145 LLDB_INVALID_REGNUM, lldb_r8_x86_64}, 146 nullptr, 147 nullptr, 148 nullptr, 149 0}, 150 {DEFINE_GPR(r9, nullptr), 151 {dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG4, 152 LLDB_INVALID_REGNUM, lldb_r9_x86_64}, 153 nullptr, 154 nullptr, 155 nullptr, 156 0}, 157 {DEFINE_GPR(r10, nullptr), 158 {dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM, 159 LLDB_INVALID_REGNUM, lldb_r10_x86_64}, 160 nullptr, 161 nullptr, 162 nullptr, 163 0}, 164 {DEFINE_GPR(r11, nullptr), 165 {dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM, 166 LLDB_INVALID_REGNUM, lldb_r11_x86_64}, 167 nullptr, 168 nullptr, 169 nullptr, 170 0}, 171 {DEFINE_GPR(r12, nullptr), 172 {dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, 173 LLDB_INVALID_REGNUM, lldb_r12_x86_64}, 174 nullptr, 175 nullptr, 176 nullptr, 177 0}, 178 {DEFINE_GPR(r13, nullptr), 179 {dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, 180 LLDB_INVALID_REGNUM, lldb_r13_x86_64}, 181 nullptr, 182 nullptr, 183 nullptr, 184 0}, 185 {DEFINE_GPR(r14, nullptr), 186 {dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, 187 LLDB_INVALID_REGNUM, lldb_r14_x86_64}, 188 nullptr, 189 nullptr, 190 nullptr, 191 0}, 192 {DEFINE_GPR(r15, nullptr), 193 {dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, 194 LLDB_INVALID_REGNUM, lldb_r15_x86_64}, 195 nullptr, 196 nullptr, 197 nullptr, 198 0}, 199 {DEFINE_GPR(rip, "pc"), 200 {dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, 201 LLDB_INVALID_REGNUM, lldb_rip_x86_64}, 202 nullptr, 203 nullptr, 204 nullptr, 205 0}, 206 {DEFINE_GPR_BIN(eflags, "flags"), 207 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, 208 LLDB_INVALID_REGNUM, lldb_rflags_x86_64}, 209 nullptr, 210 nullptr, 211 nullptr, 212 0}, 213 {DEFINE_FPU_XMM(xmm0)}, 214 {DEFINE_FPU_XMM(xmm1)}, 215 {DEFINE_FPU_XMM(xmm2)}, 216 {DEFINE_FPU_XMM(xmm3)}, 217 {DEFINE_FPU_XMM(xmm4)}, 218 {DEFINE_FPU_XMM(xmm5)}, 219 {DEFINE_FPU_XMM(xmm6)}, 220 {DEFINE_FPU_XMM(xmm7)}, 221 {DEFINE_FPU_XMM(xmm8)}, 222 {DEFINE_FPU_XMM(xmm9)}, 223 {DEFINE_FPU_XMM(xmm10)}, 224 {DEFINE_FPU_XMM(xmm11)}, 225 {DEFINE_FPU_XMM(xmm12)}, 226 {DEFINE_FPU_XMM(xmm13)}, 227 {DEFINE_FPU_XMM(xmm14)}, 228 {DEFINE_FPU_XMM(xmm15)} 229 }; 230 231 static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); 232 233 // Array of lldb register numbers used to define the set of all General Purpose 234 // Registers 235 uint32_t g_gpr_reg_indices[] = { 236 eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx, 237 eRegisterIndexRdx, eRegisterIndexRdi, eRegisterIndexRsi, 238 eRegisterIndexRbp, eRegisterIndexRsp, eRegisterIndexR8, 239 eRegisterIndexR9, eRegisterIndexR10, eRegisterIndexR11, 240 eRegisterIndexR12, eRegisterIndexR13, eRegisterIndexR14, 241 eRegisterIndexR15, eRegisterIndexRip, eRegisterIndexRflags}; 242 243 uint32_t g_fpu_reg_indices[] = { 244 eRegisterIndexXmm0, eRegisterIndexXmm1, eRegisterIndexXmm2, 245 eRegisterIndexXmm3, eRegisterIndexXmm4, eRegisterIndexXmm5, 246 eRegisterIndexXmm6, eRegisterIndexXmm7, eRegisterIndexXmm8, 247 eRegisterIndexXmm9, eRegisterIndexXmm10, eRegisterIndexXmm11, 248 eRegisterIndexXmm12, eRegisterIndexXmm13, eRegisterIndexXmm14, 249 eRegisterIndexXmm15 250 }; 251 252 RegisterSet g_register_sets[] = { 253 {"General Purpose Registers", "gpr", 254 llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices}, 255 {"Floating Point Registers", "fpu", 256 llvm::array_lengthof(g_fpu_reg_indices), g_fpu_reg_indices}}; 257 } 258 259 // Constructors and Destructors 260 RegisterContextWindows_x64::RegisterContextWindows_x64( 261 Thread &thread, uint32_t concrete_frame_idx) 262 : RegisterContextWindows(thread, concrete_frame_idx) {} 263 264 RegisterContextWindows_x64::~RegisterContextWindows_x64() {} 265 266 size_t RegisterContextWindows_x64::GetRegisterCount() { 267 return llvm::array_lengthof(g_register_infos); 268 } 269 270 const RegisterInfo * 271 RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg) { 272 if (reg < k_num_register_infos) 273 return &g_register_infos[reg]; 274 return NULL; 275 } 276 277 size_t RegisterContextWindows_x64::GetRegisterSetCount() { 278 return llvm::array_lengthof(g_register_sets); 279 } 280 281 const RegisterSet *RegisterContextWindows_x64::GetRegisterSet(size_t reg_set) { 282 return &g_register_sets[reg_set]; 283 } 284 285 bool RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info, 286 RegisterValue ®_value) { 287 if (!CacheAllRegisterValues()) 288 return false; 289 290 if (reg_info == nullptr) 291 return false; 292 293 const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; 294 295 switch (reg) { 296 case lldb_rax_x86_64: 297 reg_value.SetUInt64(m_context.Rax); 298 break; 299 case lldb_rbx_x86_64: 300 reg_value.SetUInt64(m_context.Rbx); 301 break; 302 case lldb_rcx_x86_64: 303 reg_value.SetUInt64(m_context.Rcx); 304 break; 305 case lldb_rdx_x86_64: 306 reg_value.SetUInt64(m_context.Rdx); 307 break; 308 case lldb_rdi_x86_64: 309 reg_value.SetUInt64(m_context.Rdi); 310 break; 311 case lldb_rsi_x86_64: 312 reg_value.SetUInt64(m_context.Rsi); 313 break; 314 case lldb_r8_x86_64: 315 reg_value.SetUInt64(m_context.R8); 316 break; 317 case lldb_r9_x86_64: 318 reg_value.SetUInt64(m_context.R9); 319 break; 320 case lldb_r10_x86_64: 321 reg_value.SetUInt64(m_context.R10); 322 break; 323 case lldb_r11_x86_64: 324 reg_value.SetUInt64(m_context.R11); 325 break; 326 case lldb_r12_x86_64: 327 reg_value.SetUInt64(m_context.R12); 328 break; 329 case lldb_r13_x86_64: 330 reg_value.SetUInt64(m_context.R13); 331 break; 332 case lldb_r14_x86_64: 333 reg_value.SetUInt64(m_context.R14); 334 break; 335 case lldb_r15_x86_64: 336 reg_value.SetUInt64(m_context.R15); 337 break; 338 case lldb_rbp_x86_64: 339 reg_value.SetUInt64(m_context.Rbp); 340 break; 341 case lldb_rsp_x86_64: 342 reg_value.SetUInt64(m_context.Rsp); 343 break; 344 case lldb_rip_x86_64: 345 reg_value.SetUInt64(m_context.Rip); 346 break; 347 case lldb_rflags_x86_64: 348 reg_value.SetUInt64(m_context.EFlags); 349 break; 350 case lldb_xmm0_x86_64: 351 reg_value.SetBytes(&m_context.Xmm0, 352 reg_info->byte_size, endian::InlHostByteOrder()); 353 break; 354 case lldb_xmm1_x86_64: 355 reg_value.SetBytes(&m_context.Xmm1, 356 reg_info->byte_size, endian::InlHostByteOrder()); 357 break; 358 case lldb_xmm2_x86_64: 359 reg_value.SetBytes(&m_context.Xmm2, 360 reg_info->byte_size, endian::InlHostByteOrder()); 361 break; 362 case lldb_xmm3_x86_64: 363 reg_value.SetBytes(&m_context.Xmm3, 364 reg_info->byte_size, endian::InlHostByteOrder()); 365 break; 366 case lldb_xmm4_x86_64: 367 reg_value.SetBytes(&m_context.Xmm4, 368 reg_info->byte_size, endian::InlHostByteOrder()); 369 break; 370 case lldb_xmm5_x86_64: 371 reg_value.SetBytes(&m_context.Xmm5, 372 reg_info->byte_size, endian::InlHostByteOrder()); 373 break; 374 case lldb_xmm6_x86_64: 375 reg_value.SetBytes(&m_context.Xmm6, 376 reg_info->byte_size, endian::InlHostByteOrder()); 377 break; 378 case lldb_xmm7_x86_64: 379 reg_value.SetBytes(&m_context.Xmm7, 380 reg_info->byte_size, endian::InlHostByteOrder()); 381 break; 382 case lldb_xmm8_x86_64: 383 reg_value.SetBytes(&m_context.Xmm8, 384 reg_info->byte_size, endian::InlHostByteOrder()); 385 break; 386 case lldb_xmm9_x86_64: 387 reg_value.SetBytes(&m_context.Xmm9, 388 reg_info->byte_size, endian::InlHostByteOrder()); 389 break; 390 case lldb_xmm10_x86_64: 391 reg_value.SetBytes(&m_context.Xmm10, 392 reg_info->byte_size, endian::InlHostByteOrder()); 393 break; 394 case lldb_xmm11_x86_64: 395 reg_value.SetBytes(&m_context.Xmm11, 396 reg_info->byte_size, endian::InlHostByteOrder()); 397 break; 398 case lldb_xmm12_x86_64: 399 reg_value.SetBytes(&m_context.Xmm12, 400 reg_info->byte_size, endian::InlHostByteOrder()); 401 break; 402 case lldb_xmm13_x86_64: 403 reg_value.SetBytes(&m_context.Xmm13, 404 reg_info->byte_size, endian::InlHostByteOrder()); 405 break; 406 case lldb_xmm14_x86_64: 407 reg_value.SetBytes(&m_context.Xmm14, 408 reg_info->byte_size, endian::InlHostByteOrder()); 409 break; 410 case lldb_xmm15_x86_64: 411 reg_value.SetBytes(&m_context.Xmm15, 412 reg_info->byte_size, endian::InlHostByteOrder()); 413 break; 414 } 415 return true; 416 } 417 418 bool RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info, 419 const RegisterValue ®_value) { 420 // Since we cannot only write a single register value to the inferior, we 421 // need to make sure our cached copy of the register values are fresh. 422 // Otherwise when writing EAX, for example, we may also overwrite some other 423 // register with a stale value. 424 if (!CacheAllRegisterValues()) 425 return false; 426 427 switch (reg_info->kinds[eRegisterKindLLDB]) { 428 case lldb_rax_x86_64: 429 m_context.Rax = reg_value.GetAsUInt64(); 430 break; 431 case lldb_rbx_x86_64: 432 m_context.Rbx = reg_value.GetAsUInt64(); 433 break; 434 case lldb_rcx_x86_64: 435 m_context.Rcx = reg_value.GetAsUInt64(); 436 break; 437 case lldb_rdx_x86_64: 438 m_context.Rdx = reg_value.GetAsUInt64(); 439 break; 440 case lldb_rdi_x86_64: 441 m_context.Rdi = reg_value.GetAsUInt64(); 442 break; 443 case lldb_rsi_x86_64: 444 m_context.Rsi = reg_value.GetAsUInt64(); 445 break; 446 case lldb_r8_x86_64: 447 m_context.R8 = reg_value.GetAsUInt64(); 448 break; 449 case lldb_r9_x86_64: 450 m_context.R9 = reg_value.GetAsUInt64(); 451 break; 452 case lldb_r10_x86_64: 453 m_context.R10 = reg_value.GetAsUInt64(); 454 break; 455 case lldb_r11_x86_64: 456 m_context.R11 = reg_value.GetAsUInt64(); 457 break; 458 case lldb_r12_x86_64: 459 m_context.R12 = reg_value.GetAsUInt64(); 460 break; 461 case lldb_r13_x86_64: 462 m_context.R13 = reg_value.GetAsUInt64(); 463 break; 464 case lldb_r14_x86_64: 465 m_context.R14 = reg_value.GetAsUInt64(); 466 break; 467 case lldb_r15_x86_64: 468 m_context.R15 = reg_value.GetAsUInt64(); 469 break; 470 case lldb_rbp_x86_64: 471 m_context.Rbp = reg_value.GetAsUInt64(); 472 break; 473 case lldb_rsp_x86_64: 474 m_context.Rsp = reg_value.GetAsUInt64(); 475 break; 476 case lldb_rip_x86_64: 477 m_context.Rip = reg_value.GetAsUInt64(); 478 break; 479 case lldb_rflags_x86_64: 480 m_context.EFlags = reg_value.GetAsUInt64(); 481 break; 482 case lldb_xmm0_x86_64: 483 memcpy(&m_context.Xmm0, reg_value.GetBytes(), 16); 484 break; 485 case lldb_xmm1_x86_64: 486 memcpy(&m_context.Xmm1, reg_value.GetBytes(), 16); 487 break; 488 case lldb_xmm2_x86_64: 489 memcpy(&m_context.Xmm2, reg_value.GetBytes(), 16); 490 break; 491 case lldb_xmm3_x86_64: 492 memcpy(&m_context.Xmm3, reg_value.GetBytes(), 16); 493 break; 494 case lldb_xmm4_x86_64: 495 memcpy(&m_context.Xmm4, reg_value.GetBytes(), 16); 496 break; 497 case lldb_xmm5_x86_64: 498 memcpy(&m_context.Xmm5, reg_value.GetBytes(), 16); 499 break; 500 case lldb_xmm6_x86_64: 501 memcpy(&m_context.Xmm6, reg_value.GetBytes(), 16); 502 break; 503 case lldb_xmm7_x86_64: 504 memcpy(&m_context.Xmm7, reg_value.GetBytes(), 16); 505 break; 506 case lldb_xmm8_x86_64: 507 memcpy(&m_context.Xmm8, reg_value.GetBytes(), 16); 508 break; 509 case lldb_xmm9_x86_64: 510 memcpy(&m_context.Xmm9, reg_value.GetBytes(), 16); 511 break; 512 case lldb_xmm10_x86_64: 513 memcpy(&m_context.Xmm10, reg_value.GetBytes(), 16); 514 break; 515 case lldb_xmm11_x86_64: 516 memcpy(&m_context.Xmm11, reg_value.GetBytes(), 16); 517 break; 518 case lldb_xmm12_x86_64: 519 memcpy(&m_context.Xmm12, reg_value.GetBytes(), 16); 520 break; 521 case lldb_xmm13_x86_64: 522 memcpy(&m_context.Xmm13, reg_value.GetBytes(), 16); 523 break; 524 case lldb_xmm14_x86_64: 525 memcpy(&m_context.Xmm14, reg_value.GetBytes(), 16); 526 break; 527 case lldb_xmm15_x86_64: 528 memcpy(&m_context.Xmm15, reg_value.GetBytes(), 16); 529 break; 530 } 531 532 // Physically update the registers in the target process. 533 TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); 534 return ::SetThreadContext( 535 wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); 536 } 537