xref: /llvm-project/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp (revision 0642cd768b80665585c8500bed2933a3b99123dc)
1 //===-- NativeRegisterContextLinux_x86_64.cpp -----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #if defined(__i386__) || defined(__x86_64__)
10 
11 #include "NativeRegisterContextLinux_x86_64.h"
12 #include "Plugins/Process/Linux/NativeThreadLinux.h"
13 #include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
14 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
15 #include "lldb/Host/HostInfo.h"
16 #include "lldb/Utility/DataBufferHeap.h"
17 #include "lldb/Utility/Log.h"
18 #include "lldb/Utility/RegisterValue.h"
19 #include "lldb/Utility/Status.h"
20 #include <cpuid.h>
21 #include <linux/elf.h>
22 #include <optional>
23 
24 // Newer toolchains define __get_cpuid_count in cpuid.h, but some
25 // older-but-still-supported ones (e.g. gcc 5.4.0) don't, so we
26 // define it locally here, following the definition in clang/lib/Headers.
27 static inline int get_cpuid_count(unsigned int __leaf,
28                                   unsigned int __subleaf,
29                                   unsigned int *__eax, unsigned int *__ebx,
30                                   unsigned int *__ecx, unsigned int *__edx)
31 {
32   unsigned int __max_leaf = __get_cpuid_max(__leaf & 0x80000000, nullptr);
33 
34   if (__max_leaf == 0 || __max_leaf < __leaf)
35     return 0;
36 
37   __cpuid_count(__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx);
38   return 1;
39 }
40 
41 using namespace lldb_private;
42 using namespace lldb_private::process_linux;
43 
44 // x86 32-bit general purpose registers.
45 static const uint32_t g_gpr_regnums_i386[] = {
46     lldb_eax_i386,      lldb_ebx_i386,    lldb_ecx_i386, lldb_edx_i386,
47     lldb_edi_i386,      lldb_esi_i386,    lldb_ebp_i386, lldb_esp_i386,
48     lldb_eip_i386,      lldb_eflags_i386, lldb_cs_i386,  lldb_fs_i386,
49     lldb_gs_i386,       lldb_ss_i386,     lldb_ds_i386,  lldb_es_i386,
50     lldb_ax_i386,       lldb_bx_i386,     lldb_cx_i386,  lldb_dx_i386,
51     lldb_di_i386,       lldb_si_i386,     lldb_bp_i386,  lldb_sp_i386,
52     lldb_ah_i386,       lldb_bh_i386,     lldb_ch_i386,  lldb_dh_i386,
53     lldb_al_i386,       lldb_bl_i386,     lldb_cl_i386,  lldb_dl_i386,
54     LLDB_INVALID_REGNUM // register sets need to end with this flag
55 };
56 static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) -
57                       1 ==
58                   k_num_gpr_registers_i386,
59               "g_gpr_regnums_i386 has wrong number of register infos");
60 
61 // x86 32-bit floating point registers.
62 static const uint32_t g_fpu_regnums_i386[] = {
63     lldb_fctrl_i386,    lldb_fstat_i386,     lldb_ftag_i386,  lldb_fop_i386,
64     lldb_fiseg_i386,    lldb_fioff_i386,     lldb_foseg_i386, lldb_fooff_i386,
65     lldb_mxcsr_i386,    lldb_mxcsrmask_i386, lldb_st0_i386,   lldb_st1_i386,
66     lldb_st2_i386,      lldb_st3_i386,       lldb_st4_i386,   lldb_st5_i386,
67     lldb_st6_i386,      lldb_st7_i386,       lldb_mm0_i386,   lldb_mm1_i386,
68     lldb_mm2_i386,      lldb_mm3_i386,       lldb_mm4_i386,   lldb_mm5_i386,
69     lldb_mm6_i386,      lldb_mm7_i386,       lldb_xmm0_i386,  lldb_xmm1_i386,
70     lldb_xmm2_i386,     lldb_xmm3_i386,      lldb_xmm4_i386,  lldb_xmm5_i386,
71     lldb_xmm6_i386,     lldb_xmm7_i386,
72     LLDB_INVALID_REGNUM // register sets need to end with this flag
73 };
74 static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) -
75                       1 ==
76                   k_num_fpr_registers_i386,
77               "g_fpu_regnums_i386 has wrong number of register infos");
78 
79 // x86 32-bit AVX registers.
80 static const uint32_t g_avx_regnums_i386[] = {
81     lldb_ymm0_i386,     lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386,
82     lldb_ymm4_i386,     lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386,
83     LLDB_INVALID_REGNUM // register sets need to end with this flag
84 };
85 static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) -
86                       1 ==
87                   k_num_avx_registers_i386,
88               " g_avx_regnums_i386 has wrong number of register infos");
89 
90 // x64 32-bit MPX registers.
91 static const uint32_t g_mpx_regnums_i386[] = {
92     lldb_bnd0_i386,     lldb_bnd1_i386, lldb_bnd2_i386, lldb_bnd3_i386,
93     lldb_bndcfgu_i386,  lldb_bndstatus_i386,
94     LLDB_INVALID_REGNUM // register sets need to end with this flag
95 };
96 static_assert((sizeof(g_mpx_regnums_i386) / sizeof(g_mpx_regnums_i386[0])) -
97                       1 ==
98                   k_num_mpx_registers_i386,
99               "g_mpx_regnums_x86_64 has wrong number of register infos");
100 
101 // x86 64-bit general purpose registers.
102 static const uint32_t g_gpr_regnums_x86_64[] = {
103     x86_64_with_base::lldb_rax,    x86_64_with_base::lldb_rbx,    x86_64_with_base::lldb_rcx, x86_64_with_base::lldb_rdx,
104     x86_64_with_base::lldb_rdi,    x86_64_with_base::lldb_rsi,    x86_64_with_base::lldb_rbp, x86_64_with_base::lldb_rsp,
105     x86_64_with_base::lldb_r8,     x86_64_with_base::lldb_r9,     x86_64_with_base::lldb_r10, x86_64_with_base::lldb_r11,
106     x86_64_with_base::lldb_r12,    x86_64_with_base::lldb_r13,    x86_64_with_base::lldb_r14, x86_64_with_base::lldb_r15,
107     x86_64_with_base::lldb_rip,    x86_64_with_base::lldb_rflags, x86_64_with_base::lldb_cs,  x86_64_with_base::lldb_fs,
108     x86_64_with_base::lldb_gs,     x86_64_with_base::lldb_ss,     x86_64_with_base::lldb_fs_base, x86_64_with_base::lldb_gs_base,
109     x86_64_with_base::lldb_ds,  x86_64_with_base::lldb_es,
110     x86_64_with_base::lldb_eax,    x86_64_with_base::lldb_ebx,    x86_64_with_base::lldb_ecx, x86_64_with_base::lldb_edx,
111     x86_64_with_base::lldb_edi,    x86_64_with_base::lldb_esi,    x86_64_with_base::lldb_ebp, x86_64_with_base::lldb_esp,
112     x86_64_with_base::lldb_r8d,  // Low 32 bits or r8
113     x86_64_with_base::lldb_r9d,  // Low 32 bits or r9
114     x86_64_with_base::lldb_r10d, // Low 32 bits or r10
115     x86_64_with_base::lldb_r11d, // Low 32 bits or r11
116     x86_64_with_base::lldb_r12d, // Low 32 bits or r12
117     x86_64_with_base::lldb_r13d, // Low 32 bits or r13
118     x86_64_with_base::lldb_r14d, // Low 32 bits or r14
119     x86_64_with_base::lldb_r15d, // Low 32 bits or r15
120     x86_64_with_base::lldb_ax,     x86_64_with_base::lldb_bx,     x86_64_with_base::lldb_cx,  x86_64_with_base::lldb_dx,
121     x86_64_with_base::lldb_di,     x86_64_with_base::lldb_si,     x86_64_with_base::lldb_bp,  x86_64_with_base::lldb_sp,
122     x86_64_with_base::lldb_r8w,  // Low 16 bits or r8
123     x86_64_with_base::lldb_r9w,  // Low 16 bits or r9
124     x86_64_with_base::lldb_r10w, // Low 16 bits or r10
125     x86_64_with_base::lldb_r11w, // Low 16 bits or r11
126     x86_64_with_base::lldb_r12w, // Low 16 bits or r12
127     x86_64_with_base::lldb_r13w, // Low 16 bits or r13
128     x86_64_with_base::lldb_r14w, // Low 16 bits or r14
129     x86_64_with_base::lldb_r15w, // Low 16 bits or r15
130     x86_64_with_base::lldb_ah,     x86_64_with_base::lldb_bh,     x86_64_with_base::lldb_ch,  x86_64_with_base::lldb_dh,
131     x86_64_with_base::lldb_al,     x86_64_with_base::lldb_bl,     x86_64_with_base::lldb_cl,  x86_64_with_base::lldb_dl,
132     x86_64_with_base::lldb_dil,    x86_64_with_base::lldb_sil,    x86_64_with_base::lldb_bpl, x86_64_with_base::lldb_spl,
133     x86_64_with_base::lldb_r8l,    // Low 8 bits or r8
134     x86_64_with_base::lldb_r9l,    // Low 8 bits or r9
135     x86_64_with_base::lldb_r10l,   // Low 8 bits or r10
136     x86_64_with_base::lldb_r11l,   // Low 8 bits or r11
137     x86_64_with_base::lldb_r12l,   // Low 8 bits or r12
138     x86_64_with_base::lldb_r13l,   // Low 8 bits or r13
139     x86_64_with_base::lldb_r14l,   // Low 8 bits or r14
140     x86_64_with_base::lldb_r15l,   // Low 8 bits or r15
141     LLDB_INVALID_REGNUM // register sets need to end with this flag
142 };
143 static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
144                       1 ==
145                   x86_64_with_base::k_num_gpr_registers,
146               "g_gpr_regnums_x86_64 has wrong number of register infos");
147 
148 // x86 64-bit floating point registers.
149 static const uint32_t g_fpu_regnums_x86_64[] = {
150     x86_64_with_base::lldb_fctrl,  x86_64_with_base::lldb_fstat, x86_64_with_base::lldb_ftag,
151     x86_64_with_base::lldb_fop,    x86_64_with_base::lldb_fiseg, x86_64_with_base::lldb_fioff,
152     x86_64_with_base::lldb_fip,    x86_64_with_base::lldb_foseg, x86_64_with_base::lldb_fooff,
153     x86_64_with_base::lldb_fdp,    x86_64_with_base::lldb_mxcsr, x86_64_with_base::lldb_mxcsrmask,
154     x86_64_with_base::lldb_st0,    x86_64_with_base::lldb_st1,   x86_64_with_base::lldb_st2,
155     x86_64_with_base::lldb_st3,    x86_64_with_base::lldb_st4,   x86_64_with_base::lldb_st5,
156     x86_64_with_base::lldb_st6,    x86_64_with_base::lldb_st7,   x86_64_with_base::lldb_mm0,
157     x86_64_with_base::lldb_mm1,    x86_64_with_base::lldb_mm2,   x86_64_with_base::lldb_mm3,
158     x86_64_with_base::lldb_mm4,    x86_64_with_base::lldb_mm5,   x86_64_with_base::lldb_mm6,
159     x86_64_with_base::lldb_mm7,    x86_64_with_base::lldb_xmm0,  x86_64_with_base::lldb_xmm1,
160     x86_64_with_base::lldb_xmm2,   x86_64_with_base::lldb_xmm3,  x86_64_with_base::lldb_xmm4,
161     x86_64_with_base::lldb_xmm5,   x86_64_with_base::lldb_xmm6,  x86_64_with_base::lldb_xmm7,
162     x86_64_with_base::lldb_xmm8,   x86_64_with_base::lldb_xmm9,  x86_64_with_base::lldb_xmm10,
163     x86_64_with_base::lldb_xmm11,  x86_64_with_base::lldb_xmm12, x86_64_with_base::lldb_xmm13,
164     x86_64_with_base::lldb_xmm14,  x86_64_with_base::lldb_xmm15,
165     LLDB_INVALID_REGNUM // register sets need to end with this flag
166 };
167 static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
168                       1 ==
169                   x86_64_with_base::k_num_fpr_registers,
170               "g_fpu_regnums_x86_64 has wrong number of register infos");
171 
172 // x86 64-bit AVX registers.
173 static const uint32_t g_avx_regnums_x86_64[] = {
174     x86_64_with_base::lldb_ymm0,   x86_64_with_base::lldb_ymm1,  x86_64_with_base::lldb_ymm2,  x86_64_with_base::lldb_ymm3,
175     x86_64_with_base::lldb_ymm4,   x86_64_with_base::lldb_ymm5,  x86_64_with_base::lldb_ymm6,  x86_64_with_base::lldb_ymm7,
176     x86_64_with_base::lldb_ymm8,   x86_64_with_base::lldb_ymm9,  x86_64_with_base::lldb_ymm10, x86_64_with_base::lldb_ymm11,
177     x86_64_with_base::lldb_ymm12,  x86_64_with_base::lldb_ymm13, x86_64_with_base::lldb_ymm14, x86_64_with_base::lldb_ymm15,
178     LLDB_INVALID_REGNUM // register sets need to end with this flag
179 };
180 static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) -
181                       1 ==
182                   x86_64_with_base::k_num_avx_registers,
183               "g_avx_regnums_x86_64 has wrong number of register infos");
184 
185 // x86 64-bit MPX registers.
186 static const uint32_t g_mpx_regnums_x86_64[] = {
187     x86_64_with_base::lldb_bnd0,    x86_64_with_base::lldb_bnd1,    x86_64_with_base::lldb_bnd2,
188     x86_64_with_base::lldb_bnd3,    x86_64_with_base::lldb_bndcfgu, x86_64_with_base::lldb_bndstatus,
189     LLDB_INVALID_REGNUM // register sets need to end with this flag
190 };
191 static_assert((sizeof(g_mpx_regnums_x86_64) / sizeof(g_mpx_regnums_x86_64[0])) -
192                       1 ==
193                   x86_64_with_base::k_num_mpx_registers,
194               "g_mpx_regnums_x86_64 has wrong number of register infos");
195 
196 // Number of register sets provided by this context.
197 constexpr unsigned k_num_extended_register_sets = 2, k_num_register_sets = 4;
198 
199 // Register sets for x86 32-bit.
200 static const RegisterSet g_reg_sets_i386[k_num_register_sets] = {
201     {"General Purpose Registers", "gpr", k_num_gpr_registers_i386,
202      g_gpr_regnums_i386},
203     {"Floating Point Registers", "fpu", k_num_fpr_registers_i386,
204      g_fpu_regnums_i386},
205     {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386,
206      g_avx_regnums_i386},
207     { "Memory Protection Extensions", "mpx", k_num_mpx_registers_i386,
208      g_mpx_regnums_i386}};
209 
210 // Register sets for x86 64-bit.
211 static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
212     {"General Purpose Registers", "gpr", x86_64_with_base::k_num_gpr_registers,
213      g_gpr_regnums_x86_64},
214     {"Floating Point Registers", "fpu", x86_64_with_base::k_num_fpr_registers,
215      g_fpu_regnums_x86_64},
216     {"Advanced Vector Extensions", "avx", x86_64_with_base::k_num_avx_registers,
217      g_avx_regnums_x86_64},
218     { "Memory Protection Extensions", "mpx", x86_64_with_base::k_num_mpx_registers,
219      g_mpx_regnums_x86_64}};
220 
221 #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR))
222 
223 // Required ptrace defines.
224 
225 // Support ptrace extensions even when compiled without required kernel support
226 #ifndef NT_X86_XSTATE
227 #define NT_X86_XSTATE 0x202
228 #endif
229 #ifndef NT_PRXFPREG
230 #define NT_PRXFPREG 0x46e62b7f
231 #endif
232 
233 // On x86_64 NT_PRFPREG is used to access the FXSAVE area. On i386, we need to
234 // use NT_PRXFPREG.
235 static inline unsigned int fxsr_regset(const ArchSpec &arch) {
236   return arch.GetAddressByteSize() == 8 ? NT_PRFPREG : NT_PRXFPREG;
237 }
238 
239 // Required MPX define.
240 
241 // Support MPX extensions also if compiled with compiler without MPX support.
242 #ifndef bit_MPX
243 #define bit_MPX 0x4000
244 #endif
245 
246 // XCR0 extended register sets masks.
247 #define mask_XSTATE_AVX (1ULL << 2)
248 #define mask_XSTATE_BNDREGS (1ULL << 3)
249 #define mask_XSTATE_BNDCFG (1ULL << 4)
250 #define mask_XSTATE_MPX (mask_XSTATE_BNDREGS | mask_XSTATE_BNDCFG)
251 
252 std::unique_ptr<NativeRegisterContextLinux>
253 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
254     const ArchSpec &target_arch, NativeThreadLinux &native_thread) {
255   return std::unique_ptr<NativeRegisterContextLinux>(
256       new NativeRegisterContextLinux_x86_64(target_arch, native_thread));
257 }
258 
259 llvm::Expected<ArchSpec>
260 NativeRegisterContextLinux::DetermineArchitecture(lldb::tid_t tid) {
261   return DetermineArchitectureViaGPR(
262       tid, RegisterContextLinux_x86_64::GetGPRSizeStatic());
263 }
264 
265 // NativeRegisterContextLinux_x86_64 members.
266 
267 static std::unique_ptr<RegisterContextLinux_x86>
268 CreateRegisterInfoInterface(const ArchSpec &target_arch) {
269   if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
270     // 32-bit hosts run with a RegisterContextLinux_i386 context.
271     return std::make_unique<RegisterContextLinux_i386>(target_arch);
272   } else {
273     assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
274            "Register setting path assumes this is a 64-bit host");
275     // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the
276     // x86_64 register context.
277     return std::make_unique<RegisterContextLinux_x86_64>(target_arch);
278   }
279 }
280 
281 // Return the size of the XSTATE area supported on this cpu. It is necessary to
282 // allocate the full size of the area even if we do not use/recognise all of it
283 // because ptrace(PTRACE_SETREGSET, NT_X86_XSTATE) will refuse to write to it if
284 // we do not pass it a buffer of sufficient size. The size is always at least
285 // sizeof(FPR) so that the allocated buffer can be safely cast to FPR*.
286 static std::size_t GetXSTATESize() {
287   unsigned int eax, ebx, ecx, edx;
288   // First check whether the XSTATE are is supported at all.
289   if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx) || !(ecx & bit_XSAVE))
290     return sizeof(FPR);
291 
292   // Then fetch the maximum size of the area.
293   if (!get_cpuid_count(0x0d, 0, &eax, &ebx, &ecx, &edx))
294     return sizeof(FPR);
295   return std::max<std::size_t>(ecx, sizeof(FPR));
296 }
297 
298 NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
299     const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
300     : NativeRegisterContextRegisterInfo(
301           native_thread, CreateRegisterInfoInterface(target_arch).release()),
302       NativeRegisterContextLinux(native_thread),
303       NativeRegisterContextDBReg_x86(native_thread),
304       m_xstate_type(XStateType::Invalid), m_ymm_set(), m_mpx_set(),
305       m_reg_info(), m_gpr_x86_64() {
306   // Set up data about ranges of valid registers.
307   switch (target_arch.GetMachine()) {
308   case llvm::Triple::x86:
309     m_reg_info.num_registers = k_num_registers_i386;
310     m_reg_info.num_gpr_registers = k_num_gpr_registers_i386;
311     m_reg_info.num_fpr_registers = k_num_fpr_registers_i386;
312     m_reg_info.num_avx_registers = k_num_avx_registers_i386;
313     m_reg_info.num_mpx_registers = k_num_mpx_registers_i386;
314     m_reg_info.last_gpr = k_last_gpr_i386;
315     m_reg_info.first_fpr = k_first_fpr_i386;
316     m_reg_info.last_fpr = k_last_fpr_i386;
317     m_reg_info.first_st = lldb_st0_i386;
318     m_reg_info.last_st = lldb_st7_i386;
319     m_reg_info.first_mm = lldb_mm0_i386;
320     m_reg_info.last_mm = lldb_mm7_i386;
321     m_reg_info.first_xmm = lldb_xmm0_i386;
322     m_reg_info.last_xmm = lldb_xmm7_i386;
323     m_reg_info.first_ymm = lldb_ymm0_i386;
324     m_reg_info.last_ymm = lldb_ymm7_i386;
325     m_reg_info.first_mpxr = lldb_bnd0_i386;
326     m_reg_info.last_mpxr = lldb_bnd3_i386;
327     m_reg_info.first_mpxc = lldb_bndcfgu_i386;
328     m_reg_info.last_mpxc = lldb_bndstatus_i386;
329     m_reg_info.first_dr = lldb_dr0_i386;
330     m_reg_info.last_dr = lldb_dr7_i386;
331     m_reg_info.gpr_flags = lldb_eflags_i386;
332     break;
333   case llvm::Triple::x86_64:
334     m_reg_info.num_registers = x86_64_with_base::k_num_registers;
335     m_reg_info.num_gpr_registers = x86_64_with_base::k_num_gpr_registers;
336     m_reg_info.num_fpr_registers = x86_64_with_base::k_num_fpr_registers;
337     m_reg_info.num_avx_registers = x86_64_with_base::k_num_avx_registers;
338     m_reg_info.num_mpx_registers = x86_64_with_base::k_num_mpx_registers;
339     m_reg_info.last_gpr = x86_64_with_base::k_last_gpr;
340     m_reg_info.first_fpr = x86_64_with_base::k_first_fpr;
341     m_reg_info.last_fpr = x86_64_with_base::k_last_fpr;
342     m_reg_info.first_st = x86_64_with_base::lldb_st0;
343     m_reg_info.last_st = x86_64_with_base::lldb_st7;
344     m_reg_info.first_mm = x86_64_with_base::lldb_mm0;
345     m_reg_info.last_mm = x86_64_with_base::lldb_mm7;
346     m_reg_info.first_xmm = x86_64_with_base::lldb_xmm0;
347     m_reg_info.last_xmm = x86_64_with_base::lldb_xmm15;
348     m_reg_info.first_ymm = x86_64_with_base::lldb_ymm0;
349     m_reg_info.last_ymm = x86_64_with_base::lldb_ymm15;
350     m_reg_info.first_mpxr = x86_64_with_base::lldb_bnd0;
351     m_reg_info.last_mpxr = x86_64_with_base::lldb_bnd3;
352     m_reg_info.first_mpxc = x86_64_with_base::lldb_bndcfgu;
353     m_reg_info.last_mpxc = x86_64_with_base::lldb_bndstatus;
354     m_reg_info.first_dr = x86_64_with_base::lldb_dr0;
355     m_reg_info.last_dr = x86_64_with_base::lldb_dr7;
356     m_reg_info.gpr_flags = x86_64_with_base::lldb_rflags;
357     break;
358   default:
359     assert(false && "Unhandled target architecture.");
360     break;
361   }
362 
363   std::size_t xstate_size = GetXSTATESize();
364   m_xstate.reset(static_cast<FPR *>(std::malloc(xstate_size)));
365   m_iovec.iov_base = m_xstate.get();
366   m_iovec.iov_len = xstate_size;
367 
368   // Clear out the FPR state.
369   ::memset(m_xstate.get(), 0, xstate_size);
370 
371   // Store byte offset of fctrl (i.e. first register of FPR)
372   const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl");
373   m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;
374 }
375 
376 // CONSIDER after local and llgs debugging are merged, register set support can
377 // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual.
378 uint32_t NativeRegisterContextLinux_x86_64::GetRegisterSetCount() const {
379   uint32_t sets = 0;
380   for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
381     if (IsRegisterSetAvailable(set_index))
382       ++sets;
383   }
384 
385   return sets;
386 }
387 
388 uint32_t NativeRegisterContextLinux_x86_64::GetUserRegisterCount() const {
389   uint32_t count = 0;
390   for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
391     const RegisterSet *set = GetRegisterSet(set_index);
392     if (set)
393       count += set->num_registers;
394   }
395   return count;
396 }
397 
398 const RegisterSet *
399 NativeRegisterContextLinux_x86_64::GetRegisterSet(uint32_t set_index) const {
400   if (!IsRegisterSetAvailable(set_index))
401     return nullptr;
402 
403   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
404   case llvm::Triple::x86:
405     return &g_reg_sets_i386[set_index];
406   case llvm::Triple::x86_64:
407     return &g_reg_sets_x86_64[set_index];
408   default:
409     assert(false && "Unhandled target architecture.");
410     return nullptr;
411   }
412 
413   return nullptr;
414 }
415 
416 Status
417 NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
418                                                 RegisterValue &reg_value) {
419   Status error;
420 
421   if (!reg_info) {
422     error = Status::FromErrorString("reg_info NULL");
423     return error;
424   }
425 
426   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
427   if (reg == LLDB_INVALID_REGNUM) {
428     // This is likely an internal register for lldb use only and should not be
429     // directly queried.
430     error = Status::FromErrorStringWithFormat(
431         "register \"%s\" is an internal-only lldb "
432         "register, cannot read directly",
433         reg_info->name);
434     return error;
435   }
436 
437   if (IsFPR(reg) || IsAVX(reg) || IsMPX(reg)) {
438     error = ReadFPR();
439     if (error.Fail())
440       return error;
441   } else {
442     uint32_t full_reg = reg;
443     bool is_subreg = reg_info->invalidate_regs &&
444                      (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
445 
446     if (is_subreg) {
447       // Read the full aligned 64-bit register.
448       full_reg = reg_info->invalidate_regs[0];
449     }
450 
451     error = ReadRegisterRaw(full_reg, reg_value);
452 
453     if (error.Success()) {
454       // If our read was not aligned (for ah,bh,ch,dh), shift our returned
455       // value one byte to the right.
456       if (is_subreg && (reg_info->byte_offset & 0x1))
457         reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
458 
459       // If our return byte size was greater than the return value reg size,
460       // then use the type specified by reg_info rather than the uint64_t
461       // default
462       if (reg_value.GetByteSize() > reg_info->byte_size)
463         reg_value.SetType(*reg_info);
464     }
465     return error;
466   }
467 
468   if (reg_info->encoding == lldb::eEncodingVector) {
469     lldb::ByteOrder byte_order = GetByteOrder();
470 
471     if (byte_order != lldb::eByteOrderInvalid) {
472       if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
473         reg_value.SetBytes(
474             m_xstate->fxsave.stmm[reg - m_reg_info.first_st].bytes,
475             reg_info->byte_size, byte_order);
476       if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
477         reg_value.SetBytes(
478             m_xstate->fxsave.stmm[reg - m_reg_info.first_mm].bytes,
479             reg_info->byte_size, byte_order);
480       if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
481         reg_value.SetBytes(
482             m_xstate->fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
483             reg_info->byte_size, byte_order);
484       if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
485         // Concatenate ymm using the register halves in xmm.bytes and
486         // ymmh.bytes
487         if (CopyXSTATEtoYMM(reg, byte_order))
488           reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
489                              reg_info->byte_size, byte_order);
490         else {
491           error = Status::FromErrorString("failed to copy ymm register value");
492           return error;
493         }
494       }
495       if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
496         if (CopyXSTATEtoMPX(reg))
497           reg_value.SetBytes(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,
498                              reg_info->byte_size, byte_order);
499         else {
500           error = Status::FromErrorString("failed to copy mpx register value");
501           return error;
502         }
503       }
504       if (reg >= m_reg_info.first_mpxc && reg <= m_reg_info.last_mpxc) {
505         if (CopyXSTATEtoMPX(reg))
506           reg_value.SetBytes(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,
507                              reg_info->byte_size, byte_order);
508         else {
509           error = Status::FromErrorString("failed to copy mpx register value");
510           return error;
511         }
512       }
513 
514       if (reg_value.GetType() != RegisterValue::eTypeBytes)
515         error = Status::FromErrorString(
516             "write failed - type was expected to be RegisterValue::eTypeBytes");
517 
518       return error;
519     }
520 
521     error = Status::FromErrorString("byte order is invalid");
522     return error;
523   }
524 
525   // Get pointer to m_xstate->fxsave variable and set the data from it.
526 
527   // Byte offsets of all registers are calculated wrt 'UserArea' structure.
528   // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)}
529   // and stores them in 'm_fpr' (of type FPR structure). To extract values of
530   // fpu registers, m_fpr should be read at byte offsets calculated wrt to FPR
531   // structure.
532 
533   // Since, FPR structure is also one of the member of UserArea structure.
534   // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
535   // byte_offset(fctrl wrt UserArea)
536   assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(FPR));
537   uint8_t *src = (uint8_t *)m_xstate.get() + reg_info->byte_offset -
538                  m_fctrl_offset_in_userarea;
539 
540   if (src == reinterpret_cast<uint8_t *>(&m_xstate->fxsave.ftag)) {
541     reg_value.SetUInt16(AbridgedToFullTagWord(
542         m_xstate->fxsave.ftag, m_xstate->fxsave.fstat, m_xstate->fxsave.stmm));
543     return error;
544   }
545 
546   switch (reg_info->byte_size) {
547   case 1:
548     reg_value.SetUInt8(*(uint8_t *)src);
549     break;
550   case 2:
551     reg_value.SetUInt16(*(uint16_t *)src);
552     break;
553   case 4:
554     reg_value.SetUInt32(*(uint32_t *)src);
555     break;
556   case 8:
557     reg_value.SetUInt64(*(uint64_t *)src);
558     break;
559   default:
560     assert(false && "Unhandled data size.");
561     error = Status::FromErrorStringWithFormat("unhandled byte size: %" PRIu32,
562                                               reg_info->byte_size);
563     break;
564   }
565 
566   return error;
567 }
568 
569 void NativeRegisterContextLinux_x86_64::UpdateXSTATEforWrite(
570     uint32_t reg_index) {
571   XSAVE_HDR::XFeature &xstate_bv = m_xstate->xsave.header.xstate_bv;
572   if (IsFPR(reg_index)) {
573     // IsFPR considers both %st and %xmm registers as floating point, but these
574     // map to two features. Set both flags, just in case.
575     xstate_bv |= XSAVE_HDR::XFeature::FP | XSAVE_HDR::XFeature::SSE;
576   } else if (IsAVX(reg_index)) {
577     // Lower bytes of some %ymm registers are shared with %xmm registers.
578     xstate_bv |= XSAVE_HDR::XFeature::YMM | XSAVE_HDR::XFeature::SSE;
579   } else if (IsMPX(reg_index)) {
580     // MPX registers map to two XSAVE features.
581     xstate_bv |= XSAVE_HDR::XFeature::BNDREGS | XSAVE_HDR::XFeature::BNDCSR;
582   }
583 }
584 
585 Status NativeRegisterContextLinux_x86_64::WriteRegister(
586     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
587   assert(reg_info && "reg_info is null");
588 
589   const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
590   if (reg_index == LLDB_INVALID_REGNUM)
591     return Status::FromErrorStringWithFormat(
592         "no lldb regnum for %s",
593         reg_info && reg_info->name ? reg_info->name : "<unknown register>");
594 
595   UpdateXSTATEforWrite(reg_index);
596 
597   if (IsGPR(reg_index) || IsDR(reg_index))
598     return WriteRegisterRaw(reg_index, reg_value);
599 
600   if (IsFPR(reg_index) || IsAVX(reg_index) || IsMPX(reg_index)) {
601     if (reg_info->encoding == lldb::eEncodingVector) {
602       if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st)
603         ::memcpy(m_xstate->fxsave.stmm[reg_index - m_reg_info.first_st].bytes,
604                  reg_value.GetBytes(), reg_value.GetByteSize());
605 
606       if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm)
607         ::memcpy(m_xstate->fxsave.stmm[reg_index - m_reg_info.first_mm].bytes,
608                  reg_value.GetBytes(), reg_value.GetByteSize());
609 
610       if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm)
611         ::memcpy(m_xstate->fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes,
612                  reg_value.GetBytes(), reg_value.GetByteSize());
613 
614       if (reg_index >= m_reg_info.first_ymm &&
615           reg_index <= m_reg_info.last_ymm) {
616         // Store ymm register content, and split into the register halves in
617         // xmm.bytes and ymmh.bytes
618         ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
619                  reg_value.GetBytes(), reg_value.GetByteSize());
620         if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
621           return Status::FromErrorString("CopyYMMtoXSTATE() failed");
622       }
623 
624       if (reg_index >= m_reg_info.first_mpxr &&
625           reg_index <= m_reg_info.last_mpxr) {
626         ::memcpy(m_mpx_set.mpxr[reg_index - m_reg_info.first_mpxr].bytes,
627                  reg_value.GetBytes(), reg_value.GetByteSize());
628         if (!CopyMPXtoXSTATE(reg_index))
629           return Status::FromErrorString("CopyMPXtoXSTATE() failed");
630       }
631 
632       if (reg_index >= m_reg_info.first_mpxc &&
633           reg_index <= m_reg_info.last_mpxc) {
634         ::memcpy(m_mpx_set.mpxc[reg_index - m_reg_info.first_mpxc].bytes,
635                  reg_value.GetBytes(), reg_value.GetByteSize());
636         if (!CopyMPXtoXSTATE(reg_index))
637           return Status::FromErrorString("CopyMPXtoXSTATE() failed");
638       }
639     } else {
640       // Get pointer to m_xstate->fxsave variable and set the data to it.
641 
642       // Byte offsets of all registers are calculated wrt 'UserArea' structure.
643       // However, WriteFPR() takes m_fpr (of type FPR structure) and writes
644       // only fpu registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu
645       // registers should be written in m_fpr at byte offsets calculated wrt
646       // FPR structure.
647 
648       // Since, FPR structure is also one of the member of UserArea structure.
649       // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
650       // byte_offset(fctrl wrt UserArea)
651       assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) <
652              sizeof(FPR));
653       uint8_t *dst = (uint8_t *)m_xstate.get() + reg_info->byte_offset -
654                      m_fctrl_offset_in_userarea;
655 
656       if (dst == reinterpret_cast<uint8_t *>(&m_xstate->fxsave.ftag))
657         m_xstate->fxsave.ftag = FullToAbridgedTagWord(reg_value.GetAsUInt16());
658       else {
659         switch (reg_info->byte_size) {
660         case 1:
661           *(uint8_t *)dst = reg_value.GetAsUInt8();
662           break;
663         case 2:
664           *(uint16_t *)dst = reg_value.GetAsUInt16();
665           break;
666         case 4:
667           *(uint32_t *)dst = reg_value.GetAsUInt32();
668           break;
669         case 8:
670           *(uint64_t *)dst = reg_value.GetAsUInt64();
671           break;
672         default:
673           assert(false && "Unhandled data size.");
674           return Status::FromErrorStringWithFormat(
675               "unhandled register data size %" PRIu32, reg_info->byte_size);
676         }
677       }
678     }
679 
680     Status error = WriteFPR();
681     if (error.Fail())
682       return error;
683 
684     if (IsAVX(reg_index)) {
685       if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
686         return Status::FromErrorString("CopyYMMtoXSTATE() failed");
687     }
688 
689     if (IsMPX(reg_index)) {
690       if (!CopyMPXtoXSTATE(reg_index))
691         return Status::FromErrorString("CopyMPXtoXSTATE() failed");
692     }
693     return Status();
694   }
695   return Status::FromErrorString(
696       "failed - register wasn't recognized to be a GPR or an FPR, "
697       "write strategy unknown");
698 }
699 
700 Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues(
701     lldb::WritableDataBufferSP &data_sp) {
702   Status error;
703 
704   data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
705   error = ReadGPR();
706   if (error.Fail())
707     return error;
708 
709   error = ReadFPR();
710   if (error.Fail())
711     return error;
712 
713   uint8_t *dst = data_sp->GetBytes();
714   ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());
715   dst += GetRegisterInfoInterface().GetGPRSize();
716   if (m_xstate_type == XStateType::FXSAVE)
717     ::memcpy(dst, &m_xstate->fxsave, sizeof(m_xstate->fxsave));
718   else if (m_xstate_type == XStateType::XSAVE) {
719     lldb::ByteOrder byte_order = GetByteOrder();
720 
721     if (IsCPUFeatureAvailable(RegSet::avx)) {
722       // Assemble the YMM register content from the register halves.
723       for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
724            ++reg) {
725         if (!CopyXSTATEtoYMM(reg, byte_order)) {
726           error = Status::FromErrorStringWithFormat(
727               "NativeRegisterContextLinux_x86_64::%s "
728               "CopyXSTATEtoYMM() failed for reg num "
729               "%" PRIu32,
730               __FUNCTION__, reg);
731           return error;
732         }
733       }
734     }
735 
736     if (IsCPUFeatureAvailable(RegSet::mpx)) {
737       for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc;
738            ++reg) {
739         if (!CopyXSTATEtoMPX(reg)) {
740           error = Status::FromErrorStringWithFormat(
741               "NativeRegisterContextLinux_x86_64::%s "
742               "CopyXSTATEtoMPX() failed for reg num "
743               "%" PRIu32,
744               __FUNCTION__, reg);
745           return error;
746         }
747       }
748     }
749     // Copy the extended register state including the assembled ymm registers.
750     ::memcpy(dst, m_xstate.get(), sizeof(FPR));
751   } else {
752     assert(false && "how do we save the floating point registers?");
753     error = Status::FromErrorString(
754         "unsure how to save the floating point registers");
755   }
756   /** The following code is specific to Linux x86 based architectures,
757    *  where the register orig_eax (32 bit)/orig_rax (64 bit) is set to
758    *  -1 to solve the bug 23659, such a setting prevents the automatic
759    *  decrement of the instruction pointer which was causing the SIGILL
760    *  exception.
761    * **/
762 
763   RegisterValue value((uint64_t)-1);
764   const RegisterInfo &info = GetRegisterInfo().GetOrigAxInfo();
765   return DoWriteRegisterValue(info.byte_offset, info.name, value);
766 
767   return error;
768 }
769 
770 Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues(
771     const lldb::DataBufferSP &data_sp) {
772   Status error;
773 
774   if (!data_sp) {
775     error = Status::FromErrorStringWithFormat(
776         "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided",
777         __FUNCTION__);
778     return error;
779   }
780 
781   if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
782     error = Status::FromErrorStringWithFormatv(
783         "data_sp contained mismatched data size, expected {0}, actual {1}",
784         REG_CONTEXT_SIZE, data_sp->GetByteSize());
785     return error;
786   }
787 
788   const uint8_t *src = data_sp->GetBytes();
789   if (src == nullptr) {
790     error = Status::FromErrorStringWithFormat(
791         "NativeRegisterContextLinux_x86_64::%s "
792         "DataBuffer::GetBytes() returned a null "
793         "pointer",
794         __FUNCTION__);
795     return error;
796   }
797   ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize());
798 
799   error = WriteGPR();
800   if (error.Fail())
801     return error;
802 
803   src += GetRegisterInfoInterface().GetGPRSize();
804   if (m_xstate_type == XStateType::FXSAVE)
805     ::memcpy(&m_xstate->fxsave, src, sizeof(m_xstate->fxsave));
806   else if (m_xstate_type == XStateType::XSAVE)
807     ::memcpy(&m_xstate->xsave, src, sizeof(m_xstate->xsave));
808 
809   error = WriteFPR();
810   if (error.Fail())
811     return error;
812 
813   if (m_xstate_type == XStateType::XSAVE) {
814     lldb::ByteOrder byte_order = GetByteOrder();
815 
816     if (IsCPUFeatureAvailable(RegSet::avx)) {
817       // Parse the YMM register content from the register halves.
818       for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
819            ++reg) {
820         if (!CopyYMMtoXSTATE(reg, byte_order)) {
821           error = Status::FromErrorStringWithFormat(
822               "NativeRegisterContextLinux_x86_64::%s "
823               "CopyYMMtoXSTATE() failed for reg num "
824               "%" PRIu32,
825               __FUNCTION__, reg);
826           return error;
827         }
828       }
829     }
830 
831     if (IsCPUFeatureAvailable(RegSet::mpx)) {
832       for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc;
833            ++reg) {
834         if (!CopyMPXtoXSTATE(reg)) {
835           error = Status::FromErrorStringWithFormat(
836               "NativeRegisterContextLinux_x86_64::%s "
837               "CopyMPXtoXSTATE() failed for reg num "
838               "%" PRIu32,
839               __FUNCTION__, reg);
840           return error;
841         }
842       }
843     }
844   }
845 
846   return error;
847 }
848 
849 bool NativeRegisterContextLinux_x86_64::IsCPUFeatureAvailable(
850     RegSet feature_code) const {
851   if (m_xstate_type == XStateType::Invalid) {
852     if (const_cast<NativeRegisterContextLinux_x86_64 *>(this)->ReadFPR().Fail())
853       return false;
854   }
855   switch (feature_code) {
856   case RegSet::gpr:
857   case RegSet::fpu:
858     return true;
859   case RegSet::avx: // Check if CPU has AVX and if there is kernel support, by
860                     // reading in the XCR0 area of XSAVE.
861     if ((m_xstate->xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX)
862       return true;
863      break;
864   case RegSet::mpx: // Check if CPU has MPX and if there is kernel support, by
865                     // reading in the XCR0 area of XSAVE.
866     if ((m_xstate->xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX)
867       return true;
868     break;
869   }
870   return false;
871 }
872 
873 bool NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable(
874     uint32_t set_index) const {
875   uint32_t num_sets = k_num_register_sets - k_num_extended_register_sets;
876 
877   switch (static_cast<RegSet>(set_index)) {
878   case RegSet::gpr:
879   case RegSet::fpu:
880     return (set_index < num_sets);
881   case RegSet::avx:
882     return IsCPUFeatureAvailable(RegSet::avx);
883   case RegSet::mpx:
884     return IsCPUFeatureAvailable(RegSet::mpx);
885   }
886   return false;
887 }
888 
889 bool NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const {
890   // GPRs come first.
891   return reg_index <= m_reg_info.last_gpr;
892 }
893 
894 bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const {
895   return (m_reg_info.first_fpr <= reg_index &&
896           reg_index <= m_reg_info.last_fpr);
897 }
898 
899 bool NativeRegisterContextLinux_x86_64::IsDR(uint32_t reg_index) const {
900   return (m_reg_info.first_dr <= reg_index &&
901           reg_index <= m_reg_info.last_dr);
902 }
903 
904 Status NativeRegisterContextLinux_x86_64::WriteFPR() {
905   switch (m_xstate_type) {
906   case XStateType::FXSAVE:
907     return WriteRegisterSet(
908         &m_iovec, sizeof(m_xstate->fxsave),
909         fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture()));
910   case XStateType::XSAVE:
911     return WriteRegisterSet(&m_iovec, sizeof(m_xstate->xsave), NT_X86_XSTATE);
912   default:
913     return Status::FromErrorString("Unrecognized FPR type.");
914   }
915 }
916 
917 bool NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const {
918   if (!IsCPUFeatureAvailable(RegSet::avx))
919     return false;
920   return (m_reg_info.first_ymm <= reg_index &&
921           reg_index <= m_reg_info.last_ymm);
922 }
923 
924 bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM(
925     uint32_t reg_index, lldb::ByteOrder byte_order) {
926   if (!IsAVX(reg_index))
927     return false;
928 
929   if (byte_order == lldb::eByteOrderLittle) {
930     uint32_t reg_no = reg_index - m_reg_info.first_ymm;
931     m_ymm_set.ymm[reg_no] = XStateToYMM(
932         m_xstate->fxsave.xmm[reg_no].bytes,
933         m_xstate->xsave.ymmh[reg_no].bytes);
934     return true;
935   }
936 
937   return false; // unsupported or invalid byte order
938 }
939 
940 bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(
941     uint32_t reg, lldb::ByteOrder byte_order) {
942   if (!IsAVX(reg))
943     return false;
944 
945   if (byte_order == lldb::eByteOrderLittle) {
946     uint32_t reg_no = reg - m_reg_info.first_ymm;
947     YMMToXState(m_ymm_set.ymm[reg_no],
948         m_xstate->fxsave.xmm[reg_no].bytes,
949         m_xstate->xsave.ymmh[reg_no].bytes);
950     return true;
951   }
952 
953   return false; // unsupported or invalid byte order
954 }
955 
956 void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() {
957   switch (m_xstate_type) {
958   case XStateType::FXSAVE:
959     return &m_xstate->fxsave;
960   case XStateType::XSAVE:
961     return &m_iovec;
962   default:
963     return nullptr;
964   }
965 }
966 
967 size_t NativeRegisterContextLinux_x86_64::GetFPRSize() {
968   switch (m_xstate_type) {
969   case XStateType::FXSAVE:
970     return sizeof(m_xstate->fxsave);
971   case XStateType::XSAVE:
972     return sizeof(m_iovec);
973   default:
974     return 0;
975   }
976 }
977 
978 Status NativeRegisterContextLinux_x86_64::ReadFPR() {
979   Status error;
980 
981   // Probe XSAVE and if it is not supported fall back to FXSAVE.
982   if (m_xstate_type != XStateType::FXSAVE) {
983     error = ReadRegisterSet(&m_iovec, sizeof(m_xstate->xsave), NT_X86_XSTATE);
984     if (!error.Fail()) {
985       m_xstate_type = XStateType::XSAVE;
986       return error;
987     }
988   }
989   error = ReadRegisterSet(
990       &m_iovec, sizeof(m_xstate->xsave),
991       fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture()));
992   if (!error.Fail()) {
993     m_xstate_type = XStateType::FXSAVE;
994     return error;
995   }
996   return Status::FromErrorString("Unrecognized FPR type.");
997 }
998 
999 bool NativeRegisterContextLinux_x86_64::IsMPX(uint32_t reg_index) const {
1000   if (!IsCPUFeatureAvailable(RegSet::mpx))
1001     return false;
1002   return (m_reg_info.first_mpxr <= reg_index &&
1003           reg_index <= m_reg_info.last_mpxc);
1004 }
1005 
1006 bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) {
1007   if (!IsMPX(reg))
1008     return false;
1009 
1010   if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
1011     ::memcpy(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,
1012              m_xstate->xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
1013              sizeof(MPXReg));
1014   } else {
1015     ::memcpy(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,
1016              m_xstate->xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
1017              sizeof(MPXCsr));
1018   }
1019   return true;
1020 }
1021 
1022 bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) {
1023   if (!IsMPX(reg))
1024     return false;
1025 
1026   if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
1027     ::memcpy(m_xstate->xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
1028              m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg));
1029   } else {
1030     ::memcpy(m_xstate->xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
1031              m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr));
1032   }
1033   return true;
1034 }
1035 
1036 uint32_t
1037 NativeRegisterContextLinux_x86_64::GetPtraceOffset(uint32_t reg_index) {
1038   // If register is MPX, remove extra factor from gdb offset
1039   return GetRegisterInfoAtIndex(reg_index)->byte_offset -
1040          (IsMPX(reg_index) ? 128 : 0);
1041 }
1042 
1043 std::optional<NativeRegisterContextLinux::SyscallData>
1044 NativeRegisterContextLinux_x86_64::GetSyscallData() {
1045   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
1046   case llvm::Triple::x86: {
1047     static const uint8_t Int80[] = {0xcd, 0x80};
1048     static const uint32_t Args[] = {lldb_eax_i386, lldb_ebx_i386, lldb_ecx_i386,
1049                                     lldb_edx_i386, lldb_esi_i386, lldb_edi_i386,
1050                                     lldb_ebp_i386};
1051     return SyscallData{Int80, Args, lldb_eax_i386};
1052   }
1053   case llvm::Triple::x86_64: {
1054     static const uint8_t Syscall[] = {0x0f, 0x05};
1055     static const uint32_t Args[] = {
1056         x86_64_with_base::lldb_rax, x86_64_with_base::lldb_rdi, x86_64_with_base::lldb_rsi, x86_64_with_base::lldb_rdx,
1057         x86_64_with_base::lldb_r10, x86_64_with_base::lldb_r8,  x86_64_with_base::lldb_r9};
1058     return SyscallData{Syscall, Args, x86_64_with_base::lldb_rax};
1059   }
1060   default:
1061     llvm_unreachable("Unhandled architecture!");
1062   }
1063 }
1064 
1065 std::optional<NativeRegisterContextLinux::MmapData>
1066 NativeRegisterContextLinux_x86_64::GetMmapData() {
1067   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
1068   case llvm::Triple::x86:
1069     return MmapData{192, 91};
1070   case llvm::Triple::x86_64:
1071     return MmapData{9, 11};
1072   default:
1073     llvm_unreachable("Unhandled architecture!");
1074   }
1075 }
1076 
1077 const RegisterInfo *NativeRegisterContextLinux_x86_64::GetDR(int num) const {
1078   assert(num >= 0 && num <= 7);
1079   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
1080   case llvm::Triple::x86:
1081     return GetRegisterInfoAtIndex(lldb_dr0_i386 + num);
1082   case llvm::Triple::x86_64:
1083     return GetRegisterInfoAtIndex(x86_64_with_base::lldb_dr0 + num);
1084   default:
1085     llvm_unreachable("Unhandled target architecture.");
1086   }
1087 }
1088 
1089 #endif // defined(__i386__) || defined(__x86_64__)
1090