1 //===-- NativeRegisterContextLinux_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(__i386__) || defined(__x86_64__)
10 
11 #include "NativeRegisterContextLinux_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/RegisterContextLinux_i386.h"
20 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
21 
22 #include <linux/elf.h>
23 
24 using namespace lldb_private;
25 using namespace lldb_private::process_linux;
26 
27 // ----------------------------------------------------------------------------
28 // Private namespace.
29 // ----------------------------------------------------------------------------
30 
31 namespace {
32 // x86 32-bit general purpose registers.
33 const uint32_t g_gpr_regnums_i386[] = {
34     lldb_eax_i386,      lldb_ebx_i386,    lldb_ecx_i386, lldb_edx_i386,
35     lldb_edi_i386,      lldb_esi_i386,    lldb_ebp_i386, lldb_esp_i386,
36     lldb_eip_i386,      lldb_eflags_i386, lldb_cs_i386,  lldb_fs_i386,
37     lldb_gs_i386,       lldb_ss_i386,     lldb_ds_i386,  lldb_es_i386,
38     lldb_ax_i386,       lldb_bx_i386,     lldb_cx_i386,  lldb_dx_i386,
39     lldb_di_i386,       lldb_si_i386,     lldb_bp_i386,  lldb_sp_i386,
40     lldb_ah_i386,       lldb_bh_i386,     lldb_ch_i386,  lldb_dh_i386,
41     lldb_al_i386,       lldb_bl_i386,     lldb_cl_i386,  lldb_dl_i386,
42     LLDB_INVALID_REGNUM // register sets need to end with this flag
43 };
44 static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) -
45                       1 ==
46                   k_num_gpr_registers_i386,
47               "g_gpr_regnums_i386 has wrong number of register infos");
48 
49 // x86 32-bit floating point registers.
50 const uint32_t g_fpu_regnums_i386[] = {
51     lldb_fctrl_i386,    lldb_fstat_i386,     lldb_ftag_i386,  lldb_fop_i386,
52     lldb_fiseg_i386,    lldb_fioff_i386,     lldb_foseg_i386, lldb_fooff_i386,
53     lldb_mxcsr_i386,    lldb_mxcsrmask_i386, lldb_st0_i386,   lldb_st1_i386,
54     lldb_st2_i386,      lldb_st3_i386,       lldb_st4_i386,   lldb_st5_i386,
55     lldb_st6_i386,      lldb_st7_i386,       lldb_mm0_i386,   lldb_mm1_i386,
56     lldb_mm2_i386,      lldb_mm3_i386,       lldb_mm4_i386,   lldb_mm5_i386,
57     lldb_mm6_i386,      lldb_mm7_i386,       lldb_xmm0_i386,  lldb_xmm1_i386,
58     lldb_xmm2_i386,     lldb_xmm3_i386,      lldb_xmm4_i386,  lldb_xmm5_i386,
59     lldb_xmm6_i386,     lldb_xmm7_i386,
60     LLDB_INVALID_REGNUM // register sets need to end with this flag
61 };
62 static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) -
63                       1 ==
64                   k_num_fpr_registers_i386,
65               "g_fpu_regnums_i386 has wrong number of register infos");
66 
67 // x86 32-bit AVX registers.
68 const uint32_t g_avx_regnums_i386[] = {
69     lldb_ymm0_i386,     lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386,
70     lldb_ymm4_i386,     lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386,
71     LLDB_INVALID_REGNUM // register sets need to end with this flag
72 };
73 static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) -
74                       1 ==
75                   k_num_avx_registers_i386,
76               " g_avx_regnums_i386 has wrong number of register infos");
77 
78 // x64 32-bit MPX registers.
79 static const uint32_t g_mpx_regnums_i386[] = {
80     lldb_bnd0_i386,     lldb_bnd1_i386, lldb_bnd2_i386, lldb_bnd3_i386,
81     lldb_bndcfgu_i386,  lldb_bndstatus_i386,
82     LLDB_INVALID_REGNUM // register sets need to end with this flag
83 };
84 static_assert((sizeof(g_mpx_regnums_i386) / sizeof(g_mpx_regnums_i386[0])) -
85                       1 ==
86                   k_num_mpx_registers_i386,
87               "g_mpx_regnums_x86_64 has wrong number of register infos");
88 
89 // x86 64-bit general purpose registers.
90 static const uint32_t g_gpr_regnums_x86_64[] = {
91     lldb_rax_x86_64,    lldb_rbx_x86_64,    lldb_rcx_x86_64, lldb_rdx_x86_64,
92     lldb_rdi_x86_64,    lldb_rsi_x86_64,    lldb_rbp_x86_64, lldb_rsp_x86_64,
93     lldb_r8_x86_64,     lldb_r9_x86_64,     lldb_r10_x86_64, lldb_r11_x86_64,
94     lldb_r12_x86_64,    lldb_r13_x86_64,    lldb_r14_x86_64, lldb_r15_x86_64,
95     lldb_rip_x86_64,    lldb_rflags_x86_64, lldb_cs_x86_64,  lldb_fs_x86_64,
96     lldb_gs_x86_64,     lldb_ss_x86_64,     lldb_ds_x86_64,  lldb_es_x86_64,
97     lldb_eax_x86_64,    lldb_ebx_x86_64,    lldb_ecx_x86_64, lldb_edx_x86_64,
98     lldb_edi_x86_64,    lldb_esi_x86_64,    lldb_ebp_x86_64, lldb_esp_x86_64,
99     lldb_r8d_x86_64,  // Low 32 bits or r8
100     lldb_r9d_x86_64,  // Low 32 bits or r9
101     lldb_r10d_x86_64, // Low 32 bits or r10
102     lldb_r11d_x86_64, // Low 32 bits or r11
103     lldb_r12d_x86_64, // Low 32 bits or r12
104     lldb_r13d_x86_64, // Low 32 bits or r13
105     lldb_r14d_x86_64, // Low 32 bits or r14
106     lldb_r15d_x86_64, // Low 32 bits or r15
107     lldb_ax_x86_64,     lldb_bx_x86_64,     lldb_cx_x86_64,  lldb_dx_x86_64,
108     lldb_di_x86_64,     lldb_si_x86_64,     lldb_bp_x86_64,  lldb_sp_x86_64,
109     lldb_r8w_x86_64,  // Low 16 bits or r8
110     lldb_r9w_x86_64,  // Low 16 bits or r9
111     lldb_r10w_x86_64, // Low 16 bits or r10
112     lldb_r11w_x86_64, // Low 16 bits or r11
113     lldb_r12w_x86_64, // Low 16 bits or r12
114     lldb_r13w_x86_64, // Low 16 bits or r13
115     lldb_r14w_x86_64, // Low 16 bits or r14
116     lldb_r15w_x86_64, // Low 16 bits or r15
117     lldb_ah_x86_64,     lldb_bh_x86_64,     lldb_ch_x86_64,  lldb_dh_x86_64,
118     lldb_al_x86_64,     lldb_bl_x86_64,     lldb_cl_x86_64,  lldb_dl_x86_64,
119     lldb_dil_x86_64,    lldb_sil_x86_64,    lldb_bpl_x86_64, lldb_spl_x86_64,
120     lldb_r8l_x86_64,    // Low 8 bits or r8
121     lldb_r9l_x86_64,    // Low 8 bits or r9
122     lldb_r10l_x86_64,   // Low 8 bits or r10
123     lldb_r11l_x86_64,   // Low 8 bits or r11
124     lldb_r12l_x86_64,   // Low 8 bits or r12
125     lldb_r13l_x86_64,   // Low 8 bits or r13
126     lldb_r14l_x86_64,   // Low 8 bits or r14
127     lldb_r15l_x86_64,   // Low 8 bits or r15
128     LLDB_INVALID_REGNUM // register sets need to end with this flag
129 };
130 static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
131                       1 ==
132                   k_num_gpr_registers_x86_64,
133               "g_gpr_regnums_x86_64 has wrong number of register infos");
134 
135 // x86 64-bit floating point registers.
136 static const uint32_t g_fpu_regnums_x86_64[] = {
137     lldb_fctrl_x86_64,     lldb_fstat_x86_64, lldb_ftag_x86_64,
138     lldb_fop_x86_64,       lldb_fiseg_x86_64, lldb_fioff_x86_64,
139     lldb_foseg_x86_64,     lldb_fooff_x86_64, lldb_mxcsr_x86_64,
140     lldb_mxcsrmask_x86_64, lldb_st0_x86_64,   lldb_st1_x86_64,
141     lldb_st2_x86_64,       lldb_st3_x86_64,   lldb_st4_x86_64,
142     lldb_st5_x86_64,       lldb_st6_x86_64,   lldb_st7_x86_64,
143     lldb_mm0_x86_64,       lldb_mm1_x86_64,   lldb_mm2_x86_64,
144     lldb_mm3_x86_64,       lldb_mm4_x86_64,   lldb_mm5_x86_64,
145     lldb_mm6_x86_64,       lldb_mm7_x86_64,   lldb_xmm0_x86_64,
146     lldb_xmm1_x86_64,      lldb_xmm2_x86_64,  lldb_xmm3_x86_64,
147     lldb_xmm4_x86_64,      lldb_xmm5_x86_64,  lldb_xmm6_x86_64,
148     lldb_xmm7_x86_64,      lldb_xmm8_x86_64,  lldb_xmm9_x86_64,
149     lldb_xmm10_x86_64,     lldb_xmm11_x86_64, lldb_xmm12_x86_64,
150     lldb_xmm13_x86_64,     lldb_xmm14_x86_64, lldb_xmm15_x86_64,
151     LLDB_INVALID_REGNUM // register sets need to end with this flag
152 };
153 static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
154                       1 ==
155                   k_num_fpr_registers_x86_64,
156               "g_fpu_regnums_x86_64 has wrong number of register infos");
157 
158 // x86 64-bit AVX registers.
159 static const uint32_t g_avx_regnums_x86_64[] = {
160     lldb_ymm0_x86_64,   lldb_ymm1_x86_64,  lldb_ymm2_x86_64,  lldb_ymm3_x86_64,
161     lldb_ymm4_x86_64,   lldb_ymm5_x86_64,  lldb_ymm6_x86_64,  lldb_ymm7_x86_64,
162     lldb_ymm8_x86_64,   lldb_ymm9_x86_64,  lldb_ymm10_x86_64, lldb_ymm11_x86_64,
163     lldb_ymm12_x86_64,  lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64,
164     LLDB_INVALID_REGNUM // register sets need to end with this flag
165 };
166 static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) -
167                       1 ==
168                   k_num_avx_registers_x86_64,
169               "g_avx_regnums_x86_64 has wrong number of register infos");
170 
171 // x86 64-bit MPX registers.
172 static const uint32_t g_mpx_regnums_x86_64[] = {
173     lldb_bnd0_x86_64,    lldb_bnd1_x86_64,    lldb_bnd2_x86_64,
174     lldb_bnd3_x86_64,    lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64,
175     LLDB_INVALID_REGNUM // register sets need to end with this flag
176 };
177 static_assert((sizeof(g_mpx_regnums_x86_64) / sizeof(g_mpx_regnums_x86_64[0])) -
178                       1 ==
179                   k_num_mpx_registers_x86_64,
180               "g_mpx_regnums_x86_64 has wrong number of register infos");
181 
182 // Number of register sets provided by this context.
183 enum { k_num_extended_register_sets = 2, k_num_register_sets = 4 };
184 
185 // Register sets for x86 32-bit.
186 static const RegisterSet g_reg_sets_i386[k_num_register_sets] = {
187     {"General Purpose Registers", "gpr", k_num_gpr_registers_i386,
188      g_gpr_regnums_i386},
189     {"Floating Point Registers", "fpu", k_num_fpr_registers_i386,
190      g_fpu_regnums_i386},
191     {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386,
192      g_avx_regnums_i386},
193     { "Memory Protection Extensions", "mpx", k_num_mpx_registers_i386,
194      g_mpx_regnums_i386}};
195 
196 // Register sets for x86 64-bit.
197 static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
198     {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64,
199      g_gpr_regnums_x86_64},
200     {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64,
201      g_fpu_regnums_x86_64},
202     {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64,
203      g_avx_regnums_x86_64},
204     { "Memory Protection Extensions", "mpx", k_num_mpx_registers_x86_64,
205      g_mpx_regnums_x86_64}};
206 }
207 
208 #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR))
209 
210 // ----------------------------------------------------------------------------
211 // Required ptrace defines.
212 // ----------------------------------------------------------------------------
213 
214 // Support ptrace extensions even when compiled without required kernel support
215 #ifndef NT_X86_XSTATE
216 #define NT_X86_XSTATE 0x202
217 #endif
218 #ifndef NT_PRXFPREG
219 #define NT_PRXFPREG 0x46e62b7f
220 #endif
221 
222 // On x86_64 NT_PRFPREG is used to access the FXSAVE area. On i386, we need to
223 // use NT_PRXFPREG.
224 static inline unsigned int fxsr_regset(const ArchSpec &arch) {
225   return arch.GetAddressByteSize() == 8 ? NT_PRFPREG : NT_PRXFPREG;
226 }
227 
228 // ----------------------------------------------------------------------------
229 // Required MPX define.
230 // ----------------------------------------------------------------------------
231 
232 // Support MPX extensions also if compiled with compiler without MPX support.
233 #ifndef bit_MPX
234 #define bit_MPX 0x4000
235 #endif
236 
237 // ----------------------------------------------------------------------------
238 // XCR0 extended register sets masks.
239 // ----------------------------------------------------------------------------
240 #define mask_XSTATE_AVX (1ULL << 2)
241 #define mask_XSTATE_BNDREGS (1ULL << 3)
242 #define mask_XSTATE_BNDCFG (1ULL << 4)
243 #define mask_XSTATE_MPX (mask_XSTATE_BNDREGS | mask_XSTATE_BNDCFG)
244 
245 std::unique_ptr<NativeRegisterContextLinux>
246 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
247     const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
248   return std::unique_ptr<NativeRegisterContextLinux>(
249       new NativeRegisterContextLinux_x86_64(target_arch, native_thread));
250 }
251 
252 // ----------------------------------------------------------------------------
253 // NativeRegisterContextLinux_x86_64 members.
254 // ----------------------------------------------------------------------------
255 
256 static RegisterInfoInterface *
257 CreateRegisterInfoInterface(const ArchSpec &target_arch) {
258   if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
259     // 32-bit hosts run with a RegisterContextLinux_i386 context.
260     return new RegisterContextLinux_i386(target_arch);
261   } else {
262     assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
263            "Register setting path assumes this is a 64-bit host");
264     // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the
265     // x86_64 register context.
266     return new RegisterContextLinux_x86_64(target_arch);
267   }
268 }
269 
270 NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
271     const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
272     : NativeRegisterContextLinux(native_thread,
273                                  CreateRegisterInfoInterface(target_arch)),
274       m_xstate_type(XStateType::Invalid), m_fpr(), m_iovec(), m_ymm_set(),
275       m_mpx_set(), m_reg_info(), m_gpr_x86_64() {
276   // Set up data about ranges of valid registers.
277   switch (target_arch.GetMachine()) {
278   case llvm::Triple::x86:
279     m_reg_info.num_registers = k_num_registers_i386;
280     m_reg_info.num_gpr_registers = k_num_gpr_registers_i386;
281     m_reg_info.num_fpr_registers = k_num_fpr_registers_i386;
282     m_reg_info.num_avx_registers = k_num_avx_registers_i386;
283     m_reg_info.num_mpx_registers = k_num_mpx_registers_i386;
284     m_reg_info.last_gpr = k_last_gpr_i386;
285     m_reg_info.first_fpr = k_first_fpr_i386;
286     m_reg_info.last_fpr = k_last_fpr_i386;
287     m_reg_info.first_st = lldb_st0_i386;
288     m_reg_info.last_st = lldb_st7_i386;
289     m_reg_info.first_mm = lldb_mm0_i386;
290     m_reg_info.last_mm = lldb_mm7_i386;
291     m_reg_info.first_xmm = lldb_xmm0_i386;
292     m_reg_info.last_xmm = lldb_xmm7_i386;
293     m_reg_info.first_ymm = lldb_ymm0_i386;
294     m_reg_info.last_ymm = lldb_ymm7_i386;
295     m_reg_info.first_mpxr = lldb_bnd0_i386;
296     m_reg_info.last_mpxr = lldb_bnd3_i386;
297     m_reg_info.first_mpxc = lldb_bndcfgu_i386;
298     m_reg_info.last_mpxc = lldb_bndstatus_i386;
299     m_reg_info.first_dr = lldb_dr0_i386;
300     m_reg_info.gpr_flags = lldb_eflags_i386;
301     break;
302   case llvm::Triple::x86_64:
303     m_reg_info.num_registers = k_num_registers_x86_64;
304     m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64;
305     m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64;
306     m_reg_info.num_avx_registers = k_num_avx_registers_x86_64;
307     m_reg_info.num_mpx_registers = k_num_mpx_registers_x86_64;
308     m_reg_info.last_gpr = k_last_gpr_x86_64;
309     m_reg_info.first_fpr = k_first_fpr_x86_64;
310     m_reg_info.last_fpr = k_last_fpr_x86_64;
311     m_reg_info.first_st = lldb_st0_x86_64;
312     m_reg_info.last_st = lldb_st7_x86_64;
313     m_reg_info.first_mm = lldb_mm0_x86_64;
314     m_reg_info.last_mm = lldb_mm7_x86_64;
315     m_reg_info.first_xmm = lldb_xmm0_x86_64;
316     m_reg_info.last_xmm = lldb_xmm15_x86_64;
317     m_reg_info.first_ymm = lldb_ymm0_x86_64;
318     m_reg_info.last_ymm = lldb_ymm15_x86_64;
319     m_reg_info.first_mpxr = lldb_bnd0_x86_64;
320     m_reg_info.last_mpxr = lldb_bnd3_x86_64;
321     m_reg_info.first_mpxc = lldb_bndcfgu_x86_64;
322     m_reg_info.last_mpxc = lldb_bndstatus_x86_64;
323     m_reg_info.first_dr = lldb_dr0_x86_64;
324     m_reg_info.gpr_flags = lldb_rflags_x86_64;
325     break;
326   default:
327     assert(false && "Unhandled target architecture.");
328     break;
329   }
330 
331   // Initialize m_iovec to point to the buffer and buffer size using the
332   // conventions of Berkeley style UIO structures, as required by PTRACE
333   // extensions.
334   m_iovec.iov_base = &m_fpr;
335   m_iovec.iov_len = sizeof(m_fpr);
336 
337   // Clear out the FPR state.
338   ::memset(&m_fpr, 0, sizeof(m_fpr));
339 
340   // Store byte offset of fctrl (i.e. first register of FPR)
341   const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl");
342   m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;
343 }
344 
345 // CONSIDER after local and llgs debugging are merged, register set support can
346 // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual.
347 uint32_t NativeRegisterContextLinux_x86_64::GetRegisterSetCount() const {
348   uint32_t sets = 0;
349   for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
350     if (IsRegisterSetAvailable(set_index))
351       ++sets;
352   }
353 
354   return sets;
355 }
356 
357 uint32_t NativeRegisterContextLinux_x86_64::GetUserRegisterCount() const {
358   uint32_t count = 0;
359   for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
360     const RegisterSet *set = GetRegisterSet(set_index);
361     if (set)
362       count += set->num_registers;
363   }
364   return count;
365 }
366 
367 const RegisterSet *
368 NativeRegisterContextLinux_x86_64::GetRegisterSet(uint32_t set_index) const {
369   if (!IsRegisterSetAvailable(set_index))
370     return nullptr;
371 
372   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
373   case llvm::Triple::x86:
374     return &g_reg_sets_i386[set_index];
375   case llvm::Triple::x86_64:
376     return &g_reg_sets_x86_64[set_index];
377   default:
378     assert(false && "Unhandled target architecture.");
379     return nullptr;
380   }
381 
382   return nullptr;
383 }
384 
385 Status
386 NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
387                                                 RegisterValue &reg_value) {
388   Status error;
389 
390   if (!reg_info) {
391     error.SetErrorString("reg_info NULL");
392     return error;
393   }
394 
395   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
396   if (reg == LLDB_INVALID_REGNUM) {
397     // This is likely an internal register for lldb use only and should not be
398     // directly queried.
399     error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
400                                    "register, cannot read directly",
401                                    reg_info->name);
402     return error;
403   }
404 
405   if (IsFPR(reg) || IsAVX(reg) || IsMPX(reg)) {
406     error = ReadFPR();
407     if (error.Fail())
408       return error;
409   } else {
410     uint32_t full_reg = reg;
411     bool is_subreg = reg_info->invalidate_regs &&
412                      (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
413 
414     if (is_subreg) {
415       // Read the full aligned 64-bit register.
416       full_reg = reg_info->invalidate_regs[0];
417     }
418 
419     error = ReadRegisterRaw(full_reg, reg_value);
420 
421     if (error.Success()) {
422       // If our read was not aligned (for ah,bh,ch,dh), shift our returned
423       // value one byte to the right.
424       if (is_subreg && (reg_info->byte_offset & 0x1))
425         reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
426 
427       // If our return byte size was greater than the return value reg size,
428       // then use the type specified by reg_info rather than the uint64_t
429       // default
430       if (reg_value.GetByteSize() > reg_info->byte_size)
431         reg_value.SetType(reg_info);
432     }
433     return error;
434   }
435 
436   if (reg_info->encoding == lldb::eEncodingVector) {
437     lldb::ByteOrder byte_order = GetByteOrder();
438 
439     if (byte_order != lldb::eByteOrderInvalid) {
440       if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
441         reg_value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes,
442                            reg_info->byte_size, byte_order);
443       if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
444         reg_value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes,
445                            reg_info->byte_size, byte_order);
446       if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
447         reg_value.SetBytes(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
448                            reg_info->byte_size, byte_order);
449       if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
450         // Concatenate ymm using the register halves in xmm.bytes and
451         // ymmh.bytes
452         if (CopyXSTATEtoYMM(reg, byte_order))
453           reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
454                              reg_info->byte_size, byte_order);
455         else {
456           error.SetErrorString("failed to copy ymm register value");
457           return error;
458         }
459       }
460       if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
461         if (CopyXSTATEtoMPX(reg))
462           reg_value.SetBytes(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,
463                              reg_info->byte_size, byte_order);
464         else {
465           error.SetErrorString("failed to copy mpx register value");
466           return error;
467         }
468       }
469       if (reg >= m_reg_info.first_mpxc && reg <= m_reg_info.last_mpxc) {
470         if (CopyXSTATEtoMPX(reg))
471           reg_value.SetBytes(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,
472                              reg_info->byte_size, byte_order);
473         else {
474           error.SetErrorString("failed to copy mpx register value");
475           return error;
476         }
477       }
478 
479       if (reg_value.GetType() != RegisterValue::eTypeBytes)
480         error.SetErrorString(
481             "write failed - type was expected to be RegisterValue::eTypeBytes");
482 
483       return error;
484     }
485 
486     error.SetErrorString("byte order is invalid");
487     return error;
488   }
489 
490   // Get pointer to m_fpr.fxsave variable and set the data from it.
491 
492   // Byte offsets of all registers are calculated wrt 'UserArea' structure.
493   // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)}
494   // and stores them in 'm_fpr' (of type FPR structure). To extract values of
495   // fpu registers, m_fpr should be read at byte offsets calculated wrt to FPR
496   // structure.
497 
498   // Since, FPR structure is also one of the member of UserArea structure.
499   // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
500   // byte_offset(fctrl wrt UserArea)
501   assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
502   uint8_t *src =
503       (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
504   switch (reg_info->byte_size) {
505   case 1:
506     reg_value.SetUInt8(*(uint8_t *)src);
507     break;
508   case 2:
509     reg_value.SetUInt16(*(uint16_t *)src);
510     break;
511   case 4:
512     reg_value.SetUInt32(*(uint32_t *)src);
513     break;
514   case 8:
515     reg_value.SetUInt64(*(uint64_t *)src);
516     break;
517   default:
518     assert(false && "Unhandled data size.");
519     error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32,
520                                    reg_info->byte_size);
521     break;
522   }
523 
524   return error;
525 }
526 
527 void NativeRegisterContextLinux_x86_64::UpdateXSTATEforWrite(
528     uint32_t reg_index) {
529   XSAVE_HDR::XFeature &xstate_bv = m_fpr.xsave.header.xstate_bv;
530   if (IsFPR(reg_index)) {
531     // IsFPR considers both %st and %xmm registers as floating point, but these
532     // map to two features. Set both flags, just in case.
533     xstate_bv |= XSAVE_HDR::XFeature::FP | XSAVE_HDR::XFeature::SSE;
534   } else if (IsAVX(reg_index)) {
535     // Lower bytes of some %ymm registers are shared with %xmm registers.
536     xstate_bv |= XSAVE_HDR::XFeature::YMM | XSAVE_HDR::XFeature::SSE;
537   } else if (IsMPX(reg_index)) {
538     // MPX registers map to two XSAVE features.
539     xstate_bv |= XSAVE_HDR::XFeature::BNDREGS | XSAVE_HDR::XFeature::BNDCSR;
540   }
541 }
542 
543 Status NativeRegisterContextLinux_x86_64::WriteRegister(
544     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
545   assert(reg_info && "reg_info is null");
546 
547   const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
548   if (reg_index == LLDB_INVALID_REGNUM)
549     return Status("no lldb regnum for %s", reg_info && reg_info->name
550                                                ? reg_info->name
551                                                : "<unknown register>");
552 
553   UpdateXSTATEforWrite(reg_index);
554 
555   if (IsGPR(reg_index))
556     return WriteRegisterRaw(reg_index, reg_value);
557 
558   if (IsFPR(reg_index) || IsAVX(reg_index) || IsMPX(reg_index)) {
559     if (reg_info->encoding == lldb::eEncodingVector) {
560       if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st)
561         ::memcpy(m_fpr.fxsave.stmm[reg_index - m_reg_info.first_st].bytes,
562                  reg_value.GetBytes(), reg_value.GetByteSize());
563 
564       if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm)
565         ::memcpy(m_fpr.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes,
566                  reg_value.GetBytes(), reg_value.GetByteSize());
567 
568       if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm)
569         ::memcpy(m_fpr.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes,
570                  reg_value.GetBytes(), reg_value.GetByteSize());
571 
572       if (reg_index >= m_reg_info.first_ymm &&
573           reg_index <= m_reg_info.last_ymm) {
574         // Store ymm register content, and split into the register halves in
575         // xmm.bytes and ymmh.bytes
576         ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
577                  reg_value.GetBytes(), reg_value.GetByteSize());
578         if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
579           return Status("CopyYMMtoXSTATE() failed");
580       }
581 
582       if (reg_index >= m_reg_info.first_mpxr &&
583           reg_index <= m_reg_info.last_mpxr) {
584         ::memcpy(m_mpx_set.mpxr[reg_index - m_reg_info.first_mpxr].bytes,
585                  reg_value.GetBytes(), reg_value.GetByteSize());
586         if (!CopyMPXtoXSTATE(reg_index))
587           return Status("CopyMPXtoXSTATE() failed");
588       }
589 
590       if (reg_index >= m_reg_info.first_mpxc &&
591           reg_index <= m_reg_info.last_mpxc) {
592         ::memcpy(m_mpx_set.mpxc[reg_index - m_reg_info.first_mpxc].bytes,
593                  reg_value.GetBytes(), reg_value.GetByteSize());
594         if (!CopyMPXtoXSTATE(reg_index))
595           return Status("CopyMPXtoXSTATE() failed");
596       }
597     } else {
598       // Get pointer to m_fpr.fxsave variable and set the data to it.
599 
600       // Byte offsets of all registers are calculated wrt 'UserArea' structure.
601       // However, WriteFPR() takes m_fpr (of type FPR structure) and writes
602       // only fpu registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu
603       // registers should be written in m_fpr at byte offsets calculated wrt
604       // FPR structure.
605 
606       // Since, FPR structure is also one of the member of UserArea structure.
607       // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
608       // byte_offset(fctrl wrt UserArea)
609       assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) <
610              sizeof(m_fpr));
611       uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset -
612                      m_fctrl_offset_in_userarea;
613       switch (reg_info->byte_size) {
614       case 1:
615         *(uint8_t *)dst = reg_value.GetAsUInt8();
616         break;
617       case 2:
618         *(uint16_t *)dst = reg_value.GetAsUInt16();
619         break;
620       case 4:
621         *(uint32_t *)dst = reg_value.GetAsUInt32();
622         break;
623       case 8:
624         *(uint64_t *)dst = reg_value.GetAsUInt64();
625         break;
626       default:
627         assert(false && "Unhandled data size.");
628         return Status("unhandled register data size %" PRIu32,
629                       reg_info->byte_size);
630       }
631     }
632 
633     Status error = WriteFPR();
634     if (error.Fail())
635       return error;
636 
637     if (IsAVX(reg_index)) {
638       if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
639         return Status("CopyYMMtoXSTATE() failed");
640     }
641 
642     if (IsMPX(reg_index)) {
643       if (!CopyMPXtoXSTATE(reg_index))
644         return Status("CopyMPXtoXSTATE() failed");
645     }
646     return Status();
647   }
648   return Status("failed - register wasn't recognized to be a GPR or an FPR, "
649                 "write strategy unknown");
650 }
651 
652 Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues(
653     lldb::DataBufferSP &data_sp) {
654   Status error;
655 
656   data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
657   error = ReadGPR();
658   if (error.Fail())
659     return error;
660 
661   error = ReadFPR();
662   if (error.Fail())
663     return error;
664 
665   uint8_t *dst = data_sp->GetBytes();
666   ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());
667   dst += GetRegisterInfoInterface().GetGPRSize();
668   if (m_xstate_type == XStateType::FXSAVE)
669     ::memcpy(dst, &m_fpr.fxsave, sizeof(m_fpr.fxsave));
670   else if (m_xstate_type == XStateType::XSAVE) {
671     lldb::ByteOrder byte_order = GetByteOrder();
672 
673     if (IsCPUFeatureAvailable(RegSet::avx)) {
674       // Assemble the YMM register content from the register halves.
675       for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
676            ++reg) {
677         if (!CopyXSTATEtoYMM(reg, byte_order)) {
678           error.SetErrorStringWithFormat(
679               "NativeRegisterContextLinux_x86_64::%s "
680               "CopyXSTATEtoYMM() failed for reg num "
681               "%" PRIu32,
682               __FUNCTION__, reg);
683           return error;
684         }
685       }
686     }
687 
688     if (IsCPUFeatureAvailable(RegSet::mpx)) {
689       for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc;
690            ++reg) {
691         if (!CopyXSTATEtoMPX(reg)) {
692           error.SetErrorStringWithFormat(
693               "NativeRegisterContextLinux_x86_64::%s "
694               "CopyXSTATEtoMPX() failed for reg num "
695               "%" PRIu32,
696               __FUNCTION__, reg);
697           return error;
698         }
699       }
700     }
701     // Copy the extended register state including the assembled ymm registers.
702     ::memcpy(dst, &m_fpr, sizeof(m_fpr));
703   } else {
704     assert(false && "how do we save the floating point registers?");
705     error.SetErrorString("unsure how to save the floating point registers");
706   }
707   /** The following code is specific to Linux x86 based architectures,
708    *  where the register orig_eax (32 bit)/orig_rax (64 bit) is set to
709    *  -1 to solve the bug 23659, such a setting prevents the automatic
710    *  decrement of the instruction pointer which was causing the SIGILL
711    *  exception.
712    * **/
713 
714   RegisterValue value((uint64_t)-1);
715   const RegisterInfo *reg_info =
716       GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax");
717   if (reg_info == nullptr)
718     reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax");
719 
720   if (reg_info != nullptr)
721     return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, value);
722 
723   return error;
724 }
725 
726 Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues(
727     const lldb::DataBufferSP &data_sp) {
728   Status error;
729 
730   if (!data_sp) {
731     error.SetErrorStringWithFormat(
732         "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided",
733         __FUNCTION__);
734     return error;
735   }
736 
737   if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
738     error.SetErrorStringWithFormatv(
739         "data_sp contained mismatched data size, expected {0}, actual {1}",
740         REG_CONTEXT_SIZE, data_sp->GetByteSize());
741     return error;
742   }
743 
744   uint8_t *src = data_sp->GetBytes();
745   if (src == nullptr) {
746     error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
747                                    "DataBuffer::GetBytes() returned a null "
748                                    "pointer",
749                                    __FUNCTION__);
750     return error;
751   }
752   ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize());
753 
754   error = WriteGPR();
755   if (error.Fail())
756     return error;
757 
758   src += GetRegisterInfoInterface().GetGPRSize();
759   if (m_xstate_type == XStateType::FXSAVE)
760     ::memcpy(&m_fpr.fxsave, src, sizeof(m_fpr.fxsave));
761   else if (m_xstate_type == XStateType::XSAVE)
762     ::memcpy(&m_fpr.xsave, src, sizeof(m_fpr.xsave));
763 
764   error = WriteFPR();
765   if (error.Fail())
766     return error;
767 
768   if (m_xstate_type == XStateType::XSAVE) {
769     lldb::ByteOrder byte_order = GetByteOrder();
770 
771     if (IsCPUFeatureAvailable(RegSet::avx)) {
772       // Parse the YMM register content from the register halves.
773       for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
774            ++reg) {
775         if (!CopyYMMtoXSTATE(reg, byte_order)) {
776           error.SetErrorStringWithFormat(
777               "NativeRegisterContextLinux_x86_64::%s "
778               "CopyYMMtoXSTATE() failed for reg num "
779               "%" PRIu32,
780               __FUNCTION__, reg);
781           return error;
782         }
783       }
784     }
785 
786     if (IsCPUFeatureAvailable(RegSet::mpx)) {
787       for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc;
788            ++reg) {
789         if (!CopyMPXtoXSTATE(reg)) {
790           error.SetErrorStringWithFormat(
791               "NativeRegisterContextLinux_x86_64::%s "
792               "CopyMPXtoXSTATE() failed for reg num "
793               "%" PRIu32,
794               __FUNCTION__, reg);
795           return error;
796         }
797       }
798     }
799   }
800 
801   return error;
802 }
803 
804 bool NativeRegisterContextLinux_x86_64::IsCPUFeatureAvailable(
805     RegSet feature_code) const {
806   if (m_xstate_type == XStateType::Invalid) {
807     if (const_cast<NativeRegisterContextLinux_x86_64 *>(this)->ReadFPR().Fail())
808       return false;
809   }
810   switch (feature_code) {
811   case RegSet::gpr:
812   case RegSet::fpu:
813     return true;
814   case RegSet::avx: // Check if CPU has AVX and if there is kernel support, by
815                     // reading in the XCR0 area of XSAVE.
816     if ((m_fpr.xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX)
817       return true;
818      break;
819   case RegSet::mpx: // Check if CPU has MPX and if there is kernel support, by
820                     // reading in the XCR0 area of XSAVE.
821     if ((m_fpr.xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX)
822       return true;
823     break;
824   }
825   return false;
826 }
827 
828 bool NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable(
829     uint32_t set_index) const {
830   uint32_t num_sets = k_num_register_sets - k_num_extended_register_sets;
831 
832   switch (static_cast<RegSet>(set_index)) {
833   case RegSet::gpr:
834   case RegSet::fpu:
835     return (set_index < num_sets);
836   case RegSet::avx:
837     return IsCPUFeatureAvailable(RegSet::avx);
838   case RegSet::mpx:
839     return IsCPUFeatureAvailable(RegSet::mpx);
840   }
841   return false;
842 }
843 
844 bool NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const {
845   // GPRs come first.
846   return reg_index <= m_reg_info.last_gpr;
847 }
848 
849 bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const {
850   return (m_reg_info.first_fpr <= reg_index &&
851           reg_index <= m_reg_info.last_fpr);
852 }
853 
854 Status NativeRegisterContextLinux_x86_64::WriteFPR() {
855   switch (m_xstate_type) {
856   case XStateType::FXSAVE:
857     return WriteRegisterSet(
858         &m_iovec, sizeof(m_fpr.fxsave),
859         fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture()));
860   case XStateType::XSAVE:
861     return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xsave), NT_X86_XSTATE);
862   default:
863     return Status("Unrecognized FPR type.");
864   }
865 }
866 
867 bool NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const {
868   if (!IsCPUFeatureAvailable(RegSet::avx))
869     return false;
870   return (m_reg_info.first_ymm <= reg_index &&
871           reg_index <= m_reg_info.last_ymm);
872 }
873 
874 bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM(
875     uint32_t reg_index, lldb::ByteOrder byte_order) {
876   if (!IsAVX(reg_index))
877     return false;
878 
879   if (byte_order == lldb::eByteOrderLittle) {
880     ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
881              m_fpr.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
882              sizeof(XMMReg));
883     ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes +
884                  sizeof(XMMReg),
885              m_fpr.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
886              sizeof(YMMHReg));
887     return true;
888   }
889 
890   if (byte_order == lldb::eByteOrderBig) {
891     ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes +
892                  sizeof(XMMReg),
893              m_fpr.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
894              sizeof(XMMReg));
895     ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
896              m_fpr.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
897              sizeof(YMMHReg));
898     return true;
899   }
900   return false; // unsupported or invalid byte order
901 }
902 
903 bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(
904     uint32_t reg, lldb::ByteOrder byte_order) {
905   if (!IsAVX(reg))
906     return false;
907 
908   if (byte_order == lldb::eByteOrderLittle) {
909     ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
910              m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg));
911     ::memcpy(m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
912              m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
913              sizeof(YMMHReg));
914     return true;
915   }
916 
917   if (byte_order == lldb::eByteOrderBig) {
918     ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
919              m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
920              sizeof(XMMReg));
921     ::memcpy(m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
922              m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg));
923     return true;
924   }
925   return false; // unsupported or invalid byte order
926 }
927 
928 void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() {
929   switch (m_xstate_type) {
930   case XStateType::FXSAVE:
931     return &m_fpr.fxsave;
932   case XStateType::XSAVE:
933     return &m_iovec;
934   default:
935     return nullptr;
936   }
937 }
938 
939 size_t NativeRegisterContextLinux_x86_64::GetFPRSize() {
940   switch (m_xstate_type) {
941   case XStateType::FXSAVE:
942     return sizeof(m_fpr.fxsave);
943   case XStateType::XSAVE:
944     return sizeof(m_iovec);
945   default:
946     return 0;
947   }
948 }
949 
950 Status NativeRegisterContextLinux_x86_64::ReadFPR() {
951   Status error;
952 
953   // Probe XSAVE and if it is not supported fall back to FXSAVE.
954   if (m_xstate_type != XStateType::FXSAVE) {
955     error = ReadRegisterSet(&m_iovec, sizeof(m_fpr.xsave), NT_X86_XSTATE);
956     if (!error.Fail()) {
957       m_xstate_type = XStateType::XSAVE;
958       return error;
959     }
960   }
961   error = ReadRegisterSet(
962       &m_iovec, sizeof(m_fpr.xsave),
963       fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture()));
964   if (!error.Fail()) {
965     m_xstate_type = XStateType::FXSAVE;
966     return error;
967   }
968   return Status("Unrecognized FPR type.");
969 }
970 
971 bool NativeRegisterContextLinux_x86_64::IsMPX(uint32_t reg_index) const {
972   if (!IsCPUFeatureAvailable(RegSet::mpx))
973     return false;
974   return (m_reg_info.first_mpxr <= reg_index &&
975           reg_index <= m_reg_info.last_mpxc);
976 }
977 
978 bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) {
979   if (!IsMPX(reg))
980     return false;
981 
982   if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
983     ::memcpy(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,
984              m_fpr.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
985              sizeof(MPXReg));
986   } else {
987     ::memcpy(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,
988              m_fpr.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
989              sizeof(MPXCsr));
990   }
991   return true;
992 }
993 
994 bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) {
995   if (!IsMPX(reg))
996     return false;
997 
998   if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
999     ::memcpy(m_fpr.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
1000              m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg));
1001   } else {
1002     ::memcpy(m_fpr.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
1003              m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr));
1004   }
1005   return true;
1006 }
1007 
1008 Status NativeRegisterContextLinux_x86_64::IsWatchpointHit(uint32_t wp_index,
1009                                                           bool &is_hit) {
1010   if (wp_index >= NumSupportedHardwareWatchpoints())
1011     return Status("Watchpoint index out of range");
1012 
1013   RegisterValue reg_value;
1014   Status error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
1015   if (error.Fail()) {
1016     is_hit = false;
1017     return error;
1018   }
1019 
1020   uint64_t status_bits = reg_value.GetAsUInt64();
1021 
1022   is_hit = status_bits & (1 << wp_index);
1023 
1024   return error;
1025 }
1026 
1027 Status NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex(
1028     uint32_t &wp_index, lldb::addr_t trap_addr) {
1029   uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
1030   for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
1031     bool is_hit;
1032     Status error = IsWatchpointHit(wp_index, is_hit);
1033     if (error.Fail()) {
1034       wp_index = LLDB_INVALID_INDEX32;
1035       return error;
1036     } else if (is_hit) {
1037       return error;
1038     }
1039   }
1040   wp_index = LLDB_INVALID_INDEX32;
1041   return Status();
1042 }
1043 
1044 Status NativeRegisterContextLinux_x86_64::IsWatchpointVacant(uint32_t wp_index,
1045                                                              bool &is_vacant) {
1046   if (wp_index >= NumSupportedHardwareWatchpoints())
1047     return Status("Watchpoint index out of range");
1048 
1049   RegisterValue reg_value;
1050   Status error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
1051   if (error.Fail()) {
1052     is_vacant = false;
1053     return error;
1054   }
1055 
1056   uint64_t control_bits = reg_value.GetAsUInt64();
1057 
1058   is_vacant = !(control_bits & (1 << (2 * wp_index)));
1059 
1060   return error;
1061 }
1062 
1063 Status NativeRegisterContextLinux_x86_64::SetHardwareWatchpointWithIndex(
1064     lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
1065 
1066   if (wp_index >= NumSupportedHardwareWatchpoints())
1067     return Status("Watchpoint index out of range");
1068 
1069   // Read only watchpoints aren't supported on x86_64. Fall back to read/write
1070   // waitchpoints instead.
1071   // TODO: Add logic to detect when a write happens and ignore that watchpoint
1072   // hit.
1073   if (watch_flags == 0x2)
1074     watch_flags = 0x3;
1075 
1076   if (watch_flags != 0x1 && watch_flags != 0x3)
1077     return Status("Invalid read/write bits for watchpoint");
1078 
1079   if (size != 1 && size != 2 && size != 4 && size != 8)
1080     return Status("Invalid size for watchpoint");
1081 
1082   bool is_vacant;
1083   Status error = IsWatchpointVacant(wp_index, is_vacant);
1084   if (error.Fail())
1085     return error;
1086   if (!is_vacant)
1087     return Status("Watchpoint index not vacant");
1088 
1089   RegisterValue reg_value;
1090   error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
1091   if (error.Fail())
1092     return error;
1093 
1094   // for watchpoints 0, 1, 2, or 3, respectively, set bits 1, 3, 5, or 7
1095   uint64_t enable_bit = 1 << (2 * wp_index);
1096 
1097   // set bits 16-17, 20-21, 24-25, or 28-29
1098   // with 0b01 for write, and 0b11 for read/write
1099   uint64_t rw_bits = watch_flags << (16 + 4 * wp_index);
1100 
1101   // set bits 18-19, 22-23, 26-27, or 30-31
1102   // with 0b00, 0b01, 0b10, or 0b11
1103   // for 1, 2, 8 (if supported), or 4 bytes, respectively
1104   uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
1105 
1106   uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
1107 
1108   uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
1109 
1110   control_bits |= enable_bit | rw_bits | size_bits;
1111 
1112   error = WriteRegisterRaw(m_reg_info.first_dr + wp_index, RegisterValue(addr));
1113   if (error.Fail())
1114     return error;
1115 
1116   error =
1117       WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits));
1118   if (error.Fail())
1119     return error;
1120 
1121   error.Clear();
1122   return error;
1123 }
1124 
1125 bool NativeRegisterContextLinux_x86_64::ClearHardwareWatchpoint(
1126     uint32_t wp_index) {
1127   if (wp_index >= NumSupportedHardwareWatchpoints())
1128     return false;
1129 
1130   RegisterValue reg_value;
1131 
1132   // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0, 1, 2, or 3 of
1133   // the debug status register (DR6)
1134   Status error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
1135   if (error.Fail())
1136     return false;
1137   uint64_t bit_mask = 1 << wp_index;
1138   uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
1139   error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits));
1140   if (error.Fail())
1141     return false;
1142 
1143   // for watchpoints 0, 1, 2, or 3, respectively, clear bits {0-1,16-19},
1144   // {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} of the debug control register
1145   // (DR7)
1146   error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
1147   if (error.Fail())
1148     return false;
1149   bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
1150   uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
1151   return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits))
1152       .Success();
1153 }
1154 
1155 Status NativeRegisterContextLinux_x86_64::ClearAllHardwareWatchpoints() {
1156   RegisterValue reg_value;
1157 
1158   // clear bits {0-4} of the debug status register (DR6)
1159   Status error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
1160   if (error.Fail())
1161     return error;
1162   uint64_t bit_mask = 0xF;
1163   uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
1164   error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits));
1165   if (error.Fail())
1166     return error;
1167 
1168   // clear bits {0-7,16-31} of the debug control register (DR7)
1169   error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
1170   if (error.Fail())
1171     return error;
1172   bit_mask = 0xFF | (0xFFFF << 16);
1173   uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
1174   return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits));
1175 }
1176 
1177 uint32_t NativeRegisterContextLinux_x86_64::SetHardwareWatchpoint(
1178     lldb::addr_t addr, size_t size, uint32_t watch_flags) {
1179   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
1180   const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
1181   for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) {
1182     bool is_vacant;
1183     Status error = IsWatchpointVacant(wp_index, is_vacant);
1184     if (is_vacant) {
1185       error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index);
1186       if (error.Success())
1187         return wp_index;
1188     }
1189     if (error.Fail() && log) {
1190       log->Printf("NativeRegisterContextLinux_x86_64::%s Error: %s",
1191                   __FUNCTION__, error.AsCString());
1192     }
1193   }
1194   return LLDB_INVALID_INDEX32;
1195 }
1196 
1197 lldb::addr_t
1198 NativeRegisterContextLinux_x86_64::GetWatchpointAddress(uint32_t wp_index) {
1199   if (wp_index >= NumSupportedHardwareWatchpoints())
1200     return LLDB_INVALID_ADDRESS;
1201   RegisterValue reg_value;
1202   if (ReadRegisterRaw(m_reg_info.first_dr + wp_index, reg_value).Fail())
1203     return LLDB_INVALID_ADDRESS;
1204   return reg_value.GetAsUInt64();
1205 }
1206 
1207 uint32_t NativeRegisterContextLinux_x86_64::NumSupportedHardwareWatchpoints() {
1208   // Available debug address registers: dr0, dr1, dr2, dr3
1209   return 4;
1210 }
1211 
1212 #endif // defined(__i386__) || defined(__x86_64__)
1213