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