1 //===-- NativeRegisterContextNetBSD_x86_64.cpp ----------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #if defined(__i386__) || defined(__x86_64__)
11 #include "NativeRegisterContextNetBSD_x86_64.h"
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"
19 #include "Plugins/Process/Utility/RegisterContextNetBSD_i386.h"
20 #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
23 #include <sys/types.h>
24 #include <sys/ptrace.h>
25 #include <sys/sysctl.h>
28 #include <x86/cpu_extended_state.h>
29 #include <x86/specialreg.h>
37 using namespace lldb_private
;
38 using namespace lldb_private::process_netbsd
;
40 // x86 64-bit general purpose registers.
41 static 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
81 static_assert((sizeof(g_gpr_regnums_x86_64
) / sizeof(g_gpr_regnums_x86_64
[0])) -
83 k_num_gpr_registers_x86_64
,
84 "g_gpr_regnums_x86_64 has wrong number of register infos");
86 // x86 64-bit floating point registers.
87 static 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
105 static_assert((sizeof(g_fpu_regnums_x86_64
) / sizeof(g_fpu_regnums_x86_64
[0])) -
107 k_num_fpr_registers_x86_64
,
108 "g_fpu_regnums_x86_64 has wrong number of register infos");
110 static 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
117 static_assert((sizeof(g_avx_regnums_x86_64
) / sizeof(g_avx_regnums_x86_64
[0])) -
119 k_num_avx_registers_x86_64
,
120 "g_avx_regnums_x86_64 has wrong number of register infos");
122 static 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
129 static_assert((sizeof(g_mpx_regnums_x86_64
) / sizeof(g_mpx_regnums_x86_64
[0])) -
131 k_num_mpx_registers_x86_64
,
132 "g_mpx_regnums_x86_64 has wrong number of register infos");
134 // x86 debug registers.
135 static 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
140 static_assert((sizeof(g_dbr_regnums_x86_64
) / sizeof(g_dbr_regnums_x86_64
[0])) -
142 k_num_dbr_registers_x86_64
,
143 "g_dbr_regnums_x86_64 has wrong number of register infos");
145 // x86 32-bit general purpose registers.
146 static 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
157 static_assert((sizeof(g_gpr_regnums_i386
) / sizeof(g_gpr_regnums_i386
[0])) -
159 k_num_gpr_registers_i386
,
160 "g_gpr_regnums_i386 has wrong number of register infos");
162 // x86 32-bit floating point registers.
163 static 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
175 static_assert((sizeof(g_fpu_regnums_i386
) / sizeof(g_fpu_regnums_i386
[0])) -
177 k_num_fpr_registers_i386
,
178 "g_fpu_regnums_i386 has wrong number of register infos");
180 static 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
185 static_assert((sizeof(g_avx_regnums_i386
) / sizeof(g_avx_regnums_i386
[0])) -
187 k_num_avx_registers_i386
,
188 "g_avx_regnums_i386 has wrong number of register infos");
190 static 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
197 static_assert((sizeof(g_mpx_regnums_i386
) / sizeof(g_mpx_regnums_i386
[0])) -
199 k_num_mpx_registers_i386
,
200 "g_mpx_regnums_i386 has wrong number of register infos");
202 // x86 debug registers.
203 static 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
208 static_assert((sizeof(g_dbr_regnums_i386
) / sizeof(g_dbr_regnums_i386
[0])) -
210 k_num_dbr_registers_i386
,
211 "g_dbr_regnums_i386 has wrong number of register infos");
213 // Number of register sets provided by this context.
214 enum { k_num_register_sets
= 5 };
216 // Register sets for x86 32-bit.
217 static const RegisterSet g_reg_sets_i386
[k_num_register_sets
] = {
218 {"General Purpose Registers", "gpr", k_num_gpr_registers_i386
,
220 {"Floating Point Registers", "fpu", k_num_fpr_registers_i386
,
222 {"Debug Registers", "dbr", k_num_dbr_registers_i386
, g_dbr_regnums_i386
},
223 {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386
,
225 {"Memory Protection Extensions", "mpx", k_num_mpx_registers_i386
,
229 // Register sets for x86 64-bit.
230 static 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
},
243 #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize())
245 NativeRegisterContextNetBSD
*
246 NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(
247 const ArchSpec
&target_arch
, NativeThreadProtocol
&native_thread
) {
248 return new NativeRegisterContextNetBSD_x86_64(target_arch
, native_thread
);
251 // NativeRegisterContextNetBSD_x86_64 members.
253 static RegisterInfoInterface
*
254 CreateRegisterInfoInterface(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
);
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
);
267 NativeRegisterContextNetBSD_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
;
275 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
276 case llvm::Triple::x86
:
277 first_regnos
[FPRegSet
] = lldb_fctrl_i386
;
278 first_regnos
[DBRegSet
] = lldb_dr0_i386
;
280 case llvm::Triple::x86_64
:
281 first_regnos
[FPRegSet
] = lldb_fctrl_x86_64
;
282 first_regnos
[DBRegSet
] = lldb_dr0_x86_64
;
285 llvm_unreachable("Unhandled target architecture.");
288 for (int i
: {FPRegSet
, DBRegSet
})
289 m_regset_offsets
[i
] = GetRegisterInfoInterface()
290 .GetRegisterInfo()[first_regnos
[i
]]
294 uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetCount() const {
295 return k_num_register_sets
;
299 NativeRegisterContextNetBSD_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
];
306 llvm_unreachable("Unhandled target architecture.");
310 std::optional
<NativeRegisterContextNetBSD_x86_64::RegSetKind
>
311 NativeRegisterContextNetBSD_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
)
317 if (reg_num
>= k_first_fpr_i386
&& reg_num
<= k_last_fpr_i386
)
319 if (reg_num
>= k_first_avx_i386
&& reg_num
<= k_last_avx_i386
)
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
328 case llvm::Triple::x86_64
:
329 if (reg_num
>= k_first_gpr_x86_64
&& reg_num
<= k_last_gpr_x86_64
)
331 if (reg_num
>= k_first_fpr_x86_64
&& reg_num
<= k_last_fpr_x86_64
)
333 if (reg_num
>= k_first_avx_x86_64
&& reg_num
<= k_last_avx_x86_64
)
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
343 llvm_unreachable("Unhandled target architecture.");
346 llvm_unreachable("Register does not belong to any register set");
349 Status
NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(RegSetKind set
) {
352 return DoRegisterSet(PT_GETREGS
, m_gpr
.data());
354 return DoRegisterSet(PT_GETDBREGS
, m_dbr
.data());
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
);
364 llvm_unreachable("NativeRegisterContextNetBSD_x86_64::ReadRegisterSet");
367 Status
NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(RegSetKind set
) {
370 return DoRegisterSet(PT_SETREGS
, m_gpr
.data());
372 return DoRegisterSet(PT_SETDBREGS
, m_dbr
.data());
376 struct iovec iov
= {&m_xstate
, sizeof(m_xstate
)};
377 return DoRegisterSet(PT_SETXSTATE
, &iov
);
380 llvm_unreachable("NativeRegisterContextNetBSD_x86_64::WriteRegisterSet");
384 NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo
*reg_info
,
385 RegisterValue
®_value
) {
389 error
.SetErrorString("reg_info NULL");
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
397 error
.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
398 "register, cannot read directly",
403 std::optional
<RegSetKind
> opt_set
= GetSetForNativeRegNum(reg
);
405 // This is likely an internal register for lldb use only and should not be
407 error
.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
412 RegSetKind set
= *opt_set
;
413 error
= ReadRegisterSet(set
);
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
426 AbridgedToFullTagWord(fpr
->ftag
, fpr
->fstat
, fpr
->stmm
));
428 reg_value
.SetBytes(data
, reg_info
->byte_size
, endian::InlHostByteOrder());
432 std::optional
<YMMSplitPtr
> ymm_reg
= GetYMMSplitReg(reg
);
434 error
.SetErrorStringWithFormat(
435 "register \"%s\" not supported by CPU/kernel", reg_info
->name
);
437 YMMReg ymm
= XStateToYMM(ymm_reg
->xmm
, ymm_reg
->ymm_hi
);
438 reg_value
.SetBytes(ymm
.bytes
, reg_info
->byte_size
,
439 endian::InlHostByteOrder());
444 llvm_unreachable("MPX regset should have returned error");
450 Status
NativeRegisterContextNetBSD_x86_64::WriteRegister(
451 const RegisterInfo
*reg_info
, const RegisterValue
®_value
) {
456 error
.SetErrorString("reg_info NULL");
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
464 error
.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
465 "register, cannot read directly",
470 std::optional
<RegSetKind
> opt_set
= GetSetForNativeRegNum(reg
);
472 // This is likely an internal register for lldb use only and should not be
474 error
.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
479 RegSetKind set
= *opt_set
;
480 uint64_t new_xstate_bv
= 0;
482 error
= ReadRegisterSet(set
);
489 ::memcpy(GetOffsetRegSetData(set
, reg_info
->byte_offset
),
490 reg_value
.GetBytes(), reg_value
.GetByteSize());
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());
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
;
505 new_xstate_bv
|= XCR0_X87
;
509 std::optional
<YMMSplitPtr
> ymm_reg
= GetYMMSplitReg(reg
);
511 error
.SetErrorStringWithFormat(
512 "register \"%s\" not supported by CPU/kernel", reg_info
->name
);
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
;
522 llvm_unreachable("MPX regset should have returned error");
525 if (new_xstate_bv
!= 0)
526 reinterpret_cast<xstate
*>(m_xstate
.data())->xs_xstate_bv
|= new_xstate_bv
;
527 return WriteRegisterSet(set
);
530 Status
NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues(
531 lldb::WritableDataBufferSP
&data_sp
) {
534 data_sp
.reset(new DataBufferHeap(REG_CONTEXT_SIZE
, 0));
535 error
= ReadRegisterSet(GPRegSet
);
539 uint8_t *dst
= data_sp
->GetBytes();
540 ::memcpy(dst
, m_gpr
.data(), GetRegisterInfoInterface().GetGPRSize());
541 dst
+= GetRegisterInfoInterface().GetGPRSize();
546 Status
NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues(
547 const lldb::DataBufferSP
&data_sp
) {
551 error
.SetErrorStringWithFormat(
552 "NativeRegisterContextNetBSD_x86_64::%s invalid data_sp provided",
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());
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 "
573 ::memcpy(m_gpr
.data(), src
, GetRegisterInfoInterface().GetGPRSize());
575 error
= WriteRegisterSet(GPRegSet
);
578 src
+= GetRegisterInfoInterface().GetGPRSize();
583 llvm::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.
588 Status res
= r_source
.ReadRegister(GetDR(7), dr7
);
590 // copy dbregs only if any watchpoints were set
591 if ((dr7
.GetAsUInt64() & 0xFF) == 0)
592 return llvm::Error::success();
594 m_dbr
= r_source
.m_dbr
;
595 res
= WriteRegisterSet(DBRegSet
);
597 return res
.ToError();
601 NativeRegisterContextNetBSD_x86_64::GetOffsetRegSetData(RegSetKind set
,
609 base
= m_xstate
.data() + offsetof(xstate
, xs_fxsave
);
615 llvm_unreachable("GetRegSetData() is unsuitable for this regset.");
617 llvm_unreachable("MPX regset should have returned error");
619 assert(reg_offset
>= m_regset_offsets
[set
]);
620 return base
+ (reg_offset
- m_regset_offsets
[set
]);
623 std::optional
<NativeRegisterContextNetBSD_x86_64::YMMSplitPtr
>
624 NativeRegisterContextNetBSD_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
))
630 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
631 case llvm::Triple::x86
:
632 reg_index
= reg
- lldb_ymm0_i386
;
634 case llvm::Triple::x86_64
:
635 reg_index
= reg
- lldb_ymm0_x86_64
;
638 llvm_unreachable("Unhandled target architecture.");
641 return YMMSplitPtr
{&xst
->xs_fxsave
.fx_xmm
[reg_index
],
642 &xst
->xs_ymm_hi128
.xs_ymm
[reg_index
]};
645 #endif // defined(__x86_64__)