1//===-- NativeRegisterContextNetBSD_x86_64.cpp ----------------------------===// 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(__i386__) || 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_i386.h" 20#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h" 21 22// clang-format off 23#include <sys/types.h> 24#include <sys/ptrace.h> 25#include <sys/sysctl.h> 26#include <sys/uio.h> 27#include <x86/cpu.h> 28#include <x86/cpu_extended_state.h> 29#include <x86/specialreg.h> 30#include <elf.h> 31#include <err.h> 32#include <cstdint> 33#include <cstdlib> 34#include <optional> 35// clang-format on 36 37using namespace lldb_private; 38using namespace lldb_private::process_netbsd; 39 40// x86 64-bit general purpose registers. 41static const uint32_t g_gpr_regnums_x86_64[] = { 42 lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64, 43 lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rbp_x86_64, lldb_rsp_x86_64, 44 lldb_r8_x86_64, lldb_r9_x86_64, lldb_r10_x86_64, lldb_r11_x86_64, 45 lldb_r12_x86_64, lldb_r13_x86_64, lldb_r14_x86_64, lldb_r15_x86_64, 46 lldb_rip_x86_64, lldb_rflags_x86_64, lldb_cs_x86_64, lldb_fs_x86_64, 47 lldb_gs_x86_64, lldb_ss_x86_64, lldb_ds_x86_64, lldb_es_x86_64, 48 lldb_eax_x86_64, lldb_ebx_x86_64, lldb_ecx_x86_64, lldb_edx_x86_64, 49 lldb_edi_x86_64, lldb_esi_x86_64, lldb_ebp_x86_64, lldb_esp_x86_64, 50 lldb_r8d_x86_64, // Low 32 bits or r8 51 lldb_r9d_x86_64, // Low 32 bits or r9 52 lldb_r10d_x86_64, // Low 32 bits or r10 53 lldb_r11d_x86_64, // Low 32 bits or r11 54 lldb_r12d_x86_64, // Low 32 bits or r12 55 lldb_r13d_x86_64, // Low 32 bits or r13 56 lldb_r14d_x86_64, // Low 32 bits or r14 57 lldb_r15d_x86_64, // Low 32 bits or r15 58 lldb_ax_x86_64, lldb_bx_x86_64, lldb_cx_x86_64, lldb_dx_x86_64, 59 lldb_di_x86_64, lldb_si_x86_64, lldb_bp_x86_64, lldb_sp_x86_64, 60 lldb_r8w_x86_64, // Low 16 bits or r8 61 lldb_r9w_x86_64, // Low 16 bits or r9 62 lldb_r10w_x86_64, // Low 16 bits or r10 63 lldb_r11w_x86_64, // Low 16 bits or r11 64 lldb_r12w_x86_64, // Low 16 bits or r12 65 lldb_r13w_x86_64, // Low 16 bits or r13 66 lldb_r14w_x86_64, // Low 16 bits or r14 67 lldb_r15w_x86_64, // Low 16 bits or r15 68 lldb_ah_x86_64, lldb_bh_x86_64, lldb_ch_x86_64, lldb_dh_x86_64, 69 lldb_al_x86_64, lldb_bl_x86_64, lldb_cl_x86_64, lldb_dl_x86_64, 70 lldb_dil_x86_64, lldb_sil_x86_64, lldb_bpl_x86_64, lldb_spl_x86_64, 71 lldb_r8l_x86_64, // Low 8 bits or r8 72 lldb_r9l_x86_64, // Low 8 bits or r9 73 lldb_r10l_x86_64, // Low 8 bits or r10 74 lldb_r11l_x86_64, // Low 8 bits or r11 75 lldb_r12l_x86_64, // Low 8 bits or r12 76 lldb_r13l_x86_64, // Low 8 bits or r13 77 lldb_r14l_x86_64, // Low 8 bits or r14 78 lldb_r15l_x86_64, // Low 8 bits or r15 79 LLDB_INVALID_REGNUM // register sets need to end with this flag 80}; 81static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - 82 1 == 83 k_num_gpr_registers_x86_64, 84 "g_gpr_regnums_x86_64 has wrong number of register infos"); 85 86// x86 64-bit floating point registers. 87static const uint32_t g_fpu_regnums_x86_64[] = { 88 lldb_fctrl_x86_64, lldb_fstat_x86_64, lldb_ftag_x86_64, 89 lldb_fop_x86_64, lldb_fiseg_x86_64, lldb_fioff_x86_64, 90 lldb_fip_x86_64, lldb_foseg_x86_64, lldb_fooff_x86_64, 91 lldb_fdp_x86_64, lldb_mxcsr_x86_64, lldb_mxcsrmask_x86_64, 92 lldb_st0_x86_64, lldb_st1_x86_64, lldb_st2_x86_64, 93 lldb_st3_x86_64, lldb_st4_x86_64, lldb_st5_x86_64, 94 lldb_st6_x86_64, lldb_st7_x86_64, lldb_mm0_x86_64, 95 lldb_mm1_x86_64, lldb_mm2_x86_64, lldb_mm3_x86_64, 96 lldb_mm4_x86_64, lldb_mm5_x86_64, lldb_mm6_x86_64, 97 lldb_mm7_x86_64, lldb_xmm0_x86_64, lldb_xmm1_x86_64, 98 lldb_xmm2_x86_64, lldb_xmm3_x86_64, lldb_xmm4_x86_64, 99 lldb_xmm5_x86_64, lldb_xmm6_x86_64, lldb_xmm7_x86_64, 100 lldb_xmm8_x86_64, lldb_xmm9_x86_64, lldb_xmm10_x86_64, 101 lldb_xmm11_x86_64, lldb_xmm12_x86_64, lldb_xmm13_x86_64, 102 lldb_xmm14_x86_64, lldb_xmm15_x86_64, 103 LLDB_INVALID_REGNUM // register sets need to end with this flag 104}; 105static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) - 106 1 == 107 k_num_fpr_registers_x86_64, 108 "g_fpu_regnums_x86_64 has wrong number of register infos"); 109 110static const uint32_t g_avx_regnums_x86_64[] = { 111 lldb_ymm0_x86_64, lldb_ymm1_x86_64, lldb_ymm2_x86_64, lldb_ymm3_x86_64, 112 lldb_ymm4_x86_64, lldb_ymm5_x86_64, lldb_ymm6_x86_64, lldb_ymm7_x86_64, 113 lldb_ymm8_x86_64, lldb_ymm9_x86_64, lldb_ymm10_x86_64, lldb_ymm11_x86_64, 114 lldb_ymm12_x86_64, lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64, 115 LLDB_INVALID_REGNUM // register sets need to end with this flag 116}; 117static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - 118 1 == 119 k_num_avx_registers_x86_64, 120 "g_avx_regnums_x86_64 has wrong number of register infos"); 121 122static const uint32_t g_mpx_regnums_x86_64[] = { 123 // Note: we currently do not provide them but this is needed to avoid 124 // unnamed groups in SBFrame::GetRegisterContext(). 125 lldb_bnd0_x86_64, lldb_bnd1_x86_64, lldb_bnd2_x86_64, 126 lldb_bnd3_x86_64, lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64, 127 LLDB_INVALID_REGNUM // register sets need to end with this flag 128}; 129static_assert((sizeof(g_mpx_regnums_x86_64) / sizeof(g_mpx_regnums_x86_64[0])) - 130 1 == 131 k_num_mpx_registers_x86_64, 132 "g_mpx_regnums_x86_64 has wrong number of register infos"); 133 134// x86 debug registers. 135static const uint32_t g_dbr_regnums_x86_64[] = { 136 lldb_dr0_x86_64, lldb_dr1_x86_64, lldb_dr2_x86_64, lldb_dr3_x86_64, 137 lldb_dr4_x86_64, lldb_dr5_x86_64, lldb_dr6_x86_64, lldb_dr7_x86_64, 138 LLDB_INVALID_REGNUM // register sets need to end with this flag 139}; 140static_assert((sizeof(g_dbr_regnums_x86_64) / sizeof(g_dbr_regnums_x86_64[0])) - 141 1 == 142 k_num_dbr_registers_x86_64, 143 "g_dbr_regnums_x86_64 has wrong number of register infos"); 144 145// x86 32-bit general purpose registers. 146static const uint32_t g_gpr_regnums_i386[] = { 147 lldb_eax_i386, lldb_ebx_i386, lldb_ecx_i386, lldb_edx_i386, 148 lldb_edi_i386, lldb_esi_i386, lldb_ebp_i386, lldb_esp_i386, 149 lldb_eip_i386, lldb_eflags_i386, lldb_cs_i386, lldb_fs_i386, 150 lldb_gs_i386, lldb_ss_i386, lldb_ds_i386, lldb_es_i386, 151 lldb_ax_i386, lldb_bx_i386, lldb_cx_i386, lldb_dx_i386, 152 lldb_di_i386, lldb_si_i386, lldb_bp_i386, lldb_sp_i386, 153 lldb_ah_i386, lldb_bh_i386, lldb_ch_i386, lldb_dh_i386, 154 lldb_al_i386, lldb_bl_i386, lldb_cl_i386, lldb_dl_i386, 155 LLDB_INVALID_REGNUM // register sets need to end with this flag 156}; 157static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) - 158 1 == 159 k_num_gpr_registers_i386, 160 "g_gpr_regnums_i386 has wrong number of register infos"); 161 162// x86 32-bit floating point registers. 163static const uint32_t g_fpu_regnums_i386[] = { 164 lldb_fctrl_i386, lldb_fstat_i386, lldb_ftag_i386, lldb_fop_i386, 165 lldb_fiseg_i386, lldb_fioff_i386, lldb_foseg_i386, lldb_fooff_i386, 166 lldb_mxcsr_i386, lldb_mxcsrmask_i386, lldb_st0_i386, lldb_st1_i386, 167 lldb_st2_i386, lldb_st3_i386, lldb_st4_i386, lldb_st5_i386, 168 lldb_st6_i386, lldb_st7_i386, lldb_mm0_i386, lldb_mm1_i386, 169 lldb_mm2_i386, lldb_mm3_i386, lldb_mm4_i386, lldb_mm5_i386, 170 lldb_mm6_i386, lldb_mm7_i386, lldb_xmm0_i386, lldb_xmm1_i386, 171 lldb_xmm2_i386, lldb_xmm3_i386, lldb_xmm4_i386, lldb_xmm5_i386, 172 lldb_xmm6_i386, lldb_xmm7_i386, 173 LLDB_INVALID_REGNUM // register sets need to end with this flag 174}; 175static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) - 176 1 == 177 k_num_fpr_registers_i386, 178 "g_fpu_regnums_i386 has wrong number of register infos"); 179 180static const uint32_t g_avx_regnums_i386[] = { 181 lldb_ymm0_i386, lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386, 182 lldb_ymm4_i386, lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386, 183 LLDB_INVALID_REGNUM // register sets need to end with this flag 184}; 185static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - 186 1 == 187 k_num_avx_registers_i386, 188 "g_avx_regnums_i386 has wrong number of register infos"); 189 190static const uint32_t g_mpx_regnums_i386[] = { 191 // Note: we currently do not provide them but this is needed to avoid 192 // unnamed groups in SBFrame::GetRegisterContext(). 193 lldb_bnd0_i386, lldb_bnd1_i386, lldb_bnd2_i386, 194 lldb_bnd3_i386, lldb_bndcfgu_i386, lldb_bndstatus_i386, 195 LLDB_INVALID_REGNUM // register sets need to end with this flag 196}; 197static_assert((sizeof(g_mpx_regnums_i386) / sizeof(g_mpx_regnums_i386[0])) - 198 1 == 199 k_num_mpx_registers_i386, 200 "g_mpx_regnums_i386 has wrong number of register infos"); 201 202// x86 debug registers. 203static const uint32_t g_dbr_regnums_i386[] = { 204 lldb_dr0_i386, lldb_dr1_i386, lldb_dr2_i386, lldb_dr3_i386, 205 lldb_dr4_i386, lldb_dr5_i386, lldb_dr6_i386, lldb_dr7_i386, 206 LLDB_INVALID_REGNUM // register sets need to end with this flag 207}; 208static_assert((sizeof(g_dbr_regnums_i386) / sizeof(g_dbr_regnums_i386[0])) - 209 1 == 210 k_num_dbr_registers_i386, 211 "g_dbr_regnums_i386 has wrong number of register infos"); 212 213// Number of register sets provided by this context. 214enum { k_num_register_sets = 5 }; 215 216// Register sets for x86 32-bit. 217static const RegisterSet g_reg_sets_i386[k_num_register_sets] = { 218 {"General Purpose Registers", "gpr", k_num_gpr_registers_i386, 219 g_gpr_regnums_i386}, 220 {"Floating Point Registers", "fpu", k_num_fpr_registers_i386, 221 g_fpu_regnums_i386}, 222 {"Debug Registers", "dbr", k_num_dbr_registers_i386, g_dbr_regnums_i386}, 223 {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386, 224 g_avx_regnums_i386}, 225 {"Memory Protection Extensions", "mpx", k_num_mpx_registers_i386, 226 g_mpx_regnums_i386}, 227}; 228 229// Register sets for x86 64-bit. 230static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = { 231 {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, 232 g_gpr_regnums_x86_64}, 233 {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, 234 g_fpu_regnums_x86_64}, 235 {"Debug Registers", "dbr", k_num_dbr_registers_x86_64, 236 g_dbr_regnums_x86_64}, 237 {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, 238 g_avx_regnums_x86_64}, 239 {"Memory Protection Extensions", "mpx", k_num_mpx_registers_x86_64, 240 g_mpx_regnums_x86_64}, 241}; 242 243#define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize()) 244 245NativeRegisterContextNetBSD * 246NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD( 247 const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { 248 return new NativeRegisterContextNetBSD_x86_64(target_arch, native_thread); 249} 250 251// NativeRegisterContextNetBSD_x86_64 members. 252 253static RegisterInfoInterface * 254CreateRegisterInfoInterface(const ArchSpec &target_arch) { 255 if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) { 256 // 32-bit hosts run with a RegisterContextNetBSD_i386 context. 257 return new RegisterContextNetBSD_i386(target_arch); 258 } else { 259 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && 260 "Register setting path assumes this is a 64-bit host"); 261 // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the 262 // x86_64 register context. 263 return new RegisterContextNetBSD_x86_64(target_arch); 264 } 265} 266 267NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64( 268 const ArchSpec &target_arch, NativeThreadProtocol &native_thread) 269 : NativeRegisterContextRegisterInfo( 270 native_thread, CreateRegisterInfoInterface(target_arch)), 271 NativeRegisterContextDBReg_x86(native_thread), m_regset_offsets({0}) { 272 assert(m_gpr.size() == GetRegisterInfoInterface().GetGPRSize()); 273 std::array<uint32_t, MaxRegularRegSet + 1> first_regnos; 274 275 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { 276 case llvm::Triple::x86: 277 first_regnos[FPRegSet] = lldb_fctrl_i386; 278 first_regnos[DBRegSet] = lldb_dr0_i386; 279 break; 280 case llvm::Triple::x86_64: 281 first_regnos[FPRegSet] = lldb_fctrl_x86_64; 282 first_regnos[DBRegSet] = lldb_dr0_x86_64; 283 break; 284 default: 285 llvm_unreachable("Unhandled target architecture."); 286 } 287 288 for (int i : {FPRegSet, DBRegSet}) 289 m_regset_offsets[i] = GetRegisterInfoInterface() 290 .GetRegisterInfo()[first_regnos[i]] 291 .byte_offset; 292} 293 294uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetCount() const { 295 return k_num_register_sets; 296} 297 298const RegisterSet * 299NativeRegisterContextNetBSD_x86_64::GetRegisterSet(uint32_t set_index) const { 300 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { 301 case llvm::Triple::x86: 302 return &g_reg_sets_i386[set_index]; 303 case llvm::Triple::x86_64: 304 return &g_reg_sets_x86_64[set_index]; 305 default: 306 llvm_unreachable("Unhandled target architecture."); 307 } 308} 309 310std::optional<NativeRegisterContextNetBSD_x86_64::RegSetKind> 311NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum( 312 uint32_t reg_num) const { 313 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { 314 case llvm::Triple::x86: 315 if (reg_num >= k_first_gpr_i386 && reg_num <= k_last_gpr_i386) 316 return GPRegSet; 317 if (reg_num >= k_first_fpr_i386 && reg_num <= k_last_fpr_i386) 318 return FPRegSet; 319 if (reg_num >= k_first_avx_i386 && reg_num <= k_last_avx_i386) 320 return YMMRegSet; 321 if (reg_num >= k_first_mpxr_i386 && reg_num <= k_last_mpxr_i386) 322 return std::nullopt; // MPXR 323 if (reg_num >= k_first_mpxc_i386 && reg_num <= k_last_mpxc_i386) 324 return std::nullopt; // MPXC 325 if (reg_num >= k_first_dbr_i386 && reg_num <= k_last_dbr_i386) 326 return DBRegSet; // DBR 327 break; 328 case llvm::Triple::x86_64: 329 if (reg_num >= k_first_gpr_x86_64 && reg_num <= k_last_gpr_x86_64) 330 return GPRegSet; 331 if (reg_num >= k_first_fpr_x86_64 && reg_num <= k_last_fpr_x86_64) 332 return FPRegSet; 333 if (reg_num >= k_first_avx_x86_64 && reg_num <= k_last_avx_x86_64) 334 return YMMRegSet; 335 if (reg_num >= k_first_mpxr_x86_64 && reg_num <= k_last_mpxr_x86_64) 336 return std::nullopt; // MPXR 337 if (reg_num >= k_first_mpxc_x86_64 && reg_num <= k_last_mpxc_x86_64) 338 return std::nullopt; // MPXC 339 if (reg_num >= k_first_dbr_x86_64 && reg_num <= k_last_dbr_x86_64) 340 return DBRegSet; // DBR 341 break; 342 default: 343 llvm_unreachable("Unhandled target architecture."); 344 } 345 346 llvm_unreachable("Register does not belong to any register set"); 347} 348 349Status NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(RegSetKind set) { 350 switch (set) { 351 case GPRegSet: 352 return DoRegisterSet(PT_GETREGS, m_gpr.data()); 353 case DBRegSet: 354 return DoRegisterSet(PT_GETDBREGS, m_dbr.data()); 355 case FPRegSet: 356 case YMMRegSet: 357 case MPXRegSet: { 358 struct iovec iov = {m_xstate.data(), m_xstate.size()}; 359 Status ret = DoRegisterSet(PT_GETXSTATE, &iov); 360 assert(reinterpret_cast<xstate *>(m_xstate.data())->xs_rfbm & XCR0_X87); 361 return ret; 362 } 363 } 364 llvm_unreachable("NativeRegisterContextNetBSD_x86_64::ReadRegisterSet"); 365} 366 367Status NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(RegSetKind set) { 368 switch (set) { 369 case GPRegSet: 370 return DoRegisterSet(PT_SETREGS, m_gpr.data()); 371 case DBRegSet: 372 return DoRegisterSet(PT_SETDBREGS, m_dbr.data()); 373 case FPRegSet: 374 case YMMRegSet: 375 case MPXRegSet: { 376 struct iovec iov = {&m_xstate, sizeof(m_xstate)}; 377 return DoRegisterSet(PT_SETXSTATE, &iov); 378 } 379 } 380 llvm_unreachable("NativeRegisterContextNetBSD_x86_64::WriteRegisterSet"); 381} 382 383Status 384NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, 385 RegisterValue ®_value) { 386 Status error; 387 388 if (!reg_info) { 389 error.SetErrorString("reg_info NULL"); 390 return error; 391 } 392 393 uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 394 if (reg == LLDB_INVALID_REGNUM) { 395 // This is likely an internal register for lldb use only and should not be 396 // directly queried. 397 error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " 398 "register, cannot read directly", 399 reg_info->name); 400 return error; 401 } 402 403 std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); 404 if (!opt_set) { 405 // This is likely an internal register for lldb use only and should not be 406 // directly queried. 407 error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", 408 reg_info->name); 409 return error; 410 } 411 412 RegSetKind set = *opt_set; 413 error = ReadRegisterSet(set); 414 if (error.Fail()) 415 return error; 416 417 switch (set) { 418 case GPRegSet: 419 case FPRegSet: 420 case DBRegSet: { 421 void *data = GetOffsetRegSetData(set, reg_info->byte_offset); 422 FXSAVE *fpr = reinterpret_cast<FXSAVE *>(m_xstate.data() + 423 offsetof(xstate, xs_fxsave)); 424 if (data == &fpr->ftag) // ftag 425 reg_value.SetUInt16( 426 AbridgedToFullTagWord(fpr->ftag, fpr->fstat, fpr->stmm)); 427 else 428 reg_value.SetBytes(data, reg_info->byte_size, endian::InlHostByteOrder()); 429 break; 430 } 431 case YMMRegSet: { 432 std::optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg); 433 if (!ymm_reg) { 434 error.SetErrorStringWithFormat( 435 "register \"%s\" not supported by CPU/kernel", reg_info->name); 436 } else { 437 YMMReg ymm = XStateToYMM(ymm_reg->xmm, ymm_reg->ymm_hi); 438 reg_value.SetBytes(ymm.bytes, reg_info->byte_size, 439 endian::InlHostByteOrder()); 440 } 441 break; 442 } 443 case MPXRegSet: 444 llvm_unreachable("MPX regset should have returned error"); 445 } 446 447 return error; 448} 449 450Status NativeRegisterContextNetBSD_x86_64::WriteRegister( 451 const RegisterInfo *reg_info, const RegisterValue ®_value) { 452 453 Status error; 454 455 if (!reg_info) { 456 error.SetErrorString("reg_info NULL"); 457 return error; 458 } 459 460 uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 461 if (reg == LLDB_INVALID_REGNUM) { 462 // This is likely an internal register for lldb use only and should not be 463 // directly queried. 464 error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " 465 "register, cannot read directly", 466 reg_info->name); 467 return error; 468 } 469 470 std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); 471 if (!opt_set) { 472 // This is likely an internal register for lldb use only and should not be 473 // directly queried. 474 error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", 475 reg_info->name); 476 return error; 477 } 478 479 RegSetKind set = *opt_set; 480 uint64_t new_xstate_bv = 0; 481 482 error = ReadRegisterSet(set); 483 if (error.Fail()) 484 return error; 485 486 switch (set) { 487 case GPRegSet: 488 case DBRegSet: 489 ::memcpy(GetOffsetRegSetData(set, reg_info->byte_offset), 490 reg_value.GetBytes(), reg_value.GetByteSize()); 491 break; 492 case FPRegSet: { 493 void *data = GetOffsetRegSetData(set, reg_info->byte_offset); 494 FXSAVE *fpr = reinterpret_cast<FXSAVE *>(m_xstate.data() + 495 offsetof(xstate, xs_fxsave)); 496 if (data == &fpr->ftag) // ftag 497 fpr->ftag = FullToAbridgedTagWord(reg_value.GetAsUInt16()); 498 else 499 ::memcpy(data, reg_value.GetBytes(), reg_value.GetByteSize()); 500 if (data >= &fpr->xmm) 501 new_xstate_bv |= XCR0_SSE; 502 else if (data >= &fpr->mxcsr && data < &fpr->stmm) 503 new_xstate_bv |= XCR0_SSE; 504 else 505 new_xstate_bv |= XCR0_X87; 506 break; 507 } 508 case YMMRegSet: { 509 std::optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg); 510 if (!ymm_reg) { 511 error.SetErrorStringWithFormat( 512 "register \"%s\" not supported by CPU/kernel", reg_info->name); 513 } else { 514 YMMReg ymm; 515 ::memcpy(ymm.bytes, reg_value.GetBytes(), reg_value.GetByteSize()); 516 YMMToXState(ymm, ymm_reg->xmm, ymm_reg->ymm_hi); 517 new_xstate_bv |= XCR0_SSE | XCR0_YMM_Hi128; 518 } 519 break; 520 } 521 case MPXRegSet: 522 llvm_unreachable("MPX regset should have returned error"); 523 } 524 525 if (new_xstate_bv != 0) 526 reinterpret_cast<xstate *>(m_xstate.data())->xs_xstate_bv |= new_xstate_bv; 527 return WriteRegisterSet(set); 528} 529 530Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues( 531 lldb::WritableDataBufferSP &data_sp) { 532 Status error; 533 534 data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); 535 error = ReadRegisterSet(GPRegSet); 536 if (error.Fail()) 537 return error; 538 539 uint8_t *dst = data_sp->GetBytes(); 540 ::memcpy(dst, m_gpr.data(), GetRegisterInfoInterface().GetGPRSize()); 541 dst += GetRegisterInfoInterface().GetGPRSize(); 542 543 return error; 544} 545 546Status NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues( 547 const lldb::DataBufferSP &data_sp) { 548 Status error; 549 550 if (!data_sp) { 551 error.SetErrorStringWithFormat( 552 "NativeRegisterContextNetBSD_x86_64::%s invalid data_sp provided", 553 __FUNCTION__); 554 return error; 555 } 556 557 if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { 558 error.SetErrorStringWithFormat( 559 "NativeRegisterContextNetBSD_x86_64::%s data_sp contained mismatched " 560 "data size, expected %zu, actual %" PRIu64, 561 __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); 562 return error; 563 } 564 565 const uint8_t *src = data_sp->GetBytes(); 566 if (src == nullptr) { 567 error.SetErrorStringWithFormat("NativeRegisterContextNetBSD_x86_64::%s " 568 "DataBuffer::GetBytes() returned a null " 569 "pointer", 570 __FUNCTION__); 571 return error; 572 } 573 ::memcpy(m_gpr.data(), src, GetRegisterInfoInterface().GetGPRSize()); 574 575 error = WriteRegisterSet(GPRegSet); 576 if (error.Fail()) 577 return error; 578 src += GetRegisterInfoInterface().GetGPRSize(); 579 580 return error; 581} 582 583llvm::Error NativeRegisterContextNetBSD_x86_64::CopyHardwareWatchpointsFrom( 584 NativeRegisterContextNetBSD &source) { 585 auto &r_source = static_cast<NativeRegisterContextNetBSD_x86_64 &>(source); 586 // NB: This implicitly reads the whole dbreg set. 587 RegisterValue dr7; 588 Status res = r_source.ReadRegister(GetDR(7), dr7); 589 if (!res.Fail()) { 590 // copy dbregs only if any watchpoints were set 591 if ((dr7.GetAsUInt64() & 0xFF) == 0) 592 return llvm::Error::success(); 593 594 m_dbr = r_source.m_dbr; 595 res = WriteRegisterSet(DBRegSet); 596 } 597 return res.ToError(); 598} 599 600uint8_t * 601NativeRegisterContextNetBSD_x86_64::GetOffsetRegSetData(RegSetKind set, 602 size_t reg_offset) { 603 uint8_t *base; 604 switch (set) { 605 case GPRegSet: 606 base = m_gpr.data(); 607 break; 608 case FPRegSet: 609 base = m_xstate.data() + offsetof(xstate, xs_fxsave); 610 break; 611 case DBRegSet: 612 base = m_dbr.data(); 613 break; 614 case YMMRegSet: 615 llvm_unreachable("GetRegSetData() is unsuitable for this regset."); 616 case MPXRegSet: 617 llvm_unreachable("MPX regset should have returned error"); 618 } 619 assert(reg_offset >= m_regset_offsets[set]); 620 return base + (reg_offset - m_regset_offsets[set]); 621} 622 623std::optional<NativeRegisterContextNetBSD_x86_64::YMMSplitPtr> 624NativeRegisterContextNetBSD_x86_64::GetYMMSplitReg(uint32_t reg) { 625 auto xst = reinterpret_cast<xstate *>(m_xstate.data()); 626 if (!(xst->xs_rfbm & XCR0_SSE) || !(xst->xs_rfbm & XCR0_YMM_Hi128)) 627 return std::nullopt; 628 629 uint32_t reg_index; 630 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { 631 case llvm::Triple::x86: 632 reg_index = reg - lldb_ymm0_i386; 633 break; 634 case llvm::Triple::x86_64: 635 reg_index = reg - lldb_ymm0_x86_64; 636 break; 637 default: 638 llvm_unreachable("Unhandled target architecture."); 639 } 640 641 return YMMSplitPtr{&xst->xs_fxsave.fx_xmm[reg_index], 642 &xst->xs_ymm_hi128.xs_ymm[reg_index]}; 643} 644 645#endif // defined(__x86_64__) 646