1 //===-- NativeRegisterContextNetBSD_x86_64.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 #if defined(__x86_64__) 10 11 #include "NativeRegisterContextNetBSD_x86_64.h" 12 13 #include "lldb/Host/HostInfo.h" 14 #include "lldb/Utility/DataBufferHeap.h" 15 #include "lldb/Utility/Log.h" 16 #include "lldb/Utility/RegisterValue.h" 17 #include "lldb/Utility/Status.h" 18 19 #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h" 20 21 // clang-format off 22 #include <sys/types.h> 23 #include <sys/sysctl.h> 24 #include <x86/cpu.h> 25 #include <elf.h> 26 #include <err.h> 27 #include <stdint.h> 28 #include <stdlib.h> 29 // clang-format on 30 31 using namespace lldb_private; 32 using namespace lldb_private::process_netbsd; 33 34 // ---------------------------------------------------------------------------- 35 // Private namespace. 36 // ---------------------------------------------------------------------------- 37 38 namespace { 39 // x86 64-bit general purpose registers. 40 static const uint32_t g_gpr_regnums_x86_64[] = { 41 lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64, 42 lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rbp_x86_64, lldb_rsp_x86_64, 43 lldb_r8_x86_64, lldb_r9_x86_64, lldb_r10_x86_64, lldb_r11_x86_64, 44 lldb_r12_x86_64, lldb_r13_x86_64, lldb_r14_x86_64, lldb_r15_x86_64, 45 lldb_rip_x86_64, lldb_rflags_x86_64, lldb_cs_x86_64, lldb_fs_x86_64, 46 lldb_gs_x86_64, lldb_ss_x86_64, lldb_ds_x86_64, lldb_es_x86_64, 47 lldb_eax_x86_64, lldb_ebx_x86_64, lldb_ecx_x86_64, lldb_edx_x86_64, 48 lldb_edi_x86_64, lldb_esi_x86_64, lldb_ebp_x86_64, lldb_esp_x86_64, 49 lldb_r8d_x86_64, // Low 32 bits or r8 50 lldb_r9d_x86_64, // Low 32 bits or r9 51 lldb_r10d_x86_64, // Low 32 bits or r10 52 lldb_r11d_x86_64, // Low 32 bits or r11 53 lldb_r12d_x86_64, // Low 32 bits or r12 54 lldb_r13d_x86_64, // Low 32 bits or r13 55 lldb_r14d_x86_64, // Low 32 bits or r14 56 lldb_r15d_x86_64, // Low 32 bits or r15 57 lldb_ax_x86_64, lldb_bx_x86_64, lldb_cx_x86_64, lldb_dx_x86_64, 58 lldb_di_x86_64, lldb_si_x86_64, lldb_bp_x86_64, lldb_sp_x86_64, 59 lldb_r8w_x86_64, // Low 16 bits or r8 60 lldb_r9w_x86_64, // Low 16 bits or r9 61 lldb_r10w_x86_64, // Low 16 bits or r10 62 lldb_r11w_x86_64, // Low 16 bits or r11 63 lldb_r12w_x86_64, // Low 16 bits or r12 64 lldb_r13w_x86_64, // Low 16 bits or r13 65 lldb_r14w_x86_64, // Low 16 bits or r14 66 lldb_r15w_x86_64, // Low 16 bits or r15 67 lldb_ah_x86_64, lldb_bh_x86_64, lldb_ch_x86_64, lldb_dh_x86_64, 68 lldb_al_x86_64, lldb_bl_x86_64, lldb_cl_x86_64, lldb_dl_x86_64, 69 lldb_dil_x86_64, lldb_sil_x86_64, lldb_bpl_x86_64, lldb_spl_x86_64, 70 lldb_r8l_x86_64, // Low 8 bits or r8 71 lldb_r9l_x86_64, // Low 8 bits or r9 72 lldb_r10l_x86_64, // Low 8 bits or r10 73 lldb_r11l_x86_64, // Low 8 bits or r11 74 lldb_r12l_x86_64, // Low 8 bits or r12 75 lldb_r13l_x86_64, // Low 8 bits or r13 76 lldb_r14l_x86_64, // Low 8 bits or r14 77 lldb_r15l_x86_64, // Low 8 bits or r15 78 LLDB_INVALID_REGNUM // register sets need to end with this flag 79 }; 80 static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - 81 1 == 82 k_num_gpr_registers_x86_64, 83 "g_gpr_regnums_x86_64 has wrong number of register infos"); 84 85 // Number of register sets provided by this context. 86 enum { k_num_extended_register_sets = 2, k_num_register_sets = 4 }; 87 88 // Register sets for x86 64-bit. 89 static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = { 90 {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, 91 g_gpr_regnums_x86_64}, 92 }; 93 94 #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize()) 95 96 const int fpu_present = []() -> int { 97 int mib[2]; 98 int error; 99 size_t len; 100 int val; 101 102 len = sizeof(val); 103 mib[0] = CTL_MACHDEP; 104 mib[1] = CPU_FPU_PRESENT; 105 106 error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0); 107 if (error) 108 errx(EXIT_FAILURE, "sysctl"); 109 110 return val; 111 }(); 112 113 const int osfxsr = []() -> int { 114 int mib[2]; 115 int error; 116 size_t len; 117 int val; 118 119 len = sizeof(val); 120 mib[0] = CTL_MACHDEP; 121 mib[1] = CPU_OSFXSR; 122 123 error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0); 124 if (error) 125 errx(EXIT_FAILURE, "sysctl"); 126 127 return val; 128 }(); 129 130 const int fpu_save = []() -> int { 131 int mib[2]; 132 int error; 133 size_t len; 134 int val; 135 136 len = sizeof(val); 137 mib[0] = CTL_MACHDEP; 138 mib[1] = CPU_FPU_SAVE; 139 140 error = sysctl(mib, __arraycount(mib), &val, &len, NULL, 0); 141 if (error) 142 errx(EXIT_FAILURE, "sysctl"); 143 144 return val; 145 }(); 146 147 } // namespace 148 149 NativeRegisterContextNetBSD * 150 NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD( 151 const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { 152 return new NativeRegisterContextNetBSD_x86_64(target_arch, native_thread); 153 } 154 155 // ---------------------------------------------------------------------------- 156 // NativeRegisterContextNetBSD_x86_64 members. 157 // ---------------------------------------------------------------------------- 158 159 static RegisterInfoInterface * 160 CreateRegisterInfoInterface(const ArchSpec &target_arch) { 161 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && 162 "Register setting path assumes this is a 64-bit host"); 163 // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 164 // register context. 165 return new RegisterContextNetBSD_x86_64(target_arch); 166 } 167 168 NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64( 169 const ArchSpec &target_arch, NativeThreadProtocol &native_thread) 170 : NativeRegisterContextNetBSD(native_thread, 171 CreateRegisterInfoInterface(target_arch)), 172 m_gpr_x86_64(), m_fpr_x86_64(), m_dbr_x86_64() {} 173 174 // CONSIDER after local and llgs debugging are merged, register set support can 175 // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual. 176 uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetCount() const { 177 uint32_t sets = 0; 178 for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { 179 if (GetSetForNativeRegNum(set_index) != -1) 180 ++sets; 181 } 182 183 return sets; 184 } 185 186 const RegisterSet * 187 NativeRegisterContextNetBSD_x86_64::GetRegisterSet(uint32_t set_index) const { 188 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { 189 case llvm::Triple::x86_64: 190 return &g_reg_sets_x86_64[set_index]; 191 default: 192 assert(false && "Unhandled target architecture."); 193 return nullptr; 194 } 195 196 return nullptr; 197 } 198 199 int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( 200 int reg_num) const { 201 if (reg_num <= k_last_gpr_x86_64) 202 return GPRegSet; 203 else if (reg_num <= k_last_fpr_x86_64) 204 return (fpu_present == 1 && osfxsr == 1 && fpu_save >= 1) ? FPRegSet : -1; 205 else if (reg_num <= k_last_avx_x86_64) 206 return -1; // AVX 207 else if (reg_num <= k_last_mpxr_x86_64) 208 return -1; // MPXR 209 else if (reg_num <= k_last_mpxc_x86_64) 210 return -1; // MPXC 211 else if (reg_num <= lldb_dr7_x86_64) 212 return DBRegSet; // DBR 213 else 214 return -1; 215 } 216 217 int NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) { 218 switch (set) { 219 case GPRegSet: 220 ReadGPR(); 221 return 0; 222 case FPRegSet: 223 ReadFPR(); 224 return 0; 225 case DBRegSet: 226 ReadDBR(); 227 return 0; 228 default: 229 break; 230 } 231 return -1; 232 } 233 int NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(uint32_t set) { 234 switch (set) { 235 case GPRegSet: 236 WriteGPR(); 237 return 0; 238 case FPRegSet: 239 WriteFPR(); 240 return 0; 241 case DBRegSet: 242 WriteDBR(); 243 return 0; 244 default: 245 break; 246 } 247 return -1; 248 } 249 250 Status 251 NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, 252 RegisterValue ®_value) { 253 Status error; 254 255 if (!reg_info) { 256 error.SetErrorString("reg_info NULL"); 257 return error; 258 } 259 260 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 261 if (reg == LLDB_INVALID_REGNUM) { 262 // This is likely an internal register for lldb use only and should not be 263 // directly queried. 264 error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " 265 "register, cannot read directly", 266 reg_info->name); 267 return error; 268 } 269 270 int set = GetSetForNativeRegNum(reg); 271 if (set == -1) { 272 // This is likely an internal register for lldb use only and should not be 273 // directly queried. 274 error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", 275 reg_info->name); 276 return error; 277 } 278 279 if (ReadRegisterSet(set) != 0) { 280 // This is likely an internal register for lldb use only and should not be 281 // directly queried. 282 error.SetErrorStringWithFormat( 283 "reading register set for register \"%s\" failed", reg_info->name); 284 return error; 285 } 286 287 switch (reg) { 288 case lldb_rax_x86_64: 289 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RAX]; 290 break; 291 case lldb_rbx_x86_64: 292 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RBX]; 293 break; 294 case lldb_rcx_x86_64: 295 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RCX]; 296 break; 297 case lldb_rdx_x86_64: 298 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RDX]; 299 break; 300 case lldb_rdi_x86_64: 301 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RDI]; 302 break; 303 case lldb_rsi_x86_64: 304 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RSI]; 305 break; 306 case lldb_rbp_x86_64: 307 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RBP]; 308 break; 309 case lldb_rsp_x86_64: 310 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RSP]; 311 break; 312 case lldb_r8_x86_64: 313 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R8]; 314 break; 315 case lldb_r9_x86_64: 316 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R9]; 317 break; 318 case lldb_r10_x86_64: 319 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R10]; 320 break; 321 case lldb_r11_x86_64: 322 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R11]; 323 break; 324 case lldb_r12_x86_64: 325 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R12]; 326 break; 327 case lldb_r13_x86_64: 328 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R13]; 329 break; 330 case lldb_r14_x86_64: 331 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R14]; 332 break; 333 case lldb_r15_x86_64: 334 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R15]; 335 break; 336 case lldb_rip_x86_64: 337 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RIP]; 338 break; 339 case lldb_rflags_x86_64: 340 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RFLAGS]; 341 break; 342 case lldb_cs_x86_64: 343 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_CS]; 344 break; 345 case lldb_fs_x86_64: 346 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_FS]; 347 break; 348 case lldb_gs_x86_64: 349 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_GS]; 350 break; 351 case lldb_ss_x86_64: 352 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_SS]; 353 break; 354 case lldb_ds_x86_64: 355 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_DS]; 356 break; 357 case lldb_es_x86_64: 358 reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_ES]; 359 break; 360 case lldb_fctrl_x86_64: 361 reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_cw; 362 break; 363 case lldb_fstat_x86_64: 364 reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_sw; 365 break; 366 case lldb_ftag_x86_64: 367 reg_value = (uint8_t)m_fpr_x86_64.fxstate.fx_tw; 368 break; 369 case lldb_fop_x86_64: 370 reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_opcode; 371 break; 372 case lldb_fiseg_x86_64: 373 reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_ip.fa_64; 374 break; 375 case lldb_fioff_x86_64: 376 reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off; 377 break; 378 case lldb_foseg_x86_64: 379 reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_dp.fa_64; 380 break; 381 case lldb_fooff_x86_64: 382 reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off; 383 break; 384 case lldb_mxcsr_x86_64: 385 reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr; 386 break; 387 case lldb_mxcsrmask_x86_64: 388 reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr_mask; 389 break; 390 case lldb_st0_x86_64: 391 case lldb_st1_x86_64: 392 case lldb_st2_x86_64: 393 case lldb_st3_x86_64: 394 case lldb_st4_x86_64: 395 case lldb_st5_x86_64: 396 case lldb_st6_x86_64: 397 case lldb_st7_x86_64: 398 reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64], 399 reg_info->byte_size, endian::InlHostByteOrder()); 400 break; 401 case lldb_mm0_x86_64: 402 case lldb_mm1_x86_64: 403 case lldb_mm2_x86_64: 404 case lldb_mm3_x86_64: 405 case lldb_mm4_x86_64: 406 case lldb_mm5_x86_64: 407 case lldb_mm6_x86_64: 408 case lldb_mm7_x86_64: 409 reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_mm0_x86_64], 410 reg_info->byte_size, endian::InlHostByteOrder()); 411 break; 412 case lldb_xmm0_x86_64: 413 case lldb_xmm1_x86_64: 414 case lldb_xmm2_x86_64: 415 case lldb_xmm3_x86_64: 416 case lldb_xmm4_x86_64: 417 case lldb_xmm5_x86_64: 418 case lldb_xmm6_x86_64: 419 case lldb_xmm7_x86_64: 420 case lldb_xmm8_x86_64: 421 case lldb_xmm9_x86_64: 422 case lldb_xmm10_x86_64: 423 case lldb_xmm11_x86_64: 424 case lldb_xmm12_x86_64: 425 case lldb_xmm13_x86_64: 426 case lldb_xmm14_x86_64: 427 case lldb_xmm15_x86_64: 428 reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64], 429 reg_info->byte_size, endian::InlHostByteOrder()); 430 break; 431 case lldb_dr0_x86_64: 432 case lldb_dr1_x86_64: 433 case lldb_dr2_x86_64: 434 case lldb_dr3_x86_64: 435 case lldb_dr4_x86_64: 436 case lldb_dr5_x86_64: 437 case lldb_dr6_x86_64: 438 case lldb_dr7_x86_64: 439 reg_value = (uint64_t)m_dbr_x86_64.dr[reg - lldb_dr0_x86_64]; 440 break; 441 } 442 443 return error; 444 } 445 446 Status NativeRegisterContextNetBSD_x86_64::WriteRegister( 447 const RegisterInfo *reg_info, const RegisterValue ®_value) { 448 449 Status error; 450 451 if (!reg_info) { 452 error.SetErrorString("reg_info NULL"); 453 return error; 454 } 455 456 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 457 if (reg == LLDB_INVALID_REGNUM) { 458 // This is likely an internal register for lldb use only and should not be 459 // directly queried. 460 error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " 461 "register, cannot read directly", 462 reg_info->name); 463 return error; 464 } 465 466 int set = GetSetForNativeRegNum(reg); 467 if (set == -1) { 468 // This is likely an internal register for lldb use only and should not be 469 // directly queried. 470 error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", 471 reg_info->name); 472 return error; 473 } 474 475 if (ReadRegisterSet(set) != 0) { 476 // This is likely an internal register for lldb use only and should not be 477 // directly queried. 478 error.SetErrorStringWithFormat( 479 "reading register set for register \"%s\" failed", reg_info->name); 480 return error; 481 } 482 483 switch (reg) { 484 case lldb_rax_x86_64: 485 m_gpr_x86_64.regs[_REG_RAX] = reg_value.GetAsUInt64(); 486 break; 487 case lldb_rbx_x86_64: 488 m_gpr_x86_64.regs[_REG_RBX] = reg_value.GetAsUInt64(); 489 break; 490 case lldb_rcx_x86_64: 491 m_gpr_x86_64.regs[_REG_RCX] = reg_value.GetAsUInt64(); 492 break; 493 case lldb_rdx_x86_64: 494 m_gpr_x86_64.regs[_REG_RDX] = reg_value.GetAsUInt64(); 495 break; 496 case lldb_rdi_x86_64: 497 m_gpr_x86_64.regs[_REG_RDI] = reg_value.GetAsUInt64(); 498 break; 499 case lldb_rsi_x86_64: 500 m_gpr_x86_64.regs[_REG_RSI] = reg_value.GetAsUInt64(); 501 break; 502 case lldb_rbp_x86_64: 503 m_gpr_x86_64.regs[_REG_RBP] = reg_value.GetAsUInt64(); 504 break; 505 case lldb_rsp_x86_64: 506 m_gpr_x86_64.regs[_REG_RSP] = reg_value.GetAsUInt64(); 507 break; 508 case lldb_r8_x86_64: 509 m_gpr_x86_64.regs[_REG_R8] = reg_value.GetAsUInt64(); 510 break; 511 case lldb_r9_x86_64: 512 m_gpr_x86_64.regs[_REG_R9] = reg_value.GetAsUInt64(); 513 break; 514 case lldb_r10_x86_64: 515 m_gpr_x86_64.regs[_REG_R10] = reg_value.GetAsUInt64(); 516 break; 517 case lldb_r11_x86_64: 518 m_gpr_x86_64.regs[_REG_R11] = reg_value.GetAsUInt64(); 519 break; 520 case lldb_r12_x86_64: 521 m_gpr_x86_64.regs[_REG_R12] = reg_value.GetAsUInt64(); 522 break; 523 case lldb_r13_x86_64: 524 m_gpr_x86_64.regs[_REG_R13] = reg_value.GetAsUInt64(); 525 break; 526 case lldb_r14_x86_64: 527 m_gpr_x86_64.regs[_REG_R14] = reg_value.GetAsUInt64(); 528 break; 529 case lldb_r15_x86_64: 530 m_gpr_x86_64.regs[_REG_R15] = reg_value.GetAsUInt64(); 531 break; 532 case lldb_rip_x86_64: 533 m_gpr_x86_64.regs[_REG_RIP] = reg_value.GetAsUInt64(); 534 break; 535 case lldb_rflags_x86_64: 536 m_gpr_x86_64.regs[_REG_RFLAGS] = reg_value.GetAsUInt64(); 537 break; 538 case lldb_cs_x86_64: 539 m_gpr_x86_64.regs[_REG_CS] = reg_value.GetAsUInt64(); 540 break; 541 case lldb_fs_x86_64: 542 m_gpr_x86_64.regs[_REG_FS] = reg_value.GetAsUInt64(); 543 break; 544 case lldb_gs_x86_64: 545 m_gpr_x86_64.regs[_REG_GS] = reg_value.GetAsUInt64(); 546 break; 547 case lldb_ss_x86_64: 548 m_gpr_x86_64.regs[_REG_SS] = reg_value.GetAsUInt64(); 549 break; 550 case lldb_ds_x86_64: 551 m_gpr_x86_64.regs[_REG_DS] = reg_value.GetAsUInt64(); 552 break; 553 case lldb_es_x86_64: 554 m_gpr_x86_64.regs[_REG_ES] = reg_value.GetAsUInt64(); 555 break; 556 case lldb_fctrl_x86_64: 557 m_fpr_x86_64.fxstate.fx_cw = reg_value.GetAsUInt16(); 558 break; 559 case lldb_fstat_x86_64: 560 m_fpr_x86_64.fxstate.fx_sw = reg_value.GetAsUInt16(); 561 break; 562 case lldb_ftag_x86_64: 563 m_fpr_x86_64.fxstate.fx_tw = reg_value.GetAsUInt8(); 564 break; 565 case lldb_fop_x86_64: 566 m_fpr_x86_64.fxstate.fx_opcode = reg_value.GetAsUInt16(); 567 break; 568 case lldb_fiseg_x86_64: 569 m_fpr_x86_64.fxstate.fx_ip.fa_64 = reg_value.GetAsUInt64(); 570 break; 571 case lldb_fioff_x86_64: 572 m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off = reg_value.GetAsUInt32(); 573 break; 574 case lldb_foseg_x86_64: 575 m_fpr_x86_64.fxstate.fx_dp.fa_64 = reg_value.GetAsUInt64(); 576 break; 577 case lldb_fooff_x86_64: 578 m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off = reg_value.GetAsUInt32(); 579 break; 580 case lldb_mxcsr_x86_64: 581 m_fpr_x86_64.fxstate.fx_mxcsr = reg_value.GetAsUInt32(); 582 break; 583 case lldb_mxcsrmask_x86_64: 584 m_fpr_x86_64.fxstate.fx_mxcsr_mask = reg_value.GetAsUInt32(); 585 break; 586 case lldb_st0_x86_64: 587 case lldb_st1_x86_64: 588 case lldb_st2_x86_64: 589 case lldb_st3_x86_64: 590 case lldb_st4_x86_64: 591 case lldb_st5_x86_64: 592 case lldb_st6_x86_64: 593 case lldb_st7_x86_64: 594 ::memcpy(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64], 595 reg_value.GetBytes(), reg_value.GetByteSize()); 596 break; 597 case lldb_mm0_x86_64: 598 case lldb_mm1_x86_64: 599 case lldb_mm2_x86_64: 600 case lldb_mm3_x86_64: 601 case lldb_mm4_x86_64: 602 case lldb_mm5_x86_64: 603 case lldb_mm6_x86_64: 604 case lldb_mm7_x86_64: 605 ::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_mm0_x86_64], 606 reg_value.GetBytes(), reg_value.GetByteSize()); 607 break; 608 case lldb_xmm0_x86_64: 609 case lldb_xmm1_x86_64: 610 case lldb_xmm2_x86_64: 611 case lldb_xmm3_x86_64: 612 case lldb_xmm4_x86_64: 613 case lldb_xmm5_x86_64: 614 case lldb_xmm6_x86_64: 615 case lldb_xmm7_x86_64: 616 case lldb_xmm8_x86_64: 617 case lldb_xmm9_x86_64: 618 case lldb_xmm10_x86_64: 619 case lldb_xmm11_x86_64: 620 case lldb_xmm12_x86_64: 621 case lldb_xmm13_x86_64: 622 case lldb_xmm14_x86_64: 623 case lldb_xmm15_x86_64: 624 ::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64], 625 reg_value.GetBytes(), reg_value.GetByteSize()); 626 break; 627 case lldb_dr0_x86_64: 628 case lldb_dr1_x86_64: 629 case lldb_dr2_x86_64: 630 case lldb_dr3_x86_64: 631 case lldb_dr4_x86_64: 632 case lldb_dr5_x86_64: 633 case lldb_dr6_x86_64: 634 case lldb_dr7_x86_64: 635 m_dbr_x86_64.dr[reg - lldb_dr0_x86_64] = reg_value.GetAsUInt64(); 636 break; 637 } 638 639 if (WriteRegisterSet(set) != 0) 640 error.SetErrorStringWithFormat("failed to write register set"); 641 642 return error; 643 } 644 645 Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues( 646 lldb::DataBufferSP &data_sp) { 647 Status error; 648 649 data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); 650 if (!data_sp) { 651 error.SetErrorStringWithFormat( 652 "failed to allocate DataBufferHeap instance of size %" PRIu64, 653 REG_CONTEXT_SIZE); 654 return error; 655 } 656 657 error = ReadGPR(); 658 if (error.Fail()) 659 return error; 660 661 uint8_t *dst = data_sp->GetBytes(); 662 if (dst == nullptr) { 663 error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 664 " returned a null pointer", 665 REG_CONTEXT_SIZE); 666 return error; 667 } 668 669 ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); 670 dst += GetRegisterInfoInterface().GetGPRSize(); 671 672 RegisterValue value((uint64_t)-1); 673 const RegisterInfo *reg_info = 674 GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax"); 675 if (reg_info == nullptr) 676 reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax"); 677 return error; 678 } 679 680 Status NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues( 681 const lldb::DataBufferSP &data_sp) { 682 Status error; 683 684 if (!data_sp) { 685 error.SetErrorStringWithFormat( 686 "NativeRegisterContextNetBSD_x86_64::%s invalid data_sp provided", 687 __FUNCTION__); 688 return error; 689 } 690 691 if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { 692 error.SetErrorStringWithFormat( 693 "NativeRegisterContextNetBSD_x86_64::%s data_sp contained mismatched " 694 "data size, expected %" PRIu64 ", actual %" PRIu64, 695 __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); 696 return error; 697 } 698 699 uint8_t *src = data_sp->GetBytes(); 700 if (src == nullptr) { 701 error.SetErrorStringWithFormat("NativeRegisterContextNetBSD_x86_64::%s " 702 "DataBuffer::GetBytes() returned a null " 703 "pointer", 704 __FUNCTION__); 705 return error; 706 } 707 ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize()); 708 709 error = WriteGPR(); 710 if (error.Fail()) 711 return error; 712 src += GetRegisterInfoInterface().GetGPRSize(); 713 714 return error; 715 } 716 717 Status NativeRegisterContextNetBSD_x86_64::IsWatchpointHit(uint32_t wp_index, 718 bool &is_hit) { 719 if (wp_index >= NumSupportedHardwareWatchpoints()) 720 return Status("Watchpoint index out of range"); 721 722 RegisterValue reg_value; 723 const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr6_x86_64); 724 Status error = ReadRegister(reg_info, reg_value); 725 if (error.Fail()) { 726 is_hit = false; 727 return error; 728 } 729 730 uint64_t status_bits = reg_value.GetAsUInt64(); 731 732 is_hit = status_bits & (1 << wp_index); 733 734 return error; 735 } 736 737 Status NativeRegisterContextNetBSD_x86_64::GetWatchpointHitIndex( 738 uint32_t &wp_index, lldb::addr_t trap_addr) { 739 uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); 740 for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) { 741 bool is_hit; 742 Status error = IsWatchpointHit(wp_index, is_hit); 743 if (error.Fail()) { 744 wp_index = LLDB_INVALID_INDEX32; 745 return error; 746 } else if (is_hit) { 747 return error; 748 } 749 } 750 wp_index = LLDB_INVALID_INDEX32; 751 return Status(); 752 } 753 754 Status NativeRegisterContextNetBSD_x86_64::IsWatchpointVacant(uint32_t wp_index, 755 bool &is_vacant) { 756 if (wp_index >= NumSupportedHardwareWatchpoints()) 757 return Status("Watchpoint index out of range"); 758 759 RegisterValue reg_value; 760 const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr7_x86_64); 761 Status error = ReadRegister(reg_info, reg_value); 762 if (error.Fail()) { 763 is_vacant = false; 764 return error; 765 } 766 767 uint64_t control_bits = reg_value.GetAsUInt64(); 768 769 is_vacant = !(control_bits & (1 << (2 * wp_index))); 770 771 return error; 772 } 773 774 Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex( 775 lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) { 776 777 if (wp_index >= NumSupportedHardwareWatchpoints()) 778 return Status("Watchpoint index out of range"); 779 780 // Read only watchpoints aren't supported on x86_64. Fall back to read/write 781 // waitchpoints instead. 782 // TODO: Add logic to detect when a write happens and ignore that watchpoint 783 // hit. 784 if (watch_flags == 0x2) 785 watch_flags = 0x3; 786 787 if (watch_flags != 0x1 && watch_flags != 0x3) 788 return Status("Invalid read/write bits for watchpoint"); 789 790 if (size != 1 && size != 2 && size != 4 && size != 8) 791 return Status("Invalid size for watchpoint"); 792 793 bool is_vacant; 794 Status error = IsWatchpointVacant(wp_index, is_vacant); 795 if (error.Fail()) 796 return error; 797 if (!is_vacant) 798 return Status("Watchpoint index not vacant"); 799 800 RegisterValue reg_value; 801 const RegisterInfo *const reg_info_dr7 = 802 GetRegisterInfoAtIndex(lldb_dr7_x86_64); 803 error = ReadRegister(reg_info_dr7, reg_value); 804 if (error.Fail()) 805 return error; 806 807 // for watchpoints 0, 1, 2, or 3, respectively, set bits 1, 3, 5, or 7 808 uint64_t enable_bit = 1 << (2 * wp_index); 809 810 // set bits 16-17, 20-21, 24-25, or 28-29 811 // with 0b01 for write, and 0b11 for read/write 812 uint64_t rw_bits = watch_flags << (16 + 4 * wp_index); 813 814 // set bits 18-19, 22-23, 26-27, or 30-31 815 // with 0b00, 0b01, 0b10, or 0b11 816 // for 1, 2, 8 (if supported), or 4 bytes, respectively 817 uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index); 818 819 uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); 820 821 uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; 822 823 control_bits |= enable_bit | rw_bits | size_bits; 824 825 const RegisterInfo *const reg_info_drN = 826 GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index); 827 error = WriteRegister(reg_info_drN, RegisterValue(addr)); 828 if (error.Fail()) 829 return error; 830 831 error = WriteRegister(reg_info_dr7, RegisterValue(control_bits)); 832 if (error.Fail()) 833 return error; 834 835 error.Clear(); 836 return error; 837 } 838 839 bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint( 840 uint32_t wp_index) { 841 if (wp_index >= NumSupportedHardwareWatchpoints()) 842 return false; 843 844 RegisterValue reg_value; 845 846 // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0, 1, 2, or 3 of 847 // the debug status register (DR6) 848 const RegisterInfo *const reg_info_dr6 = 849 GetRegisterInfoAtIndex(lldb_dr6_x86_64); 850 Status error = ReadRegister(reg_info_dr6, reg_value); 851 if (error.Fail()) 852 return false; 853 uint64_t bit_mask = 1 << wp_index; 854 uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; 855 error = WriteRegister(reg_info_dr6, RegisterValue(status_bits)); 856 if (error.Fail()) 857 return false; 858 859 // for watchpoints 0, 1, 2, or 3, respectively, clear bits {0-1,16-19}, 860 // {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} of the debug control register 861 // (DR7) 862 const RegisterInfo *const reg_info_dr7 = 863 GetRegisterInfoAtIndex(lldb_dr7_x86_64); 864 error = ReadRegister(reg_info_dr7, reg_value); 865 if (error.Fail()) 866 return false; 867 bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); 868 uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; 869 return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success(); 870 } 871 872 Status NativeRegisterContextNetBSD_x86_64::ClearAllHardwareWatchpoints() { 873 RegisterValue reg_value; 874 875 // clear bits {0-4} of the debug status register (DR6) 876 const RegisterInfo *const reg_info_dr6 = 877 GetRegisterInfoAtIndex(lldb_dr6_x86_64); 878 Status error = ReadRegister(reg_info_dr6, reg_value); 879 if (error.Fail()) 880 return error; 881 uint64_t bit_mask = 0xF; 882 uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; 883 error = WriteRegister(reg_info_dr6, RegisterValue(status_bits)); 884 if (error.Fail()) 885 return error; 886 887 // clear bits {0-7,16-31} of the debug control register (DR7) 888 const RegisterInfo *const reg_info_dr7 = 889 GetRegisterInfoAtIndex(lldb_dr7_x86_64); 890 error = ReadRegister(reg_info_dr7, reg_value); 891 if (error.Fail()) 892 return error; 893 bit_mask = 0xFF | (0xFFFF << 16); 894 uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; 895 return WriteRegister(reg_info_dr7, RegisterValue(control_bits)); 896 } 897 898 uint32_t NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpoint( 899 lldb::addr_t addr, size_t size, uint32_t watch_flags) { 900 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); 901 const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); 902 for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) { 903 bool is_vacant; 904 Status error = IsWatchpointVacant(wp_index, is_vacant); 905 if (is_vacant) { 906 error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index); 907 if (error.Success()) 908 return wp_index; 909 } 910 if (error.Fail() && log) { 911 log->Printf("NativeRegisterContextNetBSD_x86_64::%s Error: %s", 912 __FUNCTION__, error.AsCString()); 913 } 914 } 915 return LLDB_INVALID_INDEX32; 916 } 917 918 lldb::addr_t 919 NativeRegisterContextNetBSD_x86_64::GetWatchpointAddress(uint32_t wp_index) { 920 if (wp_index >= NumSupportedHardwareWatchpoints()) 921 return LLDB_INVALID_ADDRESS; 922 RegisterValue reg_value; 923 const RegisterInfo *const reg_info_drN = 924 GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index); 925 if (ReadRegister(reg_info_drN, reg_value).Fail()) 926 return LLDB_INVALID_ADDRESS; 927 return reg_value.GetAsUInt64(); 928 } 929 930 uint32_t NativeRegisterContextNetBSD_x86_64::NumSupportedHardwareWatchpoints() { 931 // Available debug address registers: dr0, dr1, dr2, dr3 932 return 4; 933 } 934 935 #endif // defined(__x86_64__) 936