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