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