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