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