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