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 30 using namespace lldb_private; 31 using namespace lldb_private::process_freebsd; 32 33 // x86 64-bit general purpose registers. 34 static 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 }; 74 static_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. 80 static 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 }; 98 static_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 103 static 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 }; 110 static_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 115 static 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 }; 122 static_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. 128 static 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 }; 133 static_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. 139 static 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 }; 150 static_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. 156 static 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 }; 168 static_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 173 static 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 }; 178 static_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 183 static 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 }; 190 static_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. 196 static 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 }; 201 static_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. 207 enum { k_num_register_sets = 5 }; 208 209 // Register sets for x86 32-bit. 210 static 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. 223 static 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 238 NativeRegisterContextFreeBSD * 239 NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD( 240 const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) { 241 return new NativeRegisterContextFreeBSD_x86_64(target_arch, native_thread); 242 } 243 244 // NativeRegisterContextFreeBSD_x86_64 members. 245 246 static RegisterInfoInterface * 247 CreateRegisterInfoInterface(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 260 NativeRegisterContextFreeBSD_x86_64::NativeRegisterContextFreeBSD_x86_64( 261 const ArchSpec &target_arch, NativeThreadFreeBSD &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 287 uint32_t NativeRegisterContextFreeBSD_x86_64::GetRegisterSetCount() const { 288 return k_num_register_sets; 289 } 290 291 const RegisterSet * 292 NativeRegisterContextFreeBSD_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 303 std::optional<NativeRegisterContextFreeBSD_x86_64::RegSetKind> 304 NativeRegisterContextFreeBSD_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 342 Status 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 383 Status 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 409 Status 410 NativeRegisterContextFreeBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, 411 RegisterValue ®_value) { 412 Status error; 413 414 if (!reg_info) { 415 error = Status::FromErrorString("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 = Status::FromErrorStringWithFormat( 424 "register \"%s\" is an internal-only lldb " 425 "register, cannot read directly", 426 reg_info->name); 427 return error; 428 } 429 430 std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); 431 if (!opt_set) { 432 // This is likely an internal register for lldb use only and should not be 433 // directly queried. 434 error = Status::FromErrorStringWithFormat( 435 "register \"%s\" is in unrecognized set", reg_info->name); 436 return error; 437 } 438 439 RegSetKind set = opt_set.value(); 440 error = ReadRegisterSet(set); 441 if (error.Fail()) 442 return error; 443 444 switch (set) { 445 case GPRegSet: 446 case FPRegSet: 447 case DBRegSet: { 448 void *data = GetOffsetRegSetData(set, reg_info->byte_offset); 449 FXSAVE *fpr = reinterpret_cast<FXSAVE *>(m_fpr.data()); 450 if (data == &fpr->ftag) // ftag 451 reg_value.SetUInt16( 452 AbridgedToFullTagWord(fpr->ftag, fpr->fstat, fpr->stmm)); 453 else 454 reg_value.SetBytes(data, reg_info->byte_size, endian::InlHostByteOrder()); 455 break; 456 } 457 case YMMRegSet: { 458 std::optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg); 459 if (!ymm_reg) { 460 error = Status::FromErrorStringWithFormat( 461 "register \"%s\" not supported by CPU/kernel", reg_info->name); 462 } else { 463 YMMReg ymm = XStateToYMM(ymm_reg->xmm, ymm_reg->ymm_hi); 464 reg_value.SetBytes(ymm.bytes, reg_info->byte_size, 465 endian::InlHostByteOrder()); 466 } 467 break; 468 } 469 case MPXRegSet: 470 llvm_unreachable("MPX regset should have returned error"); 471 } 472 473 return error; 474 } 475 476 Status NativeRegisterContextFreeBSD_x86_64::WriteRegister( 477 const RegisterInfo *reg_info, const RegisterValue ®_value) { 478 479 Status error; 480 481 if (!reg_info) { 482 error = Status::FromErrorString("reg_info NULL"); 483 return error; 484 } 485 486 uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 487 if (reg == LLDB_INVALID_REGNUM) { 488 // This is likely an internal register for lldb use only and should not be 489 // directly queried. 490 error = Status::FromErrorStringWithFormat( 491 "register \"%s\" is an internal-only lldb " 492 "register, cannot read directly", 493 reg_info->name); 494 return error; 495 } 496 497 std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); 498 if (!opt_set) { 499 // This is likely an internal register for lldb use only and should not be 500 // directly queried. 501 error = Status::FromErrorStringWithFormat( 502 "register \"%s\" is in unrecognized set", reg_info->name); 503 return error; 504 } 505 506 RegSetKind set = opt_set.value(); 507 error = ReadRegisterSet(set); 508 if (error.Fail()) 509 return error; 510 511 switch (set) { 512 case GPRegSet: 513 case FPRegSet: 514 case DBRegSet: { 515 void *data = GetOffsetRegSetData(set, reg_info->byte_offset); 516 FXSAVE *fpr = reinterpret_cast<FXSAVE *>(m_fpr.data()); 517 if (data == &fpr->ftag) // ftag 518 fpr->ftag = FullToAbridgedTagWord(reg_value.GetAsUInt16()); 519 else 520 ::memcpy(data, reg_value.GetBytes(), reg_value.GetByteSize()); 521 break; 522 } 523 case YMMRegSet: { 524 std::optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg); 525 if (!ymm_reg) { 526 error = Status::FromErrorStringWithFormat( 527 "register \"%s\" not supported by CPU/kernel", reg_info->name); 528 } else { 529 YMMReg ymm; 530 ::memcpy(ymm.bytes, reg_value.GetBytes(), reg_value.GetByteSize()); 531 YMMToXState(ymm, ymm_reg->xmm, ymm_reg->ymm_hi); 532 } 533 break; 534 } 535 case MPXRegSet: 536 llvm_unreachable("MPX regset should have returned error"); 537 } 538 539 return WriteRegisterSet(set); 540 } 541 542 Status NativeRegisterContextFreeBSD_x86_64::ReadAllRegisterValues( 543 lldb::WritableDataBufferSP &data_sp) { 544 Status error; 545 546 data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); 547 error = ReadRegisterSet(GPRegSet); 548 if (error.Fail()) 549 return error; 550 551 uint8_t *dst = data_sp->GetBytes(); 552 ::memcpy(dst, m_gpr.data(), GetRegisterInfoInterface().GetGPRSize()); 553 dst += GetRegisterInfoInterface().GetGPRSize(); 554 555 return error; 556 } 557 558 Status NativeRegisterContextFreeBSD_x86_64::WriteAllRegisterValues( 559 const lldb::DataBufferSP &data_sp) { 560 Status error; 561 562 if (!data_sp) { 563 error = Status::FromErrorStringWithFormat( 564 "NativeRegisterContextFreeBSD_x86_64::%s invalid data_sp provided", 565 __FUNCTION__); 566 return error; 567 } 568 569 if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { 570 error = Status::FromErrorStringWithFormat( 571 "NativeRegisterContextFreeBSD_x86_64::%s data_sp contained mismatched " 572 "data size, expected %zu, actual %" PRIu64, 573 __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); 574 return error; 575 } 576 577 const uint8_t *src = data_sp->GetBytes(); 578 if (src == nullptr) { 579 error = Status::FromErrorStringWithFormat( 580 "NativeRegisterContextFreeBSD_x86_64::%s " 581 "DataBuffer::GetBytes() returned a null " 582 "pointer", 583 __FUNCTION__); 584 return error; 585 } 586 ::memcpy(m_gpr.data(), src, GetRegisterInfoInterface().GetGPRSize()); 587 588 error = WriteRegisterSet(GPRegSet); 589 if (error.Fail()) 590 return error; 591 src += GetRegisterInfoInterface().GetGPRSize(); 592 593 return error; 594 } 595 596 llvm::Error NativeRegisterContextFreeBSD_x86_64::CopyHardwareWatchpointsFrom( 597 NativeRegisterContextFreeBSD &source) { 598 auto &r_source = static_cast<NativeRegisterContextFreeBSD_x86_64 &>(source); 599 // NB: This implicitly reads the whole dbreg set. 600 RegisterValue dr7; 601 Status res = r_source.ReadRegister(GetDR(7), dr7); 602 if (!res.Fail()) { 603 // copy dbregs only if any watchpoints were set 604 if ((dr7.GetAsUInt64() & 0xFF) == 0) 605 return llvm::Error::success(); 606 607 m_dbr = r_source.m_dbr; 608 res = WriteRegisterSet(DBRegSet); 609 } 610 return res.ToError(); 611 } 612 613 uint8_t * 614 NativeRegisterContextFreeBSD_x86_64::GetOffsetRegSetData(RegSetKind set, 615 size_t reg_offset) { 616 uint8_t *base; 617 switch (set) { 618 case GPRegSet: 619 base = m_gpr.data(); 620 break; 621 case FPRegSet: 622 base = m_fpr.data(); 623 break; 624 case DBRegSet: 625 base = m_dbr.data(); 626 break; 627 case YMMRegSet: 628 llvm_unreachable("GetRegSetData() is unsuitable for this regset."); 629 case MPXRegSet: 630 llvm_unreachable("MPX regset should have returned error"); 631 } 632 assert(reg_offset >= m_regset_offsets[set]); 633 return base + (reg_offset - m_regset_offsets[set]); 634 } 635 636 std::optional<NativeRegisterContextFreeBSD_x86_64::YMMSplitPtr> 637 NativeRegisterContextFreeBSD_x86_64::GetYMMSplitReg(uint32_t reg) { 638 uint32_t offset = m_xsave_offsets[YMMRegSet]; 639 if (offset == LLDB_INVALID_XSAVE_OFFSET) 640 return std::nullopt; 641 642 uint32_t reg_index; 643 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { 644 case llvm::Triple::x86: 645 reg_index = reg - lldb_ymm0_i386; 646 break; 647 case llvm::Triple::x86_64: 648 reg_index = reg - lldb_ymm0_x86_64; 649 break; 650 default: 651 llvm_unreachable("Unhandled target architecture."); 652 } 653 654 auto *fpreg = reinterpret_cast<struct savexmm_ymm *>(m_xsave.data()); 655 auto *ymmreg = reinterpret_cast<struct ymmacc *>(m_xsave.data() + offset); 656 657 return YMMSplitPtr{&fpreg->sv_xmm[reg_index], &ymmreg[reg_index]}; 658 } 659 660 #endif // defined(__x86_64__) 661