1 //===-- NativeRegisterContextNetBSD_x86_64.cpp ---------------*- C++ -*-===//
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(__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_x86_64.h"
20 
21 // clang-format off
22 #include <sys/types.h>
23 #include <sys/ptrace.h>
24 #include <sys/sysctl.h>
25 #include <sys/uio.h>
26 #include <x86/cpu.h>
27 #include <x86/cpu_extended_state.h>
28 #include <x86/specialreg.h>
29 #include <elf.h>
30 #include <err.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 // clang-format on
34 
35 using namespace lldb_private;
36 using namespace lldb_private::process_netbsd;
37 
38 // Private namespace.
39 
40 namespace {
41 // x86 64-bit general purpose registers.
42 static const uint32_t g_gpr_regnums_x86_64[] = {
43     lldb_rax_x86_64,    lldb_rbx_x86_64,    lldb_rcx_x86_64, lldb_rdx_x86_64,
44     lldb_rdi_x86_64,    lldb_rsi_x86_64,    lldb_rbp_x86_64, lldb_rsp_x86_64,
45     lldb_r8_x86_64,     lldb_r9_x86_64,     lldb_r10_x86_64, lldb_r11_x86_64,
46     lldb_r12_x86_64,    lldb_r13_x86_64,    lldb_r14_x86_64, lldb_r15_x86_64,
47     lldb_rip_x86_64,    lldb_rflags_x86_64, lldb_cs_x86_64,  lldb_fs_x86_64,
48     lldb_gs_x86_64,     lldb_ss_x86_64,     lldb_ds_x86_64,  lldb_es_x86_64,
49     lldb_eax_x86_64,    lldb_ebx_x86_64,    lldb_ecx_x86_64, lldb_edx_x86_64,
50     lldb_edi_x86_64,    lldb_esi_x86_64,    lldb_ebp_x86_64, lldb_esp_x86_64,
51     lldb_r8d_x86_64,  // Low 32 bits or r8
52     lldb_r9d_x86_64,  // Low 32 bits or r9
53     lldb_r10d_x86_64, // Low 32 bits or r10
54     lldb_r11d_x86_64, // Low 32 bits or r11
55     lldb_r12d_x86_64, // Low 32 bits or r12
56     lldb_r13d_x86_64, // Low 32 bits or r13
57     lldb_r14d_x86_64, // Low 32 bits or r14
58     lldb_r15d_x86_64, // Low 32 bits or r15
59     lldb_ax_x86_64,     lldb_bx_x86_64,     lldb_cx_x86_64,  lldb_dx_x86_64,
60     lldb_di_x86_64,     lldb_si_x86_64,     lldb_bp_x86_64,  lldb_sp_x86_64,
61     lldb_r8w_x86_64,  // Low 16 bits or r8
62     lldb_r9w_x86_64,  // Low 16 bits or r9
63     lldb_r10w_x86_64, // Low 16 bits or r10
64     lldb_r11w_x86_64, // Low 16 bits or r11
65     lldb_r12w_x86_64, // Low 16 bits or r12
66     lldb_r13w_x86_64, // Low 16 bits or r13
67     lldb_r14w_x86_64, // Low 16 bits or r14
68     lldb_r15w_x86_64, // Low 16 bits or r15
69     lldb_ah_x86_64,     lldb_bh_x86_64,     lldb_ch_x86_64,  lldb_dh_x86_64,
70     lldb_al_x86_64,     lldb_bl_x86_64,     lldb_cl_x86_64,  lldb_dl_x86_64,
71     lldb_dil_x86_64,    lldb_sil_x86_64,    lldb_bpl_x86_64, lldb_spl_x86_64,
72     lldb_r8l_x86_64,    // Low 8 bits or r8
73     lldb_r9l_x86_64,    // Low 8 bits or r9
74     lldb_r10l_x86_64,   // Low 8 bits or r10
75     lldb_r11l_x86_64,   // Low 8 bits or r11
76     lldb_r12l_x86_64,   // Low 8 bits or r12
77     lldb_r13l_x86_64,   // Low 8 bits or r13
78     lldb_r14l_x86_64,   // Low 8 bits or r14
79     lldb_r15l_x86_64,   // Low 8 bits or r15
80     LLDB_INVALID_REGNUM // register sets need to end with this flag
81 };
82 static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
83                       1 ==
84                   k_num_gpr_registers_x86_64,
85               "g_gpr_regnums_x86_64 has wrong number of register infos");
86 
87 // x86 64-bit floating point registers.
88 static const uint32_t g_fpu_regnums_x86_64[] = {
89     lldb_fctrl_x86_64,     lldb_fstat_x86_64, lldb_ftag_x86_64,
90     lldb_fop_x86_64,       lldb_fiseg_x86_64, lldb_fioff_x86_64,
91     lldb_foseg_x86_64,     lldb_fooff_x86_64, lldb_mxcsr_x86_64,
92     lldb_mxcsrmask_x86_64, lldb_st0_x86_64,   lldb_st1_x86_64,
93     lldb_st2_x86_64,       lldb_st3_x86_64,   lldb_st4_x86_64,
94     lldb_st5_x86_64,       lldb_st6_x86_64,   lldb_st7_x86_64,
95     lldb_mm0_x86_64,       lldb_mm1_x86_64,   lldb_mm2_x86_64,
96     lldb_mm3_x86_64,       lldb_mm4_x86_64,   lldb_mm5_x86_64,
97     lldb_mm6_x86_64,       lldb_mm7_x86_64,   lldb_xmm0_x86_64,
98     lldb_xmm1_x86_64,      lldb_xmm2_x86_64,  lldb_xmm3_x86_64,
99     lldb_xmm4_x86_64,      lldb_xmm5_x86_64,  lldb_xmm6_x86_64,
100     lldb_xmm7_x86_64,      lldb_xmm8_x86_64,  lldb_xmm9_x86_64,
101     lldb_xmm10_x86_64,     lldb_xmm11_x86_64, lldb_xmm12_x86_64,
102     lldb_xmm13_x86_64,     lldb_xmm14_x86_64, lldb_xmm15_x86_64,
103     LLDB_INVALID_REGNUM // register sets need to end with this flag
104 };
105 static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
106                       1 ==
107                   k_num_fpr_registers_x86_64,
108               "g_fpu_regnums_x86_64 has wrong number of register infos");
109 
110 // x86 64-bit registers available via XState.
111 static const uint32_t g_xstate_regnums_x86_64[] = {
112     lldb_ymm0_x86_64,   lldb_ymm1_x86_64,  lldb_ymm2_x86_64,  lldb_ymm3_x86_64,
113     lldb_ymm4_x86_64,   lldb_ymm5_x86_64,  lldb_ymm6_x86_64,  lldb_ymm7_x86_64,
114     lldb_ymm8_x86_64,   lldb_ymm9_x86_64,  lldb_ymm10_x86_64, lldb_ymm11_x86_64,
115     lldb_ymm12_x86_64,  lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64,
116     // Note: we currently do not provide them but this is needed to avoid
117     // unnamed groups in SBFrame::GetRegisterContext().
118     lldb_bnd0_x86_64,    lldb_bnd1_x86_64,    lldb_bnd2_x86_64,
119     lldb_bnd3_x86_64,    lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64,
120     LLDB_INVALID_REGNUM // register sets need to end with this flag
121 };
122 static_assert((sizeof(g_xstate_regnums_x86_64) / sizeof(g_xstate_regnums_x86_64[0])) -
123                       1 ==
124                   k_num_avx_registers_x86_64 + k_num_mpx_registers_x86_64,
125               "g_xstate_regnums_x86_64 has wrong number of register infos");
126 
127 // x86 debug registers.
128 static const uint32_t g_dbr_regnums_x86_64[] = {
129     lldb_dr0_x86_64,   lldb_dr1_x86_64,  lldb_dr2_x86_64,  lldb_dr3_x86_64,
130     lldb_dr4_x86_64,   lldb_dr5_x86_64,  lldb_dr6_x86_64,  lldb_dr7_x86_64,
131     LLDB_INVALID_REGNUM // register sets need to end with this flag
132 };
133 static_assert((sizeof(g_dbr_regnums_x86_64) / sizeof(g_dbr_regnums_x86_64[0])) -
134                       1 ==
135                   k_num_dbr_registers_x86_64,
136               "g_dbr_regnums_x86_64 has wrong number of register infos");
137 
138 // Number of register sets provided by this context.
139 enum { k_num_register_sets = 4 };
140 
141 // Register sets for x86 64-bit.
142 static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
143     {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64,
144      g_gpr_regnums_x86_64},
145     {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64,
146      g_fpu_regnums_x86_64},
147     {"Extended State Registers", "xstate",
148      k_num_avx_registers_x86_64 + k_num_mpx_registers_x86_64,
149      g_xstate_regnums_x86_64},
150     {"Debug Registers", "dbr", k_num_dbr_registers_x86_64,
151      g_dbr_regnums_x86_64},
152 };
153 
154 #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize())
155 } // namespace
156 
157 NativeRegisterContextNetBSD *
158 NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(
159     const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
160   return new NativeRegisterContextNetBSD_x86_64(target_arch, native_thread);
161 }
162 
163 // NativeRegisterContextNetBSD_x86_64 members.
164 
165 static RegisterInfoInterface *
166 CreateRegisterInfoInterface(const ArchSpec &target_arch) {
167   assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
168          "Register setting path assumes this is a 64-bit host");
169   // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64
170   // register context.
171   return new RegisterContextNetBSD_x86_64(target_arch);
172 }
173 
174 NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64(
175     const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
176     : NativeRegisterContextNetBSD(native_thread,
177                                   CreateRegisterInfoInterface(target_arch)),
178       m_gpr_x86_64(), m_fpr_x86_64(), m_dbr_x86_64() {}
179 
180 // CONSIDER after local and llgs debugging are merged, register set support can
181 // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual.
182 uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetCount() const {
183   uint32_t sets = 0;
184   for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
185     if (GetSetForNativeRegNum(set_index) != -1)
186       ++sets;
187   }
188 
189   return sets;
190 }
191 
192 const RegisterSet *
193 NativeRegisterContextNetBSD_x86_64::GetRegisterSet(uint32_t set_index) const {
194   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
195   case llvm::Triple::x86_64:
196     return &g_reg_sets_x86_64[set_index];
197   default:
198     assert(false && "Unhandled target architecture.");
199     return nullptr;
200   }
201 
202   return nullptr;
203 }
204 
205 int NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum(
206     int reg_num) const {
207   if (reg_num <= k_last_gpr_x86_64)
208     return GPRegSet;
209   else if (reg_num <= k_last_fpr_x86_64)
210     return FPRegSet;
211   else if (reg_num <= k_last_avx_x86_64)
212     return XStateRegSet; // AVX
213   else if (reg_num <= k_last_mpxr_x86_64)
214     return -1; // MPXR
215   else if (reg_num <= k_last_mpxc_x86_64)
216     return -1; // MPXC
217   else if (reg_num <= lldb_dr7_x86_64)
218     return DBRegSet; // DBR
219   else
220     return -1;
221 }
222 
223 Status NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(uint32_t set) {
224   switch (set) {
225   case GPRegSet:
226     return DoRegisterSet(PT_GETREGS, &m_gpr_x86_64);
227   case FPRegSet:
228     return DoRegisterSet(PT_GETFPREGS, &m_fpr_x86_64);
229   case DBRegSet:
230     return DoRegisterSet(PT_GETDBREGS, &m_dbr_x86_64);
231   case XStateRegSet:
232 #ifdef HAVE_XSTATE
233     {
234       struct iovec iov = {&m_xstate_x86_64, sizeof(m_xstate_x86_64)};
235       return DoRegisterSet(PT_GETXSTATE, &iov);
236     }
237 #else
238     return Status("XState is not supported by the kernel");
239 #endif
240   }
241   llvm_unreachable("NativeRegisterContextNetBSD_x86_64::ReadRegisterSet");
242 }
243 
244 Status NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(uint32_t set) {
245   switch (set) {
246   case GPRegSet:
247     return DoRegisterSet(PT_SETREGS, &m_gpr_x86_64);
248   case FPRegSet:
249     return DoRegisterSet(PT_SETFPREGS, &m_fpr_x86_64);
250   case DBRegSet:
251     return DoRegisterSet(PT_SETDBREGS, &m_dbr_x86_64);
252   case XStateRegSet:
253 #ifdef HAVE_XSTATE
254     {
255       struct iovec iov = {&m_xstate_x86_64, sizeof(m_xstate_x86_64)};
256       return DoRegisterSet(PT_SETXSTATE, &iov);
257     }
258 #else
259     return Status("XState is not supported by the kernel");
260 #endif
261   }
262   llvm_unreachable("NativeRegisterContextNetBSD_x86_64::WriteRegisterSet");
263 }
264 
265 Status
266 NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info,
267                                                  RegisterValue &reg_value) {
268   Status error;
269 
270   if (!reg_info) {
271     error.SetErrorString("reg_info NULL");
272     return error;
273   }
274 
275   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
276   if (reg == LLDB_INVALID_REGNUM) {
277     // This is likely an internal register for lldb use only and should not be
278     // directly queried.
279     error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
280                                    "register, cannot read directly",
281                                    reg_info->name);
282     return error;
283   }
284 
285   int set = GetSetForNativeRegNum(reg);
286   if (set == -1) {
287     // This is likely an internal register for lldb use only and should not be
288     // directly queried.
289     error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
290                                    reg_info->name);
291     return error;
292   }
293 
294   error = ReadRegisterSet(set);
295   if (error.Fail())
296     return error;
297 
298   switch (reg) {
299   case lldb_rax_x86_64:
300     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RAX];
301     break;
302   case lldb_rbx_x86_64:
303     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RBX];
304     break;
305   case lldb_rcx_x86_64:
306     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RCX];
307     break;
308   case lldb_rdx_x86_64:
309     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RDX];
310     break;
311   case lldb_rdi_x86_64:
312     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RDI];
313     break;
314   case lldb_rsi_x86_64:
315     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RSI];
316     break;
317   case lldb_rbp_x86_64:
318     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RBP];
319     break;
320   case lldb_rsp_x86_64:
321     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RSP];
322     break;
323   case lldb_r8_x86_64:
324     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R8];
325     break;
326   case lldb_r9_x86_64:
327     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R9];
328     break;
329   case lldb_r10_x86_64:
330     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R10];
331     break;
332   case lldb_r11_x86_64:
333     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R11];
334     break;
335   case lldb_r12_x86_64:
336     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R12];
337     break;
338   case lldb_r13_x86_64:
339     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R13];
340     break;
341   case lldb_r14_x86_64:
342     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R14];
343     break;
344   case lldb_r15_x86_64:
345     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_R15];
346     break;
347   case lldb_rip_x86_64:
348     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RIP];
349     break;
350   case lldb_rflags_x86_64:
351     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_RFLAGS];
352     break;
353   case lldb_cs_x86_64:
354     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_CS];
355     break;
356   case lldb_fs_x86_64:
357     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_FS];
358     break;
359   case lldb_gs_x86_64:
360     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_GS];
361     break;
362   case lldb_ss_x86_64:
363     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_SS];
364     break;
365   case lldb_ds_x86_64:
366     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_DS];
367     break;
368   case lldb_es_x86_64:
369     reg_value = (uint64_t)m_gpr_x86_64.regs[_REG_ES];
370     break;
371   case lldb_fctrl_x86_64:
372     reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_cw;
373     break;
374   case lldb_fstat_x86_64:
375     reg_value = (uint16_t)m_fpr_x86_64.fxstate.fx_sw;
376     break;
377   case lldb_ftag_x86_64:
378     reg_value = (uint8_t)m_fpr_x86_64.fxstate.fx_tw;
379     break;
380   case lldb_fop_x86_64:
381     reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_opcode;
382     break;
383   case lldb_fiseg_x86_64:
384     reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_ip.fa_64;
385     break;
386   case lldb_fioff_x86_64:
387     reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off;
388     break;
389   case lldb_foseg_x86_64:
390     reg_value = (uint64_t)m_fpr_x86_64.fxstate.fx_dp.fa_64;
391     break;
392   case lldb_fooff_x86_64:
393     reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off;
394     break;
395   case lldb_mxcsr_x86_64:
396     reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr;
397     break;
398   case lldb_mxcsrmask_x86_64:
399     reg_value = (uint32_t)m_fpr_x86_64.fxstate.fx_mxcsr_mask;
400     break;
401   case lldb_st0_x86_64:
402   case lldb_st1_x86_64:
403   case lldb_st2_x86_64:
404   case lldb_st3_x86_64:
405   case lldb_st4_x86_64:
406   case lldb_st5_x86_64:
407   case lldb_st6_x86_64:
408   case lldb_st7_x86_64:
409     reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64],
410                        reg_info->byte_size, endian::InlHostByteOrder());
411     break;
412   case lldb_mm0_x86_64:
413   case lldb_mm1_x86_64:
414   case lldb_mm2_x86_64:
415   case lldb_mm3_x86_64:
416   case lldb_mm4_x86_64:
417   case lldb_mm5_x86_64:
418   case lldb_mm6_x86_64:
419   case lldb_mm7_x86_64:
420     reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_mm0_x86_64],
421                        reg_info->byte_size, endian::InlHostByteOrder());
422     break;
423   case lldb_xmm0_x86_64:
424   case lldb_xmm1_x86_64:
425   case lldb_xmm2_x86_64:
426   case lldb_xmm3_x86_64:
427   case lldb_xmm4_x86_64:
428   case lldb_xmm5_x86_64:
429   case lldb_xmm6_x86_64:
430   case lldb_xmm7_x86_64:
431   case lldb_xmm8_x86_64:
432   case lldb_xmm9_x86_64:
433   case lldb_xmm10_x86_64:
434   case lldb_xmm11_x86_64:
435   case lldb_xmm12_x86_64:
436   case lldb_xmm13_x86_64:
437   case lldb_xmm14_x86_64:
438   case lldb_xmm15_x86_64:
439     reg_value.SetBytes(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64],
440                        reg_info->byte_size, endian::InlHostByteOrder());
441     break;
442   case lldb_ymm0_x86_64:
443   case lldb_ymm1_x86_64:
444   case lldb_ymm2_x86_64:
445   case lldb_ymm3_x86_64:
446   case lldb_ymm4_x86_64:
447   case lldb_ymm5_x86_64:
448   case lldb_ymm6_x86_64:
449   case lldb_ymm7_x86_64:
450   case lldb_ymm8_x86_64:
451   case lldb_ymm9_x86_64:
452   case lldb_ymm10_x86_64:
453   case lldb_ymm11_x86_64:
454   case lldb_ymm12_x86_64:
455   case lldb_ymm13_x86_64:
456   case lldb_ymm14_x86_64:
457   case lldb_ymm15_x86_64:
458 #ifdef HAVE_XSTATE
459     if (!(m_xstate_x86_64.xs_rfbm & XCR0_SSE) ||
460         !(m_xstate_x86_64.xs_rfbm & XCR0_YMM_Hi128)) {
461       error.SetErrorStringWithFormat("register \"%s\" not supported by CPU/kernel",
462                                      reg_info->name);
463     } else {
464       uint32_t reg_index = reg - lldb_ymm0_x86_64;
465       YMMReg ymm = XStateToYMM(
466           m_xstate_x86_64.xs_fxsave.fx_xmm[reg_index].xmm_bytes,
467           m_xstate_x86_64.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes);
468       reg_value.SetBytes(ymm.bytes, reg_info->byte_size,
469                          endian::InlHostByteOrder());
470     }
471 #else
472     error.SetErrorString("XState queries not supported by the kernel");
473 #endif
474     break;
475   case lldb_dr0_x86_64:
476   case lldb_dr1_x86_64:
477   case lldb_dr2_x86_64:
478   case lldb_dr3_x86_64:
479   case lldb_dr4_x86_64:
480   case lldb_dr5_x86_64:
481   case lldb_dr6_x86_64:
482   case lldb_dr7_x86_64:
483     reg_value = (uint64_t)m_dbr_x86_64.dr[reg - lldb_dr0_x86_64];
484     break;
485   }
486 
487   return error;
488 }
489 
490 Status NativeRegisterContextNetBSD_x86_64::WriteRegister(
491     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
492 
493   Status error;
494 
495   if (!reg_info) {
496     error.SetErrorString("reg_info NULL");
497     return error;
498   }
499 
500   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
501   if (reg == LLDB_INVALID_REGNUM) {
502     // This is likely an internal register for lldb use only and should not be
503     // directly queried.
504     error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
505                                    "register, cannot read directly",
506                                    reg_info->name);
507     return error;
508   }
509 
510   int set = GetSetForNativeRegNum(reg);
511   if (set == -1) {
512     // This is likely an internal register for lldb use only and should not be
513     // directly queried.
514     error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
515                                    reg_info->name);
516     return error;
517   }
518 
519   error = ReadRegisterSet(set);
520   if (error.Fail())
521     return error;
522 
523   switch (reg) {
524   case lldb_rax_x86_64:
525     m_gpr_x86_64.regs[_REG_RAX] = reg_value.GetAsUInt64();
526     break;
527   case lldb_rbx_x86_64:
528     m_gpr_x86_64.regs[_REG_RBX] = reg_value.GetAsUInt64();
529     break;
530   case lldb_rcx_x86_64:
531     m_gpr_x86_64.regs[_REG_RCX] = reg_value.GetAsUInt64();
532     break;
533   case lldb_rdx_x86_64:
534     m_gpr_x86_64.regs[_REG_RDX] = reg_value.GetAsUInt64();
535     break;
536   case lldb_rdi_x86_64:
537     m_gpr_x86_64.regs[_REG_RDI] = reg_value.GetAsUInt64();
538     break;
539   case lldb_rsi_x86_64:
540     m_gpr_x86_64.regs[_REG_RSI] = reg_value.GetAsUInt64();
541     break;
542   case lldb_rbp_x86_64:
543     m_gpr_x86_64.regs[_REG_RBP] = reg_value.GetAsUInt64();
544     break;
545   case lldb_rsp_x86_64:
546     m_gpr_x86_64.regs[_REG_RSP] = reg_value.GetAsUInt64();
547     break;
548   case lldb_r8_x86_64:
549     m_gpr_x86_64.regs[_REG_R8] = reg_value.GetAsUInt64();
550     break;
551   case lldb_r9_x86_64:
552     m_gpr_x86_64.regs[_REG_R9] = reg_value.GetAsUInt64();
553     break;
554   case lldb_r10_x86_64:
555     m_gpr_x86_64.regs[_REG_R10] = reg_value.GetAsUInt64();
556     break;
557   case lldb_r11_x86_64:
558     m_gpr_x86_64.regs[_REG_R11] = reg_value.GetAsUInt64();
559     break;
560   case lldb_r12_x86_64:
561     m_gpr_x86_64.regs[_REG_R12] = reg_value.GetAsUInt64();
562     break;
563   case lldb_r13_x86_64:
564     m_gpr_x86_64.regs[_REG_R13] = reg_value.GetAsUInt64();
565     break;
566   case lldb_r14_x86_64:
567     m_gpr_x86_64.regs[_REG_R14] = reg_value.GetAsUInt64();
568     break;
569   case lldb_r15_x86_64:
570     m_gpr_x86_64.regs[_REG_R15] = reg_value.GetAsUInt64();
571     break;
572   case lldb_rip_x86_64:
573     m_gpr_x86_64.regs[_REG_RIP] = reg_value.GetAsUInt64();
574     break;
575   case lldb_rflags_x86_64:
576     m_gpr_x86_64.regs[_REG_RFLAGS] = reg_value.GetAsUInt64();
577     break;
578   case lldb_cs_x86_64:
579     m_gpr_x86_64.regs[_REG_CS] = reg_value.GetAsUInt64();
580     break;
581   case lldb_fs_x86_64:
582     m_gpr_x86_64.regs[_REG_FS] = reg_value.GetAsUInt64();
583     break;
584   case lldb_gs_x86_64:
585     m_gpr_x86_64.regs[_REG_GS] = reg_value.GetAsUInt64();
586     break;
587   case lldb_ss_x86_64:
588     m_gpr_x86_64.regs[_REG_SS] = reg_value.GetAsUInt64();
589     break;
590   case lldb_ds_x86_64:
591     m_gpr_x86_64.regs[_REG_DS] = reg_value.GetAsUInt64();
592     break;
593   case lldb_es_x86_64:
594     m_gpr_x86_64.regs[_REG_ES] = reg_value.GetAsUInt64();
595     break;
596   case lldb_fctrl_x86_64:
597     m_fpr_x86_64.fxstate.fx_cw = reg_value.GetAsUInt16();
598     break;
599   case lldb_fstat_x86_64:
600     m_fpr_x86_64.fxstate.fx_sw = reg_value.GetAsUInt16();
601     break;
602   case lldb_ftag_x86_64:
603     m_fpr_x86_64.fxstate.fx_tw = reg_value.GetAsUInt8();
604     break;
605   case lldb_fop_x86_64:
606     m_fpr_x86_64.fxstate.fx_opcode = reg_value.GetAsUInt16();
607     break;
608   case lldb_fiseg_x86_64:
609     m_fpr_x86_64.fxstate.fx_ip.fa_64 = reg_value.GetAsUInt64();
610     break;
611   case lldb_fioff_x86_64:
612     m_fpr_x86_64.fxstate.fx_ip.fa_32.fa_off = reg_value.GetAsUInt32();
613     break;
614   case lldb_foseg_x86_64:
615     m_fpr_x86_64.fxstate.fx_dp.fa_64 = reg_value.GetAsUInt64();
616     break;
617   case lldb_fooff_x86_64:
618     m_fpr_x86_64.fxstate.fx_dp.fa_32.fa_off = reg_value.GetAsUInt32();
619     break;
620   case lldb_mxcsr_x86_64:
621     m_fpr_x86_64.fxstate.fx_mxcsr = reg_value.GetAsUInt32();
622     break;
623   case lldb_mxcsrmask_x86_64:
624     m_fpr_x86_64.fxstate.fx_mxcsr_mask = reg_value.GetAsUInt32();
625     break;
626   case lldb_st0_x86_64:
627   case lldb_st1_x86_64:
628   case lldb_st2_x86_64:
629   case lldb_st3_x86_64:
630   case lldb_st4_x86_64:
631   case lldb_st5_x86_64:
632   case lldb_st6_x86_64:
633   case lldb_st7_x86_64:
634     ::memcpy(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_st0_x86_64],
635              reg_value.GetBytes(), reg_value.GetByteSize());
636     break;
637   case lldb_mm0_x86_64:
638   case lldb_mm1_x86_64:
639   case lldb_mm2_x86_64:
640   case lldb_mm3_x86_64:
641   case lldb_mm4_x86_64:
642   case lldb_mm5_x86_64:
643   case lldb_mm6_x86_64:
644   case lldb_mm7_x86_64:
645     ::memcpy(&m_fpr_x86_64.fxstate.fx_87_ac[reg - lldb_mm0_x86_64],
646              reg_value.GetBytes(), reg_value.GetByteSize());
647     break;
648   case lldb_xmm0_x86_64:
649   case lldb_xmm1_x86_64:
650   case lldb_xmm2_x86_64:
651   case lldb_xmm3_x86_64:
652   case lldb_xmm4_x86_64:
653   case lldb_xmm5_x86_64:
654   case lldb_xmm6_x86_64:
655   case lldb_xmm7_x86_64:
656   case lldb_xmm8_x86_64:
657   case lldb_xmm9_x86_64:
658   case lldb_xmm10_x86_64:
659   case lldb_xmm11_x86_64:
660   case lldb_xmm12_x86_64:
661   case lldb_xmm13_x86_64:
662   case lldb_xmm14_x86_64:
663   case lldb_xmm15_x86_64:
664     ::memcpy(&m_fpr_x86_64.fxstate.fx_xmm[reg - lldb_xmm0_x86_64],
665              reg_value.GetBytes(), reg_value.GetByteSize());
666     break;
667   case lldb_ymm0_x86_64:
668   case lldb_ymm1_x86_64:
669   case lldb_ymm2_x86_64:
670   case lldb_ymm3_x86_64:
671   case lldb_ymm4_x86_64:
672   case lldb_ymm5_x86_64:
673   case lldb_ymm6_x86_64:
674   case lldb_ymm7_x86_64:
675   case lldb_ymm8_x86_64:
676   case lldb_ymm9_x86_64:
677   case lldb_ymm10_x86_64:
678   case lldb_ymm11_x86_64:
679   case lldb_ymm12_x86_64:
680   case lldb_ymm13_x86_64:
681   case lldb_ymm14_x86_64:
682   case lldb_ymm15_x86_64:
683 #ifdef HAVE_XSTATE
684     if (!(m_xstate_x86_64.xs_rfbm & XCR0_SSE) ||
685         !(m_xstate_x86_64.xs_rfbm & XCR0_YMM_Hi128)) {
686       error.SetErrorStringWithFormat("register \"%s\" not supported by CPU/kernel",
687                                      reg_info->name);
688     } else {
689       uint32_t reg_index = reg - lldb_ymm0_x86_64;
690       YMMReg ymm;
691       ::memcpy(ymm.bytes, reg_value.GetBytes(), reg_value.GetByteSize());
692       YMMToXState(ymm,
693           m_xstate_x86_64.xs_fxsave.fx_xmm[reg_index].xmm_bytes,
694           m_xstate_x86_64.xs_ymm_hi128.xs_ymm[reg_index].ymm_bytes);
695     }
696 #else
697     error.SetErrorString("XState not supported by the kernel");
698 #endif
699     break;
700   case lldb_dr0_x86_64:
701   case lldb_dr1_x86_64:
702   case lldb_dr2_x86_64:
703   case lldb_dr3_x86_64:
704   case lldb_dr4_x86_64:
705   case lldb_dr5_x86_64:
706   case lldb_dr6_x86_64:
707   case lldb_dr7_x86_64:
708     m_dbr_x86_64.dr[reg - lldb_dr0_x86_64] = reg_value.GetAsUInt64();
709     break;
710   }
711 
712   return WriteRegisterSet(set);
713 }
714 
715 Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues(
716     lldb::DataBufferSP &data_sp) {
717   Status error;
718 
719   data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
720   error = ReadRegisterSet(GPRegSet);
721   if (error.Fail())
722     return error;
723 
724   uint8_t *dst = data_sp->GetBytes();
725   ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());
726   dst += GetRegisterInfoInterface().GetGPRSize();
727 
728   RegisterValue value((uint64_t)-1);
729   const RegisterInfo *reg_info =
730       GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax");
731   if (reg_info == nullptr)
732     reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax");
733   return error;
734 }
735 
736 Status NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues(
737     const lldb::DataBufferSP &data_sp) {
738   Status error;
739 
740   if (!data_sp) {
741     error.SetErrorStringWithFormat(
742         "NativeRegisterContextNetBSD_x86_64::%s invalid data_sp provided",
743         __FUNCTION__);
744     return error;
745   }
746 
747   if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
748     error.SetErrorStringWithFormat(
749         "NativeRegisterContextNetBSD_x86_64::%s data_sp contained mismatched "
750         "data size, expected %" PRIu64 ", actual %" PRIu64,
751         __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
752     return error;
753   }
754 
755   uint8_t *src = data_sp->GetBytes();
756   if (src == nullptr) {
757     error.SetErrorStringWithFormat("NativeRegisterContextNetBSD_x86_64::%s "
758                                    "DataBuffer::GetBytes() returned a null "
759                                    "pointer",
760                                    __FUNCTION__);
761     return error;
762   }
763   ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize());
764 
765   error = WriteRegisterSet(GPRegSet);
766   if (error.Fail())
767     return error;
768   src += GetRegisterInfoInterface().GetGPRSize();
769 
770   return error;
771 }
772 
773 Status NativeRegisterContextNetBSD_x86_64::IsWatchpointHit(uint32_t wp_index,
774                                                            bool &is_hit) {
775   if (wp_index >= NumSupportedHardwareWatchpoints())
776     return Status("Watchpoint index out of range");
777 
778   RegisterValue reg_value;
779   const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr6_x86_64);
780   Status error = ReadRegister(reg_info, reg_value);
781   if (error.Fail()) {
782     is_hit = false;
783     return error;
784   }
785 
786   uint64_t status_bits = reg_value.GetAsUInt64();
787 
788   is_hit = status_bits & (1 << wp_index);
789 
790   return error;
791 }
792 
793 Status NativeRegisterContextNetBSD_x86_64::GetWatchpointHitIndex(
794     uint32_t &wp_index, lldb::addr_t trap_addr) {
795   uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
796   for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
797     bool is_hit;
798     Status error = IsWatchpointHit(wp_index, is_hit);
799     if (error.Fail()) {
800       wp_index = LLDB_INVALID_INDEX32;
801       return error;
802     } else if (is_hit) {
803       return error;
804     }
805   }
806   wp_index = LLDB_INVALID_INDEX32;
807   return Status();
808 }
809 
810 Status NativeRegisterContextNetBSD_x86_64::IsWatchpointVacant(uint32_t wp_index,
811                                                               bool &is_vacant) {
812   if (wp_index >= NumSupportedHardwareWatchpoints())
813     return Status("Watchpoint index out of range");
814 
815   RegisterValue reg_value;
816   const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(lldb_dr7_x86_64);
817   Status error = ReadRegister(reg_info, reg_value);
818   if (error.Fail()) {
819     is_vacant = false;
820     return error;
821   }
822 
823   uint64_t control_bits = reg_value.GetAsUInt64();
824 
825   is_vacant = !(control_bits & (1 << (2 * wp_index + 1)));
826 
827   return error;
828 }
829 
830 Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
831     lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
832 
833   if (wp_index >= NumSupportedHardwareWatchpoints())
834     return Status("Watchpoint index out of range");
835 
836   // Read only watchpoints aren't supported on x86_64. Fall back to read/write
837   // waitchpoints instead.
838   // TODO: Add logic to detect when a write happens and ignore that watchpoint
839   // hit.
840   if (watch_flags == 0x2)
841     watch_flags = 0x3;
842 
843   if (watch_flags != 0x1 && watch_flags != 0x3)
844     return Status("Invalid read/write bits for watchpoint");
845 
846   if (size != 1 && size != 2 && size != 4 && size != 8)
847     return Status("Invalid size for watchpoint");
848 
849   bool is_vacant;
850   Status error = IsWatchpointVacant(wp_index, is_vacant);
851   if (error.Fail())
852     return error;
853   if (!is_vacant)
854     return Status("Watchpoint index not vacant");
855 
856   const RegisterInfo *const reg_info_dr7 =
857       GetRegisterInfoAtIndex(lldb_dr7_x86_64);
858   RegisterValue dr7_value;
859   error = ReadRegister(reg_info_dr7, dr7_value);
860   if (error.Fail())
861     return error;
862 
863   // for watchpoints 0, 1, 2, or 3, respectively, set bits 1, 3, 5, or 7
864   uint64_t enable_bit = 1 << (2 * wp_index + 1);
865 
866   // set bits 16-17, 20-21, 24-25, or 28-29
867   // with 0b01 for write, and 0b11 for read/write
868   uint64_t rw_bits = watch_flags << (16 + 4 * wp_index);
869 
870   // set bits 18-19, 22-23, 26-27, or 30-31
871   // with 0b00, 0b01, 0b10, or 0b11
872   // for 1, 2, 8 (if supported), or 4 bytes, respectively
873   uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
874 
875   uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
876 
877   uint64_t control_bits = dr7_value.GetAsUInt64() & ~bit_mask;
878 
879   control_bits |= enable_bit | rw_bits | size_bits;
880 
881   const RegisterInfo *const reg_info_drN =
882       GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index);
883   RegisterValue drN_value;
884   error = ReadRegister(reg_info_drN, drN_value);
885   if (error.Fail())
886     return error;
887 
888   // clear dr6 if address or bits changed (i.e. we're not reenabling the same
889   // watchpoint)
890   if (drN_value.GetAsUInt64() != addr ||
891       (dr7_value.GetAsUInt64() & bit_mask) != (rw_bits | size_bits)) {
892     ClearWatchpointHit(wp_index);
893 
894     error = WriteRegister(reg_info_drN, RegisterValue(addr));
895     if (error.Fail())
896       return error;
897   }
898 
899   error = WriteRegister(reg_info_dr7, RegisterValue(control_bits));
900   if (error.Fail())
901     return error;
902 
903   error.Clear();
904   return error;
905 }
906 
907 bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint(
908     uint32_t wp_index) {
909   if (wp_index >= NumSupportedHardwareWatchpoints())
910     return false;
911 
912   // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0-1, 2-3, 4-5
913   // or 6-7 of the debug control register (DR7)
914   const RegisterInfo *const reg_info_dr7 =
915       GetRegisterInfoAtIndex(lldb_dr7_x86_64);
916   RegisterValue reg_value;
917   Status error = ReadRegister(reg_info_dr7, reg_value);
918   if (error.Fail())
919     return false;
920   uint64_t bit_mask = 0x3 << (2 * wp_index);
921   uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
922 
923   return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success();
924 }
925 
926 Status NativeRegisterContextNetBSD_x86_64::ClearWatchpointHit(uint32_t wp_index) {
927   if (wp_index >= NumSupportedHardwareWatchpoints())
928     return Status("Watchpoint index out of range");
929 
930   // for watchpoints 0, 1, 2, or 3, respectively, check bits 0, 1, 2, or 3 of
931   // the debug status register (DR6)
932   const RegisterInfo *const reg_info_dr6 =
933       GetRegisterInfoAtIndex(lldb_dr6_x86_64);
934   RegisterValue reg_value;
935   Status error = ReadRegister(reg_info_dr6, reg_value);
936   if (error.Fail())
937     return error;
938 
939   uint64_t bit_mask = 1 << wp_index;
940   uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
941   return WriteRegister(reg_info_dr6, RegisterValue(status_bits));
942 }
943 
944 Status NativeRegisterContextNetBSD_x86_64::ClearAllHardwareWatchpoints() {
945   RegisterValue reg_value;
946 
947   // clear bits {0-4} of the debug status register (DR6)
948   const RegisterInfo *const reg_info_dr6 =
949       GetRegisterInfoAtIndex(lldb_dr6_x86_64);
950   Status error = ReadRegister(reg_info_dr6, reg_value);
951   if (error.Fail())
952     return error;
953   uint64_t bit_mask = 0xF;
954   uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
955   error = WriteRegister(reg_info_dr6, RegisterValue(status_bits));
956   if (error.Fail())
957     return error;
958 
959   // clear bits {0-7,16-31} of the debug control register (DR7)
960   const RegisterInfo *const reg_info_dr7 =
961       GetRegisterInfoAtIndex(lldb_dr7_x86_64);
962   error = ReadRegister(reg_info_dr7, reg_value);
963   if (error.Fail())
964     return error;
965   bit_mask = 0xFF | (0xFFFF << 16);
966   uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
967   return WriteRegister(reg_info_dr7, RegisterValue(control_bits));
968 }
969 
970 uint32_t NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpoint(
971     lldb::addr_t addr, size_t size, uint32_t watch_flags) {
972   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
973   const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
974   for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) {
975     bool is_vacant;
976     Status error = IsWatchpointVacant(wp_index, is_vacant);
977     if (is_vacant) {
978       error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index);
979       if (error.Success())
980         return wp_index;
981     }
982     if (error.Fail() && log) {
983       LLDB_LOGF(log, "NativeRegisterContextNetBSD_x86_64::%s Error: %s",
984                 __FUNCTION__, error.AsCString());
985     }
986   }
987   return LLDB_INVALID_INDEX32;
988 }
989 
990 lldb::addr_t
991 NativeRegisterContextNetBSD_x86_64::GetWatchpointAddress(uint32_t wp_index) {
992   if (wp_index >= NumSupportedHardwareWatchpoints())
993     return LLDB_INVALID_ADDRESS;
994   RegisterValue reg_value;
995   const RegisterInfo *const reg_info_drN =
996       GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index);
997   if (ReadRegister(reg_info_drN, reg_value).Fail())
998     return LLDB_INVALID_ADDRESS;
999   return reg_value.GetAsUInt64();
1000 }
1001 
1002 uint32_t NativeRegisterContextNetBSD_x86_64::NumSupportedHardwareWatchpoints() {
1003   // Available debug address registers: dr0, dr1, dr2, dr3
1004   return 4;
1005 }
1006 
1007 Status NativeRegisterContextNetBSD_x86_64::CopyHardwareWatchpointsFrom(
1008     NativeRegisterContextNetBSD &source) {
1009   auto &r_source = static_cast<NativeRegisterContextNetBSD_x86_64&>(source);
1010   Status res = r_source.ReadRegisterSet(DBRegSet);
1011   if (!res.Fail()) {
1012     // copy dbregs only if any watchpoints were set
1013     if ((r_source.m_dbr_x86_64.dr[7] & 0xFF) == 0)
1014       return res;
1015 
1016     m_dbr_x86_64 = r_source.m_dbr_x86_64;
1017     res = WriteRegisterSet(DBRegSet);
1018   }
1019   return res;
1020 }
1021 
1022 #endif // defined(__x86_64__)
1023