1 //===-- NativeRegisterContextNetBSD_x86_64.cpp ----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #if defined(__i386__) || defined(__x86_64__)
10 
11 #include "NativeRegisterContextNetBSD_x86_64.h"
12 
13 #include "lldb/Host/HostInfo.h"
14 #include "lldb/Utility/DataBufferHeap.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/RegisterValue.h"
17 #include "lldb/Utility/Status.h"
18 
19 #include "Plugins/Process/Utility/RegisterContextNetBSD_i386.h"
20 #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
21 
22 // clang-format off
23 #include <sys/types.h>
24 #include <sys/ptrace.h>
25 #include <sys/sysctl.h>
26 #include <sys/uio.h>
27 #include <x86/cpu.h>
28 #include <x86/cpu_extended_state.h>
29 #include <x86/specialreg.h>
30 #include <elf.h>
31 #include <err.h>
32 #include <stdint.h>
33 #include <stdlib.h>
34 // clang-format on
35 
36 using namespace lldb_private;
37 using namespace lldb_private::process_netbsd;
38 
39 // Private namespace.
40 
41 namespace {
42 // x86 64-bit general purpose registers.
43 static const uint32_t g_gpr_regnums_x86_64[] = {
44     lldb_rax_x86_64,    lldb_rbx_x86_64,    lldb_rcx_x86_64, lldb_rdx_x86_64,
45     lldb_rdi_x86_64,    lldb_rsi_x86_64,    lldb_rbp_x86_64, lldb_rsp_x86_64,
46     lldb_r8_x86_64,     lldb_r9_x86_64,     lldb_r10_x86_64, lldb_r11_x86_64,
47     lldb_r12_x86_64,    lldb_r13_x86_64,    lldb_r14_x86_64, lldb_r15_x86_64,
48     lldb_rip_x86_64,    lldb_rflags_x86_64, lldb_cs_x86_64,  lldb_fs_x86_64,
49     lldb_gs_x86_64,     lldb_ss_x86_64,     lldb_ds_x86_64,  lldb_es_x86_64,
50     lldb_eax_x86_64,    lldb_ebx_x86_64,    lldb_ecx_x86_64, lldb_edx_x86_64,
51     lldb_edi_x86_64,    lldb_esi_x86_64,    lldb_ebp_x86_64, lldb_esp_x86_64,
52     lldb_r8d_x86_64,  // Low 32 bits or r8
53     lldb_r9d_x86_64,  // Low 32 bits or r9
54     lldb_r10d_x86_64, // Low 32 bits or r10
55     lldb_r11d_x86_64, // Low 32 bits or r11
56     lldb_r12d_x86_64, // Low 32 bits or r12
57     lldb_r13d_x86_64, // Low 32 bits or r13
58     lldb_r14d_x86_64, // Low 32 bits or r14
59     lldb_r15d_x86_64, // Low 32 bits or r15
60     lldb_ax_x86_64,     lldb_bx_x86_64,     lldb_cx_x86_64,  lldb_dx_x86_64,
61     lldb_di_x86_64,     lldb_si_x86_64,     lldb_bp_x86_64,  lldb_sp_x86_64,
62     lldb_r8w_x86_64,  // Low 16 bits or r8
63     lldb_r9w_x86_64,  // Low 16 bits or r9
64     lldb_r10w_x86_64, // Low 16 bits or r10
65     lldb_r11w_x86_64, // Low 16 bits or r11
66     lldb_r12w_x86_64, // Low 16 bits or r12
67     lldb_r13w_x86_64, // Low 16 bits or r13
68     lldb_r14w_x86_64, // Low 16 bits or r14
69     lldb_r15w_x86_64, // Low 16 bits or r15
70     lldb_ah_x86_64,     lldb_bh_x86_64,     lldb_ch_x86_64,  lldb_dh_x86_64,
71     lldb_al_x86_64,     lldb_bl_x86_64,     lldb_cl_x86_64,  lldb_dl_x86_64,
72     lldb_dil_x86_64,    lldb_sil_x86_64,    lldb_bpl_x86_64, lldb_spl_x86_64,
73     lldb_r8l_x86_64,    // Low 8 bits or r8
74     lldb_r9l_x86_64,    // Low 8 bits or r9
75     lldb_r10l_x86_64,   // Low 8 bits or r10
76     lldb_r11l_x86_64,   // Low 8 bits or r11
77     lldb_r12l_x86_64,   // Low 8 bits or r12
78     lldb_r13l_x86_64,   // Low 8 bits or r13
79     lldb_r14l_x86_64,   // Low 8 bits or r14
80     lldb_r15l_x86_64,   // Low 8 bits or r15
81     LLDB_INVALID_REGNUM // register sets need to end with this flag
82 };
83 static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
84                       1 ==
85                   k_num_gpr_registers_x86_64,
86               "g_gpr_regnums_x86_64 has wrong number of register infos");
87 
88 // x86 64-bit floating point registers.
89 static const uint32_t g_fpu_regnums_x86_64[] = {
90     lldb_fctrl_x86_64,     lldb_fstat_x86_64, lldb_ftag_x86_64,
91     lldb_fop_x86_64,       lldb_fiseg_x86_64, lldb_fioff_x86_64,
92     lldb_foseg_x86_64,     lldb_fooff_x86_64, lldb_mxcsr_x86_64,
93     lldb_mxcsrmask_x86_64, lldb_st0_x86_64,   lldb_st1_x86_64,
94     lldb_st2_x86_64,       lldb_st3_x86_64,   lldb_st4_x86_64,
95     lldb_st5_x86_64,       lldb_st6_x86_64,   lldb_st7_x86_64,
96     lldb_mm0_x86_64,       lldb_mm1_x86_64,   lldb_mm2_x86_64,
97     lldb_mm3_x86_64,       lldb_mm4_x86_64,   lldb_mm5_x86_64,
98     lldb_mm6_x86_64,       lldb_mm7_x86_64,   lldb_xmm0_x86_64,
99     lldb_xmm1_x86_64,      lldb_xmm2_x86_64,  lldb_xmm3_x86_64,
100     lldb_xmm4_x86_64,      lldb_xmm5_x86_64,  lldb_xmm6_x86_64,
101     lldb_xmm7_x86_64,      lldb_xmm8_x86_64,  lldb_xmm9_x86_64,
102     lldb_xmm10_x86_64,     lldb_xmm11_x86_64, lldb_xmm12_x86_64,
103     lldb_xmm13_x86_64,     lldb_xmm14_x86_64, lldb_xmm15_x86_64,
104     LLDB_INVALID_REGNUM // register sets need to end with this flag
105 };
106 static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
107                       1 ==
108                   k_num_fpr_registers_x86_64,
109               "g_fpu_regnums_x86_64 has wrong number of register infos");
110 
111 // x86 64-bit registers available via XState.
112 static const uint32_t g_xstate_regnums_x86_64[] = {
113     lldb_ymm0_x86_64,   lldb_ymm1_x86_64,  lldb_ymm2_x86_64,  lldb_ymm3_x86_64,
114     lldb_ymm4_x86_64,   lldb_ymm5_x86_64,  lldb_ymm6_x86_64,  lldb_ymm7_x86_64,
115     lldb_ymm8_x86_64,   lldb_ymm9_x86_64,  lldb_ymm10_x86_64, lldb_ymm11_x86_64,
116     lldb_ymm12_x86_64,  lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64,
117     // Note: we currently do not provide them but this is needed to avoid
118     // unnamed groups in SBFrame::GetRegisterContext().
119     lldb_bnd0_x86_64,    lldb_bnd1_x86_64,    lldb_bnd2_x86_64,
120     lldb_bnd3_x86_64,    lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64,
121     LLDB_INVALID_REGNUM // register sets need to end with this flag
122 };
123 static_assert((sizeof(g_xstate_regnums_x86_64) / sizeof(g_xstate_regnums_x86_64[0])) -
124                       1 ==
125                   k_num_avx_registers_x86_64 + k_num_mpx_registers_x86_64,
126               "g_xstate_regnums_x86_64 has wrong number of register infos");
127 
128 // x86 debug registers.
129 static const uint32_t g_dbr_regnums_x86_64[] = {
130     lldb_dr0_x86_64,   lldb_dr1_x86_64,  lldb_dr2_x86_64,  lldb_dr3_x86_64,
131     lldb_dr4_x86_64,   lldb_dr5_x86_64,  lldb_dr6_x86_64,  lldb_dr7_x86_64,
132     LLDB_INVALID_REGNUM // register sets need to end with this flag
133 };
134 static_assert((sizeof(g_dbr_regnums_x86_64) / sizeof(g_dbr_regnums_x86_64[0])) -
135                       1 ==
136                   k_num_dbr_registers_x86_64,
137               "g_dbr_regnums_x86_64 has wrong number of register infos");
138 
139 // x86 32-bit general purpose registers.
140 const uint32_t g_gpr_regnums_i386[] = {
141     lldb_eax_i386,      lldb_ebx_i386,    lldb_ecx_i386, lldb_edx_i386,
142     lldb_edi_i386,      lldb_esi_i386,    lldb_ebp_i386, lldb_esp_i386,
143     lldb_eip_i386,      lldb_eflags_i386, lldb_cs_i386,  lldb_fs_i386,
144     lldb_gs_i386,       lldb_ss_i386,     lldb_ds_i386,  lldb_es_i386,
145     lldb_ax_i386,       lldb_bx_i386,     lldb_cx_i386,  lldb_dx_i386,
146     lldb_di_i386,       lldb_si_i386,     lldb_bp_i386,  lldb_sp_i386,
147     lldb_ah_i386,       lldb_bh_i386,     lldb_ch_i386,  lldb_dh_i386,
148     lldb_al_i386,       lldb_bl_i386,     lldb_cl_i386,  lldb_dl_i386,
149     LLDB_INVALID_REGNUM // register sets need to end with this flag
150 };
151 static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) -
152                       1 ==
153                   k_num_gpr_registers_i386,
154               "g_gpr_regnums_i386 has wrong number of register infos");
155 
156 // x86 32-bit floating point registers.
157 const uint32_t g_fpu_regnums_i386[] = {
158     lldb_fctrl_i386,    lldb_fstat_i386,     lldb_ftag_i386,  lldb_fop_i386,
159     lldb_fiseg_i386,    lldb_fioff_i386,     lldb_foseg_i386, lldb_fooff_i386,
160     lldb_mxcsr_i386,    lldb_mxcsrmask_i386, lldb_st0_i386,   lldb_st1_i386,
161     lldb_st2_i386,      lldb_st3_i386,       lldb_st4_i386,   lldb_st5_i386,
162     lldb_st6_i386,      lldb_st7_i386,       lldb_mm0_i386,   lldb_mm1_i386,
163     lldb_mm2_i386,      lldb_mm3_i386,       lldb_mm4_i386,   lldb_mm5_i386,
164     lldb_mm6_i386,      lldb_mm7_i386,       lldb_xmm0_i386,  lldb_xmm1_i386,
165     lldb_xmm2_i386,     lldb_xmm3_i386,      lldb_xmm4_i386,  lldb_xmm5_i386,
166     lldb_xmm6_i386,     lldb_xmm7_i386,
167     LLDB_INVALID_REGNUM // register sets need to end with this flag
168 };
169 static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) -
170                       1 ==
171                   k_num_fpr_registers_i386,
172               "g_fpu_regnums_i386 has wrong number of register infos");
173 
174 // x86 64-bit registers available via XState.
175 static const uint32_t g_xstate_regnums_i386[] = {
176     lldb_ymm0_i386,     lldb_ymm1_i386,  lldb_ymm2_i386,  lldb_ymm3_i386,
177     lldb_ymm4_i386,     lldb_ymm5_i386,  lldb_ymm6_i386,  lldb_ymm7_i386,
178     // Note: we currently do not provide them but this is needed to avoid
179     // unnamed groups in SBFrame::GetRegisterContext().
180     lldb_bnd0_i386,      lldb_bnd1_i386,    lldb_bnd2_i386,
181     lldb_bnd3_i386,      lldb_bndcfgu_i386, lldb_bndstatus_i386,
182     LLDB_INVALID_REGNUM // register sets need to end with this flag
183 };
184 static_assert((sizeof(g_xstate_regnums_i386) / sizeof(g_xstate_regnums_i386[0])) -
185                       1 ==
186                   k_num_avx_registers_i386 + k_num_mpx_registers_i386,
187               "g_xstate_regnums_i386 has wrong number of register infos");
188 
189 // x86 debug registers.
190 static const uint32_t g_dbr_regnums_i386[] = {
191     lldb_dr0_i386,   lldb_dr1_i386,  lldb_dr2_i386,  lldb_dr3_i386,
192     lldb_dr4_i386,   lldb_dr5_i386,  lldb_dr6_i386,  lldb_dr7_i386,
193     LLDB_INVALID_REGNUM // register sets need to end with this flag
194 };
195 static_assert((sizeof(g_dbr_regnums_i386) / sizeof(g_dbr_regnums_i386[0])) -
196                       1 ==
197                   k_num_dbr_registers_i386,
198               "g_dbr_regnums_i386 has wrong number of register infos");
199 
200 
201 // Number of register sets provided by this context.
202 enum { k_num_register_sets = 4 };
203 
204 // Register sets for x86 32-bit.
205 static const RegisterSet g_reg_sets_i386[k_num_register_sets] = {
206     {"General Purpose Registers", "gpr", k_num_gpr_registers_i386,
207      g_gpr_regnums_i386},
208     {"Floating Point Registers", "fpu", k_num_fpr_registers_i386,
209      g_fpu_regnums_i386},
210     {"Extended State Registers", "xstate",
211      k_num_avx_registers_i386 + k_num_mpx_registers_i386,
212      g_xstate_regnums_i386},
213     {"Debug Registers", "dbr", k_num_dbr_registers_i386,
214      g_dbr_regnums_i386},
215 };
216 
217 // Register sets for x86 64-bit.
218 static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
219     {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64,
220      g_gpr_regnums_x86_64},
221     {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64,
222      g_fpu_regnums_x86_64},
223     {"Extended State Registers", "xstate",
224      k_num_avx_registers_x86_64 + k_num_mpx_registers_x86_64,
225      g_xstate_regnums_x86_64},
226     {"Debug Registers", "dbr", k_num_dbr_registers_x86_64,
227      g_dbr_regnums_x86_64},
228 };
229 
230 #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize())
231 } // namespace
232 
233 NativeRegisterContextNetBSD *
234 NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(
235     const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
236   return new NativeRegisterContextNetBSD_x86_64(target_arch, native_thread);
237 }
238 
239 // NativeRegisterContextNetBSD_x86_64 members.
240 
241 static RegisterInfoInterface *
242 CreateRegisterInfoInterface(const ArchSpec &target_arch) {
243   if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
244     // 32-bit hosts run with a RegisterContextNetBSD_i386 context.
245     return new RegisterContextNetBSD_i386(target_arch);
246   } else {
247     assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
248            "Register setting path assumes this is a 64-bit host");
249     // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64
250     // register context.
251     return new RegisterContextNetBSD_x86_64(target_arch);
252   }
253 }
254 
255 NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64(
256     const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
257     : NativeRegisterContextNetBSD(native_thread,
258                                   CreateRegisterInfoInterface(target_arch)),
259       m_gpr(), m_fpr(), m_dbr() {}
260 
261 // CONSIDER after local and llgs debugging are merged, register set support can
262 // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual.
263 uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetCount() const {
264   uint32_t sets = 0;
265   for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
266     if (GetSetForNativeRegNum(set_index) != -1)
267       ++sets;
268   }
269 
270   return sets;
271 }
272 
273 const RegisterSet *
274 NativeRegisterContextNetBSD_x86_64::GetRegisterSet(uint32_t set_index) const {
275   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
276   case llvm::Triple::x86:
277     return &g_reg_sets_i386[set_index];
278   case llvm::Triple::x86_64:
279     return &g_reg_sets_x86_64[set_index];
280   default:
281     assert(false && "Unhandled target architecture.");
282     return nullptr;
283   }
284 
285   return nullptr;
286 }
287 
288 static constexpr int RegNumX86ToX86_64(int regnum) {
289   switch (regnum) {
290   case lldb_eax_i386:
291     return lldb_rax_x86_64;
292   case lldb_ebx_i386:
293     return lldb_rbx_x86_64;
294   case lldb_ecx_i386:
295     return lldb_rcx_x86_64;
296   case lldb_edx_i386:
297     return lldb_rdx_x86_64;
298   case lldb_edi_i386:
299     return lldb_rdi_x86_64;
300   case lldb_esi_i386:
301     return lldb_rsi_x86_64;
302   case lldb_ebp_i386:
303     return lldb_rbp_x86_64;
304   case lldb_esp_i386:
305     return lldb_rsp_x86_64;
306   case lldb_eip_i386:
307     return lldb_rip_x86_64;
308   case lldb_eflags_i386:
309     return lldb_rflags_x86_64;
310   case lldb_cs_i386:
311     return lldb_cs_x86_64;
312   case lldb_fs_i386:
313     return lldb_fs_x86_64;
314   case lldb_gs_i386:
315     return lldb_gs_x86_64;
316   case lldb_ss_i386:
317     return lldb_ss_x86_64;
318   case lldb_ds_i386:
319     return lldb_ds_x86_64;
320   case lldb_es_i386:
321     return lldb_es_x86_64;
322   case lldb_fctrl_i386:
323     return lldb_fctrl_x86_64;
324   case lldb_fstat_i386:
325     return lldb_fstat_x86_64;
326   case lldb_ftag_i386:
327     return lldb_fstat_x86_64;
328   case lldb_fop_i386:
329     return lldb_fop_x86_64;
330   case lldb_fiseg_i386:
331     return lldb_fiseg_x86_64;
332   case lldb_fioff_i386:
333     return lldb_fioff_x86_64;
334   case lldb_foseg_i386:
335     return lldb_foseg_x86_64;
336   case lldb_fooff_i386:
337     return lldb_fooff_x86_64;
338   case lldb_mxcsr_i386:
339     return lldb_mxcsr_x86_64;
340   case lldb_mxcsrmask_i386:
341     return lldb_mxcsrmask_x86_64;
342   case lldb_st0_i386:
343   case lldb_st1_i386:
344   case lldb_st2_i386:
345   case lldb_st3_i386:
346   case lldb_st4_i386:
347   case lldb_st5_i386:
348   case lldb_st6_i386:
349   case lldb_st7_i386:
350     return lldb_st0_x86_64 + regnum - lldb_st0_i386;
351   case lldb_mm0_i386:
352   case lldb_mm1_i386:
353   case lldb_mm2_i386:
354   case lldb_mm3_i386:
355   case lldb_mm4_i386:
356   case lldb_mm5_i386:
357   case lldb_mm6_i386:
358   case lldb_mm7_i386:
359     return lldb_mm0_x86_64 + regnum - lldb_mm0_i386;
360   case lldb_xmm0_i386:
361   case lldb_xmm1_i386:
362   case lldb_xmm2_i386:
363   case lldb_xmm3_i386:
364   case lldb_xmm4_i386:
365   case lldb_xmm5_i386:
366   case lldb_xmm6_i386:
367   case lldb_xmm7_i386:
368     return lldb_xmm0_x86_64 + regnum - lldb_xmm0_i386;
369   case lldb_ymm0_i386:
370   case lldb_ymm1_i386:
371   case lldb_ymm2_i386:
372   case lldb_ymm3_i386:
373   case lldb_ymm4_i386:
374   case lldb_ymm5_i386:
375   case lldb_ymm6_i386:
376   case lldb_ymm7_i386:
377     return lldb_ymm0_x86_64 + regnum - lldb_ymm0_i386;
378   case lldb_dr0_i386:
379   case lldb_dr1_i386:
380   case lldb_dr2_i386:
381   case lldb_dr3_i386:
382   case lldb_dr4_i386:
383   case lldb_dr5_i386:
384   case lldb_dr6_i386:
385   case lldb_dr7_i386:
386     return lldb_dr0_x86_64 + regnum - lldb_dr0_i386;
387   default:
388     assert(false && "Unhandled i386 register.");
389     return 0;
390   }
391 }
392 
393 int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum(
394     int reg_num) const {
395   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
396   case llvm::Triple::x86:
397     if (reg_num <= k_last_gpr_i386)
398       return GPRegSet;
399     else if (reg_num <= k_last_fpr_i386)
400       return FPRegSet;
401     else if (reg_num <= k_last_avx_i386)
402       return XStateRegSet; // AVX
403     else if (reg_num <= lldb_dr7_i386)
404       return DBRegSet; // DBR
405     else
406       return -1;
407   case llvm::Triple::x86_64:
408     if (reg_num <= k_last_gpr_x86_64)
409       return GPRegSet;
410     else if (reg_num <= k_last_fpr_x86_64)
411       return FPRegSet;
412     else if (reg_num <= k_last_avx_x86_64)
413       return XStateRegSet; // AVX
414     else if (reg_num <= k_last_mpxr_x86_64)
415       return -1; // MPXR
416     else if (reg_num <= k_last_mpxc_x86_64)
417       return -1; // MPXC
418     else if (reg_num <= lldb_dr7_x86_64)
419       return DBRegSet; // DBR
420     else
421       return -1;
422   default:
423     assert(false && "Unhandled target architecture.");
424     return -1;
425   }
426 }
427 
428 Status NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) {
429   switch (set) {
430   case GPRegSet:
431     return DoRegisterSet(PT_GETREGS, &m_gpr);
432   case FPRegSet:
433 #if defined(__x86_64__)
434     return DoRegisterSet(PT_GETFPREGS, &m_fpr);
435 #else
436     return DoRegisterSet(PT_GETXMMREGS, &m_fpr);
437 #endif
438   case DBRegSet:
439     return DoRegisterSet(PT_GETDBREGS, &m_dbr);
440   case XStateRegSet:
441 #ifdef HAVE_XSTATE
442     {
443       struct iovec iov = {&m_xstate, sizeof(m_xstate)};
444       return DoRegisterSet(PT_GETXSTATE, &iov);
445     }
446 #else
447     return Status("XState is not supported by the kernel");
448 #endif
449   }
450   llvm_unreachable("NativeRegisterContextNetBSD_x86_64::ReadRegisterSet");
451 }
452 
453 Status NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(uint32_t set) {
454   switch (set) {
455   case GPRegSet:
456     return DoRegisterSet(PT_SETREGS, &m_gpr);
457   case FPRegSet:
458 #if defined(__x86_64__)
459     return DoRegisterSet(PT_SETFPREGS, &m_fpr);
460 #else
461     return DoRegisterSet(PT_SETXMMREGS, &m_fpr);
462 #endif
463   case DBRegSet:
464     return DoRegisterSet(PT_SETDBREGS, &m_dbr);
465   case XStateRegSet:
466 #ifdef HAVE_XSTATE
467     {
468       struct iovec iov = {&m_xstate, sizeof(m_xstate)};
469       return DoRegisterSet(PT_SETXSTATE, &iov);
470     }
471 #else
472     return Status("XState is not supported by the kernel");
473 #endif
474   }
475   llvm_unreachable("NativeRegisterContextNetBSD_x86_64::WriteRegisterSet");
476 }
477 
478 Status
479 NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info,
480                                                  RegisterValue &reg_value) {
481   Status error;
482 
483   if (!reg_info) {
484     error.SetErrorString("reg_info NULL");
485     return error;
486   }
487 
488   uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
489   if (reg == LLDB_INVALID_REGNUM) {
490     // This is likely an internal register for lldb use only and should not be
491     // directly queried.
492     error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
493                                    "register, cannot read directly",
494                                    reg_info->name);
495     return error;
496   }
497 
498   int set = GetSetForNativeRegNum(reg);
499   if (set == -1) {
500     // This is likely an internal register for lldb use only and should not be
501     // directly queried.
502     error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
503                                    reg_info->name);
504     return error;
505   }
506 
507   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
508   case llvm::Triple::x86_64:
509     break;
510   case llvm::Triple::x86:
511     reg = RegNumX86ToX86_64(reg);
512     break;
513   default:
514     assert(false && "Unhandled target architecture.");
515     error.SetErrorString("Unhandled target architecture.");
516     return error;
517   }
518 
519   error = ReadRegisterSet(set);
520   if (error.Fail())
521     return error;
522 
523   switch (reg) {
524 #if defined(__x86_64__)
525   case lldb_rax_x86_64:
526     reg_value = (uint64_t)m_gpr.regs[_REG_RAX];
527     break;
528   case lldb_rbx_x86_64:
529     reg_value = (uint64_t)m_gpr.regs[_REG_RBX];
530     break;
531   case lldb_rcx_x86_64:
532     reg_value = (uint64_t)m_gpr.regs[_REG_RCX];
533     break;
534   case lldb_rdx_x86_64:
535     reg_value = (uint64_t)m_gpr.regs[_REG_RDX];
536     break;
537   case lldb_rdi_x86_64:
538     reg_value = (uint64_t)m_gpr.regs[_REG_RDI];
539     break;
540   case lldb_rsi_x86_64:
541     reg_value = (uint64_t)m_gpr.regs[_REG_RSI];
542     break;
543   case lldb_rbp_x86_64:
544     reg_value = (uint64_t)m_gpr.regs[_REG_RBP];
545     break;
546   case lldb_rsp_x86_64:
547     reg_value = (uint64_t)m_gpr.regs[_REG_RSP];
548     break;
549   case lldb_r8_x86_64:
550     reg_value = (uint64_t)m_gpr.regs[_REG_R8];
551     break;
552   case lldb_r9_x86_64:
553     reg_value = (uint64_t)m_gpr.regs[_REG_R9];
554     break;
555   case lldb_r10_x86_64:
556     reg_value = (uint64_t)m_gpr.regs[_REG_R10];
557     break;
558   case lldb_r11_x86_64:
559     reg_value = (uint64_t)m_gpr.regs[_REG_R11];
560     break;
561   case lldb_r12_x86_64:
562     reg_value = (uint64_t)m_gpr.regs[_REG_R12];
563     break;
564   case lldb_r13_x86_64:
565     reg_value = (uint64_t)m_gpr.regs[_REG_R13];
566     break;
567   case lldb_r14_x86_64:
568     reg_value = (uint64_t)m_gpr.regs[_REG_R14];
569     break;
570   case lldb_r15_x86_64:
571     reg_value = (uint64_t)m_gpr.regs[_REG_R15];
572     break;
573   case lldb_rip_x86_64:
574     reg_value = (uint64_t)m_gpr.regs[_REG_RIP];
575     break;
576   case lldb_rflags_x86_64:
577     reg_value = (uint64_t)m_gpr.regs[_REG_RFLAGS];
578     break;
579   case lldb_cs_x86_64:
580     reg_value = (uint64_t)m_gpr.regs[_REG_CS];
581     break;
582   case lldb_fs_x86_64:
583     reg_value = (uint64_t)m_gpr.regs[_REG_FS];
584     break;
585   case lldb_gs_x86_64:
586     reg_value = (uint64_t)m_gpr.regs[_REG_GS];
587     break;
588   case lldb_ss_x86_64:
589     reg_value = (uint64_t)m_gpr.regs[_REG_SS];
590     break;
591   case lldb_ds_x86_64:
592     reg_value = (uint64_t)m_gpr.regs[_REG_DS];
593     break;
594   case lldb_es_x86_64:
595     reg_value = (uint64_t)m_gpr.regs[_REG_ES];
596     break;
597 #else
598   case lldb_rax_x86_64:
599     reg_value = (uint32_t)m_gpr.r_eax;
600     break;
601   case lldb_rbx_x86_64:
602     reg_value = (uint32_t)m_gpr.r_ebx;
603     break;
604   case lldb_rcx_x86_64:
605     reg_value = (uint32_t)m_gpr.r_ecx;
606     break;
607   case lldb_rdx_x86_64:
608     reg_value = (uint32_t)m_gpr.r_edx;
609     break;
610   case lldb_rdi_x86_64:
611     reg_value = (uint32_t)m_gpr.r_edi;
612     break;
613   case lldb_rsi_x86_64:
614     reg_value = (uint32_t)m_gpr.r_esi;
615     break;
616   case lldb_rsp_x86_64:
617     reg_value = (uint32_t)m_gpr.r_esp;
618     break;
619   case lldb_rbp_x86_64:
620     reg_value = (uint32_t)m_gpr.r_ebp;
621     break;
622   case lldb_rip_x86_64:
623     reg_value = (uint32_t)m_gpr.r_eip;
624     break;
625   case lldb_rflags_x86_64:
626     reg_value = (uint32_t)m_gpr.r_eflags;
627     break;
628   case lldb_cs_x86_64:
629     reg_value = (uint32_t)m_gpr.r_cs;
630     break;
631   case lldb_fs_x86_64:
632     reg_value = (uint32_t)m_gpr.r_fs;
633     break;
634   case lldb_gs_x86_64:
635     reg_value = (uint32_t)m_gpr.r_gs;
636     break;
637   case lldb_ss_x86_64:
638     reg_value = (uint32_t)m_gpr.r_ss;
639     break;
640   case lldb_ds_x86_64:
641     reg_value = (uint32_t)m_gpr.r_ds;
642     break;
643   case lldb_es_x86_64:
644     reg_value = (uint32_t)m_gpr.r_es;
645     break;
646 #endif
647   case lldb_fctrl_x86_64:
648     reg_value = (uint16_t)m_fpr.fxstate.fx_cw;
649     break;
650   case lldb_fstat_x86_64:
651     reg_value = (uint16_t)m_fpr.fxstate.fx_sw;
652     break;
653   case lldb_ftag_x86_64:
654     reg_value = (uint8_t)m_fpr.fxstate.fx_tw;
655     break;
656   case lldb_fop_x86_64:
657     reg_value = (uint64_t)m_fpr.fxstate.fx_opcode;
658     break;
659   case lldb_fiseg_x86_64:
660     reg_value = (uint64_t)m_fpr.fxstate.fx_ip.fa_64;
661     break;
662   case lldb_fioff_x86_64:
663     reg_value = (uint32_t)m_fpr.fxstate.fx_ip.fa_32.fa_off;
664     break;
665   case lldb_foseg_x86_64:
666     reg_value = (uint64_t)m_fpr.fxstate.fx_dp.fa_64;
667     break;
668   case lldb_fooff_x86_64:
669     reg_value = (uint32_t)m_fpr.fxstate.fx_dp.fa_32.fa_off;
670     break;
671   case lldb_mxcsr_x86_64:
672     reg_value = (uint32_t)m_fpr.fxstate.fx_mxcsr;
673     break;
674   case lldb_mxcsrmask_x86_64:
675     reg_value = (uint32_t)m_fpr.fxstate.fx_mxcsr_mask;
676     break;
677   case lldb_st0_x86_64:
678   case lldb_st1_x86_64:
679   case lldb_st2_x86_64:
680   case lldb_st3_x86_64:
681   case lldb_st4_x86_64:
682   case lldb_st5_x86_64:
683   case lldb_st6_x86_64:
684   case lldb_st7_x86_64:
685     reg_value.SetBytes(&m_fpr.fxstate.fx_87_ac[reg - lldb_st0_x86_64],
686                        reg_info->byte_size, endian::InlHostByteOrder());
687     break;
688   case lldb_mm0_x86_64:
689   case lldb_mm1_x86_64:
690   case lldb_mm2_x86_64:
691   case lldb_mm3_x86_64:
692   case lldb_mm4_x86_64:
693   case lldb_mm5_x86_64:
694   case lldb_mm6_x86_64:
695   case lldb_mm7_x86_64:
696     reg_value.SetBytes(&m_fpr.fxstate.fx_87_ac[reg - lldb_mm0_x86_64],
697                        reg_info->byte_size, endian::InlHostByteOrder());
698     break;
699   case lldb_xmm0_x86_64:
700   case lldb_xmm1_x86_64:
701   case lldb_xmm2_x86_64:
702   case lldb_xmm3_x86_64:
703   case lldb_xmm4_x86_64:
704   case lldb_xmm5_x86_64:
705   case lldb_xmm6_x86_64:
706   case lldb_xmm7_x86_64:
707   case lldb_xmm8_x86_64:
708   case lldb_xmm9_x86_64:
709   case lldb_xmm10_x86_64:
710   case lldb_xmm11_x86_64:
711   case lldb_xmm12_x86_64:
712   case lldb_xmm13_x86_64:
713   case lldb_xmm14_x86_64:
714   case lldb_xmm15_x86_64:
715     reg_value.SetBytes(&m_fpr.fxstate.fx_xmm[reg - lldb_xmm0_x86_64],
716                        reg_info->byte_size, endian::InlHostByteOrder());
717     break;
718   case lldb_ymm0_x86_64:
719   case lldb_ymm1_x86_64:
720   case lldb_ymm2_x86_64:
721   case lldb_ymm3_x86_64:
722   case lldb_ymm4_x86_64:
723   case lldb_ymm5_x86_64:
724   case lldb_ymm6_x86_64:
725   case lldb_ymm7_x86_64:
726   case lldb_ymm8_x86_64:
727   case lldb_ymm9_x86_64:
728   case lldb_ymm10_x86_64:
729   case lldb_ymm11_x86_64:
730   case lldb_ymm12_x86_64:
731   case lldb_ymm13_x86_64:
732   case lldb_ymm14_x86_64:
733   case lldb_ymm15_x86_64:
734 #ifdef HAVE_XSTATE
735     if (!(m_xstate.xs_rfbm & XCR0_SSE) ||
736         !(m_xstate.xs_rfbm & XCR0_YMM_Hi128)) {
737       error.SetErrorStringWithFormat("register \"%s\" not supported by CPU/kernel",
738                                      reg_info->name);
739     } else {
740       uint32_t reg_index = reg - lldb_ymm0_x86_64;
741       YMMReg ymm = XStateToYMM(
742           m_xstate.xs_fxsave.fx_xmm[reg_index].xmm_bytes,
743           m_xstate.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes);
744       reg_value.SetBytes(ymm.bytes, reg_info->byte_size,
745                          endian::InlHostByteOrder());
746     }
747 #else
748     error.SetErrorString("XState queries not supported by the kernel");
749 #endif
750     break;
751   case lldb_dr0_x86_64:
752   case lldb_dr1_x86_64:
753   case lldb_dr2_x86_64:
754   case lldb_dr3_x86_64:
755   case lldb_dr4_x86_64:
756   case lldb_dr5_x86_64:
757   case lldb_dr6_x86_64:
758   case lldb_dr7_x86_64:
759     reg_value = (uint64_t)m_dbr.dr[reg - lldb_dr0_x86_64];
760     break;
761   }
762 
763   return error;
764 }
765 
766 Status NativeRegisterContextNetBSD_x86_64::WriteRegister(
767     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
768 
769   Status error;
770 
771   if (!reg_info) {
772     error.SetErrorString("reg_info NULL");
773     return error;
774   }
775 
776   uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
777   if (reg == LLDB_INVALID_REGNUM) {
778     // This is likely an internal register for lldb use only and should not be
779     // directly queried.
780     error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
781                                    "register, cannot read directly",
782                                    reg_info->name);
783     return error;
784   }
785 
786   int set = GetSetForNativeRegNum(reg);
787   if (set == -1) {
788     // This is likely an internal register for lldb use only and should not be
789     // directly queried.
790     error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
791                                    reg_info->name);
792     return error;
793   }
794 
795   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
796   case llvm::Triple::x86_64:
797     break;
798   case llvm::Triple::x86:
799     reg = RegNumX86ToX86_64(reg);
800     break;
801   default:
802     assert(false && "Unhandled target architecture.");
803     error.SetErrorString("Unhandled target architecture.");
804     return error;
805   }
806 
807   error = ReadRegisterSet(set);
808   if (error.Fail())
809     return error;
810 
811   switch (reg) {
812 #if defined(__x86_64__)
813   case lldb_rax_x86_64:
814     m_gpr.regs[_REG_RAX] = reg_value.GetAsUInt64();
815     break;
816   case lldb_rbx_x86_64:
817     m_gpr.regs[_REG_RBX] = reg_value.GetAsUInt64();
818     break;
819   case lldb_rcx_x86_64:
820     m_gpr.regs[_REG_RCX] = reg_value.GetAsUInt64();
821     break;
822   case lldb_rdx_x86_64:
823     m_gpr.regs[_REG_RDX] = reg_value.GetAsUInt64();
824     break;
825   case lldb_rdi_x86_64:
826     m_gpr.regs[_REG_RDI] = reg_value.GetAsUInt64();
827     break;
828   case lldb_rsi_x86_64:
829     m_gpr.regs[_REG_RSI] = reg_value.GetAsUInt64();
830     break;
831   case lldb_rbp_x86_64:
832     m_gpr.regs[_REG_RBP] = reg_value.GetAsUInt64();
833     break;
834   case lldb_rsp_x86_64:
835     m_gpr.regs[_REG_RSP] = reg_value.GetAsUInt64();
836     break;
837   case lldb_r8_x86_64:
838     m_gpr.regs[_REG_R8] = reg_value.GetAsUInt64();
839     break;
840   case lldb_r9_x86_64:
841     m_gpr.regs[_REG_R9] = reg_value.GetAsUInt64();
842     break;
843   case lldb_r10_x86_64:
844     m_gpr.regs[_REG_R10] = reg_value.GetAsUInt64();
845     break;
846   case lldb_r11_x86_64:
847     m_gpr.regs[_REG_R11] = reg_value.GetAsUInt64();
848     break;
849   case lldb_r12_x86_64:
850     m_gpr.regs[_REG_R12] = reg_value.GetAsUInt64();
851     break;
852   case lldb_r13_x86_64:
853     m_gpr.regs[_REG_R13] = reg_value.GetAsUInt64();
854     break;
855   case lldb_r14_x86_64:
856     m_gpr.regs[_REG_R14] = reg_value.GetAsUInt64();
857     break;
858   case lldb_r15_x86_64:
859     m_gpr.regs[_REG_R15] = reg_value.GetAsUInt64();
860     break;
861   case lldb_rip_x86_64:
862     m_gpr.regs[_REG_RIP] = reg_value.GetAsUInt64();
863     break;
864   case lldb_rflags_x86_64:
865     m_gpr.regs[_REG_RFLAGS] = reg_value.GetAsUInt64();
866     break;
867   case lldb_cs_x86_64:
868     m_gpr.regs[_REG_CS] = reg_value.GetAsUInt64();
869     break;
870   case lldb_fs_x86_64:
871     m_gpr.regs[_REG_FS] = reg_value.GetAsUInt64();
872     break;
873   case lldb_gs_x86_64:
874     m_gpr.regs[_REG_GS] = reg_value.GetAsUInt64();
875     break;
876   case lldb_ss_x86_64:
877     m_gpr.regs[_REG_SS] = reg_value.GetAsUInt64();
878     break;
879   case lldb_ds_x86_64:
880     m_gpr.regs[_REG_DS] = reg_value.GetAsUInt64();
881     break;
882   case lldb_es_x86_64:
883     m_gpr.regs[_REG_ES] = reg_value.GetAsUInt64();
884     break;
885 #else
886   case lldb_rax_x86_64:
887     m_gpr.r_eax = reg_value.GetAsUInt32();
888     break;
889   case lldb_rbx_x86_64:
890     m_gpr.r_ebx = reg_value.GetAsUInt32();
891     break;
892   case lldb_rcx_x86_64:
893     m_gpr.r_ecx = reg_value.GetAsUInt32();
894     break;
895   case lldb_rdx_x86_64:
896     m_gpr.r_edx = reg_value.GetAsUInt32();
897     break;
898   case lldb_rdi_x86_64:
899     m_gpr.r_edi = reg_value.GetAsUInt32();
900     break;
901   case lldb_rsi_x86_64:
902     m_gpr.r_esi = reg_value.GetAsUInt32();
903     break;
904   case lldb_rsp_x86_64:
905     m_gpr.r_esp = reg_value.GetAsUInt32();
906     break;
907   case lldb_rbp_x86_64:
908     m_gpr.r_ebp = reg_value.GetAsUInt32();
909     break;
910   case lldb_rip_x86_64:
911     m_gpr.r_eip = reg_value.GetAsUInt32();
912     break;
913   case lldb_rflags_x86_64:
914     m_gpr.r_eflags = reg_value.GetAsUInt32();
915     break;
916   case lldb_cs_x86_64:
917     m_gpr.r_cs = reg_value.GetAsUInt32();
918     break;
919   case lldb_fs_x86_64:
920     m_gpr.r_fs = reg_value.GetAsUInt32();
921     break;
922   case lldb_gs_x86_64:
923     m_gpr.r_gs = reg_value.GetAsUInt32();
924     break;
925   case lldb_ss_x86_64:
926     m_gpr.r_ss = reg_value.GetAsUInt32();
927     break;
928   case lldb_ds_x86_64:
929     m_gpr.r_ds = reg_value.GetAsUInt32();
930     break;
931   case lldb_es_x86_64:
932     m_gpr.r_es = reg_value.GetAsUInt32();
933     break;
934 #endif
935   case lldb_fctrl_x86_64:
936     m_fpr.fxstate.fx_cw = reg_value.GetAsUInt16();
937     break;
938   case lldb_fstat_x86_64:
939     m_fpr.fxstate.fx_sw = reg_value.GetAsUInt16();
940     break;
941   case lldb_ftag_x86_64:
942     m_fpr.fxstate.fx_tw = reg_value.GetAsUInt8();
943     break;
944   case lldb_fop_x86_64:
945     m_fpr.fxstate.fx_opcode = reg_value.GetAsUInt16();
946     break;
947   case lldb_fiseg_x86_64:
948     m_fpr.fxstate.fx_ip.fa_64 = reg_value.GetAsUInt64();
949     break;
950   case lldb_fioff_x86_64:
951     m_fpr.fxstate.fx_ip.fa_32.fa_off = reg_value.GetAsUInt32();
952     break;
953   case lldb_foseg_x86_64:
954     m_fpr.fxstate.fx_dp.fa_64 = reg_value.GetAsUInt64();
955     break;
956   case lldb_fooff_x86_64:
957     m_fpr.fxstate.fx_dp.fa_32.fa_off = reg_value.GetAsUInt32();
958     break;
959   case lldb_mxcsr_x86_64:
960     m_fpr.fxstate.fx_mxcsr = reg_value.GetAsUInt32();
961     break;
962   case lldb_mxcsrmask_x86_64:
963     m_fpr.fxstate.fx_mxcsr_mask = reg_value.GetAsUInt32();
964     break;
965   case lldb_st0_x86_64:
966   case lldb_st1_x86_64:
967   case lldb_st2_x86_64:
968   case lldb_st3_x86_64:
969   case lldb_st4_x86_64:
970   case lldb_st5_x86_64:
971   case lldb_st6_x86_64:
972   case lldb_st7_x86_64:
973     ::memcpy(&m_fpr.fxstate.fx_87_ac[reg - lldb_st0_x86_64],
974              reg_value.GetBytes(), reg_value.GetByteSize());
975     break;
976   case lldb_mm0_x86_64:
977   case lldb_mm1_x86_64:
978   case lldb_mm2_x86_64:
979   case lldb_mm3_x86_64:
980   case lldb_mm4_x86_64:
981   case lldb_mm5_x86_64:
982   case lldb_mm6_x86_64:
983   case lldb_mm7_x86_64:
984     ::memcpy(&m_fpr.fxstate.fx_87_ac[reg - lldb_mm0_x86_64],
985              reg_value.GetBytes(), reg_value.GetByteSize());
986     break;
987   case lldb_xmm0_x86_64:
988   case lldb_xmm1_x86_64:
989   case lldb_xmm2_x86_64:
990   case lldb_xmm3_x86_64:
991   case lldb_xmm4_x86_64:
992   case lldb_xmm5_x86_64:
993   case lldb_xmm6_x86_64:
994   case lldb_xmm7_x86_64:
995   case lldb_xmm8_x86_64:
996   case lldb_xmm9_x86_64:
997   case lldb_xmm10_x86_64:
998   case lldb_xmm11_x86_64:
999   case lldb_xmm12_x86_64:
1000   case lldb_xmm13_x86_64:
1001   case lldb_xmm14_x86_64:
1002   case lldb_xmm15_x86_64:
1003     ::memcpy(&m_fpr.fxstate.fx_xmm[reg - lldb_xmm0_x86_64],
1004              reg_value.GetBytes(), reg_value.GetByteSize());
1005     break;
1006   case lldb_ymm0_x86_64:
1007   case lldb_ymm1_x86_64:
1008   case lldb_ymm2_x86_64:
1009   case lldb_ymm3_x86_64:
1010   case lldb_ymm4_x86_64:
1011   case lldb_ymm5_x86_64:
1012   case lldb_ymm6_x86_64:
1013   case lldb_ymm7_x86_64:
1014   case lldb_ymm8_x86_64:
1015   case lldb_ymm9_x86_64:
1016   case lldb_ymm10_x86_64:
1017   case lldb_ymm11_x86_64:
1018   case lldb_ymm12_x86_64:
1019   case lldb_ymm13_x86_64:
1020   case lldb_ymm14_x86_64:
1021   case lldb_ymm15_x86_64:
1022 #ifdef HAVE_XSTATE
1023     if (!(m_xstate.xs_rfbm & XCR0_SSE) ||
1024         !(m_xstate.xs_rfbm & XCR0_YMM_Hi128)) {
1025       error.SetErrorStringWithFormat("register \"%s\" not supported by CPU/kernel",
1026                                      reg_info->name);
1027     } else {
1028       uint32_t reg_index = reg - lldb_ymm0_x86_64;
1029       YMMReg ymm;
1030       ::memcpy(ymm.bytes, reg_value.GetBytes(), reg_value.GetByteSize());
1031       YMMToXState(ymm,
1032           m_xstate.xs_fxsave.fx_xmm[reg_index].xmm_bytes,
1033           m_xstate.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes);
1034     }
1035 #else
1036     error.SetErrorString("XState not supported by the kernel");
1037 #endif
1038     break;
1039   case lldb_dr0_x86_64:
1040   case lldb_dr1_x86_64:
1041   case lldb_dr2_x86_64:
1042   case lldb_dr3_x86_64:
1043   case lldb_dr4_x86_64:
1044   case lldb_dr5_x86_64:
1045   case lldb_dr6_x86_64:
1046   case lldb_dr7_x86_64:
1047     m_dbr.dr[reg - lldb_dr0_x86_64] = reg_value.GetAsUInt64();
1048     break;
1049   }
1050 
1051   return WriteRegisterSet(set);
1052 }
1053 
1054 Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues(
1055     lldb::DataBufferSP &data_sp) {
1056   Status error;
1057 
1058   data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
1059   error = ReadRegisterSet(GPRegSet);
1060   if (error.Fail())
1061     return error;
1062 
1063   uint8_t *dst = data_sp->GetBytes();
1064   ::memcpy(dst, &m_gpr, GetRegisterInfoInterface().GetGPRSize());
1065   dst += GetRegisterInfoInterface().GetGPRSize();
1066 
1067   return error;
1068 }
1069 
1070 Status NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues(
1071     const lldb::DataBufferSP &data_sp) {
1072   Status error;
1073 
1074   if (!data_sp) {
1075     error.SetErrorStringWithFormat(
1076         "NativeRegisterContextNetBSD_x86_64::%s invalid data_sp provided",
1077         __FUNCTION__);
1078     return error;
1079   }
1080 
1081   if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
1082     error.SetErrorStringWithFormat(
1083         "NativeRegisterContextNetBSD_x86_64::%s data_sp contained mismatched "
1084         "data size, expected %zu, actual %" PRIu64,
1085         __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
1086     return error;
1087   }
1088 
1089   uint8_t *src = data_sp->GetBytes();
1090   if (src == nullptr) {
1091     error.SetErrorStringWithFormat("NativeRegisterContextNetBSD_x86_64::%s "
1092                                    "DataBuffer::GetBytes() returned a null "
1093                                    "pointer",
1094                                    __FUNCTION__);
1095     return error;
1096   }
1097   ::memcpy(&m_gpr, src, GetRegisterInfoInterface().GetGPRSize());
1098 
1099   error = WriteRegisterSet(GPRegSet);
1100   if (error.Fail())
1101     return error;
1102   src += GetRegisterInfoInterface().GetGPRSize();
1103 
1104   return error;
1105 }
1106 
1107 int NativeRegisterContextNetBSD_x86_64::GetDR(int num) const {
1108   assert(num >= 0 && num <= 7);
1109   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
1110   case llvm::Triple::x86:
1111     return lldb_dr0_i386 + num;
1112   case llvm::Triple::x86_64:
1113     return lldb_dr0_x86_64 + num;
1114   default:
1115     return -1;
1116   }
1117 }
1118 
1119 Status NativeRegisterContextNetBSD_x86_64::IsWatchpointHit(uint32_t wp_index,
1120                                                            bool &is_hit) {
1121   if (wp_index >= NumSupportedHardwareWatchpoints())
1122     return Status("Watchpoint index out of range");
1123 
1124   RegisterValue reg_value;
1125   const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(GetDR(6));
1126   Status error = ReadRegister(reg_info, reg_value);
1127   if (error.Fail()) {
1128     is_hit = false;
1129     return error;
1130   }
1131 
1132   uint64_t status_bits = reg_value.GetAsUInt64();
1133 
1134   is_hit = status_bits & (1 << wp_index);
1135 
1136   return error;
1137 }
1138 
1139 Status NativeRegisterContextNetBSD_x86_64::GetWatchpointHitIndex(
1140     uint32_t &wp_index, lldb::addr_t trap_addr) {
1141   uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
1142   for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
1143     bool is_hit;
1144     Status error = IsWatchpointHit(wp_index, is_hit);
1145     if (error.Fail()) {
1146       wp_index = LLDB_INVALID_INDEX32;
1147       return error;
1148     } else if (is_hit) {
1149       return error;
1150     }
1151   }
1152   wp_index = LLDB_INVALID_INDEX32;
1153   return Status();
1154 }
1155 
1156 Status NativeRegisterContextNetBSD_x86_64::IsWatchpointVacant(uint32_t wp_index,
1157                                                               bool &is_vacant) {
1158   if (wp_index >= NumSupportedHardwareWatchpoints())
1159     return Status("Watchpoint index out of range");
1160 
1161   RegisterValue reg_value;
1162   const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(GetDR(7));
1163   Status error = ReadRegister(reg_info, reg_value);
1164   if (error.Fail()) {
1165     is_vacant = false;
1166     return error;
1167   }
1168 
1169   uint64_t control_bits = reg_value.GetAsUInt64();
1170 
1171   is_vacant = !(control_bits & (1 << (2 * wp_index + 1)));
1172 
1173   return error;
1174 }
1175 
1176 Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
1177     lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
1178 
1179   if (wp_index >= NumSupportedHardwareWatchpoints())
1180     return Status("Watchpoint index out of range");
1181 
1182   // Read only watchpoints aren't supported on x86_64. Fall back to read/write
1183   // waitchpoints instead.
1184   // TODO: Add logic to detect when a write happens and ignore that watchpoint
1185   // hit.
1186   if (watch_flags == 0x2)
1187     watch_flags = 0x3;
1188 
1189   if (watch_flags != 0x1 && watch_flags != 0x3)
1190     return Status("Invalid read/write bits for watchpoint");
1191 
1192   if (size != 1 && size != 2 && size != 4 && size != 8)
1193     return Status("Invalid size for watchpoint");
1194 
1195   bool is_vacant;
1196   Status error = IsWatchpointVacant(wp_index, is_vacant);
1197   if (error.Fail())
1198     return error;
1199   if (!is_vacant)
1200     return Status("Watchpoint index not vacant");
1201 
1202   const RegisterInfo *const reg_info_dr7 = GetRegisterInfoAtIndex(GetDR(7));
1203   RegisterValue dr7_value;
1204   error = ReadRegister(reg_info_dr7, dr7_value);
1205   if (error.Fail())
1206     return error;
1207 
1208   // for watchpoints 0, 1, 2, or 3, respectively, set bits 1, 3, 5, or 7
1209   uint64_t enable_bit = 1 << (2 * wp_index + 1);
1210 
1211   // set bits 16-17, 20-21, 24-25, or 28-29
1212   // with 0b01 for write, and 0b11 for read/write
1213   uint64_t rw_bits = watch_flags << (16 + 4 * wp_index);
1214 
1215   // set bits 18-19, 22-23, 26-27, or 30-31
1216   // with 0b00, 0b01, 0b10, or 0b11
1217   // for 1, 2, 8 (if supported), or 4 bytes, respectively
1218   uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
1219 
1220   uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
1221 
1222   uint64_t control_bits = dr7_value.GetAsUInt64() & ~bit_mask;
1223 
1224   control_bits |= enable_bit | rw_bits | size_bits;
1225 
1226   const RegisterInfo *const reg_info_drN =
1227       GetRegisterInfoAtIndex(GetDR(wp_index));
1228   RegisterValue drN_value;
1229   error = ReadRegister(reg_info_drN, drN_value);
1230   if (error.Fail())
1231     return error;
1232 
1233   // clear dr6 if address or bits changed (i.e. we're not reenabling the same
1234   // watchpoint)
1235   if (drN_value.GetAsUInt64() != addr ||
1236       (dr7_value.GetAsUInt64() & bit_mask) != (rw_bits | size_bits)) {
1237     ClearWatchpointHit(wp_index);
1238 
1239     error = WriteRegister(reg_info_drN, RegisterValue(addr));
1240     if (error.Fail())
1241       return error;
1242   }
1243 
1244   error = WriteRegister(reg_info_dr7, RegisterValue(control_bits));
1245   if (error.Fail())
1246     return error;
1247 
1248   error.Clear();
1249   return error;
1250 }
1251 
1252 bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint(
1253     uint32_t wp_index) {
1254   if (wp_index >= NumSupportedHardwareWatchpoints())
1255     return false;
1256 
1257   // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0-1, 2-3, 4-5
1258   // or 6-7 of the debug control register (DR7)
1259   const RegisterInfo *const reg_info_dr7 = GetRegisterInfoAtIndex(GetDR(7));
1260   RegisterValue reg_value;
1261   Status error = ReadRegister(reg_info_dr7, reg_value);
1262   if (error.Fail())
1263     return false;
1264   uint64_t bit_mask = 0x3 << (2 * wp_index);
1265   uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
1266 
1267   return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success();
1268 }
1269 
1270 Status NativeRegisterContextNetBSD_x86_64::ClearWatchpointHit(uint32_t wp_index) {
1271   if (wp_index >= NumSupportedHardwareWatchpoints())
1272     return Status("Watchpoint index out of range");
1273 
1274   // for watchpoints 0, 1, 2, or 3, respectively, check bits 0, 1, 2, or 3 of
1275   // the debug status register (DR6)
1276   const RegisterInfo *const reg_info_dr6 = GetRegisterInfoAtIndex(GetDR(6));
1277   RegisterValue reg_value;
1278   Status error = ReadRegister(reg_info_dr6, reg_value);
1279   if (error.Fail())
1280     return error;
1281 
1282   uint64_t bit_mask = 1 << wp_index;
1283   uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
1284   return WriteRegister(reg_info_dr6, RegisterValue(status_bits));
1285 }
1286 
1287 Status NativeRegisterContextNetBSD_x86_64::ClearAllHardwareWatchpoints() {
1288   RegisterValue reg_value;
1289 
1290   // clear bits {0-4} of the debug status register (DR6)
1291   const RegisterInfo *const reg_info_dr6 = GetRegisterInfoAtIndex(GetDR(6));
1292   Status error = ReadRegister(reg_info_dr6, reg_value);
1293   if (error.Fail())
1294     return error;
1295   uint64_t bit_mask = 0xF;
1296   uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
1297   error = WriteRegister(reg_info_dr6, RegisterValue(status_bits));
1298   if (error.Fail())
1299     return error;
1300 
1301   // clear bits {0-7,16-31} of the debug control register (DR7)
1302   const RegisterInfo *const reg_info_dr7 = GetRegisterInfoAtIndex(GetDR(7));
1303   error = ReadRegister(reg_info_dr7, reg_value);
1304   if (error.Fail())
1305     return error;
1306   bit_mask = 0xFF | (0xFFFF << 16);
1307   uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
1308   return WriteRegister(reg_info_dr7, RegisterValue(control_bits));
1309 }
1310 
1311 uint32_t NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpoint(
1312     lldb::addr_t addr, size_t size, uint32_t watch_flags) {
1313   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
1314   const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
1315   for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) {
1316     bool is_vacant;
1317     Status error = IsWatchpointVacant(wp_index, is_vacant);
1318     if (is_vacant) {
1319       error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index);
1320       if (error.Success())
1321         return wp_index;
1322     }
1323     if (error.Fail() && log) {
1324       LLDB_LOGF(log, "NativeRegisterContextNetBSD_x86_64::%s Error: %s",
1325                 __FUNCTION__, error.AsCString());
1326     }
1327   }
1328   return LLDB_INVALID_INDEX32;
1329 }
1330 
1331 lldb::addr_t
1332 NativeRegisterContextNetBSD_x86_64::GetWatchpointAddress(uint32_t wp_index) {
1333   if (wp_index >= NumSupportedHardwareWatchpoints())
1334     return LLDB_INVALID_ADDRESS;
1335   RegisterValue reg_value;
1336   const RegisterInfo *const reg_info_drN =
1337       GetRegisterInfoAtIndex(GetDR(wp_index));
1338   if (ReadRegister(reg_info_drN, reg_value).Fail())
1339     return LLDB_INVALID_ADDRESS;
1340   return reg_value.GetAsUInt64();
1341 }
1342 
1343 uint32_t NativeRegisterContextNetBSD_x86_64::NumSupportedHardwareWatchpoints() {
1344   // Available debug address registers: dr0, dr1, dr2, dr3
1345   return 4;
1346 }
1347 
1348 Status NativeRegisterContextNetBSD_x86_64::CopyHardwareWatchpointsFrom(
1349     NativeRegisterContextNetBSD &source) {
1350   auto &r_source = static_cast<NativeRegisterContextNetBSD_x86_64&>(source);
1351   Status res = r_source.ReadRegisterSet(DBRegSet);
1352   if (!res.Fail()) {
1353     // copy dbregs only if any watchpoints were set
1354     if ((r_source.m_dbr.dr[7] & 0xFF) == 0)
1355       return res;
1356 
1357     m_dbr = r_source.m_dbr;
1358     res = WriteRegisterSet(DBRegSet);
1359   }
1360   return res;
1361 }
1362 
1363 #endif // defined(__x86_64__)
1364