12850b1beSTodd Fiala //===-- NativeRegisterContextLinux_x86_64.cpp ---------------*- C++ -*-===//
22850b1beSTodd Fiala //
32850b1beSTodd Fiala //                     The LLVM Compiler Infrastructure
42850b1beSTodd Fiala //
52850b1beSTodd Fiala // This file is distributed under the University of Illinois Open Source
62850b1beSTodd Fiala // License. See LICENSE.TXT for details.
72850b1beSTodd Fiala //
82850b1beSTodd Fiala //===----------------------------------------------------------------------===//
92850b1beSTodd Fiala 
10068f8a7eSTamas Berghammer #if defined(__i386__) || defined(__x86_64__)
11068f8a7eSTamas Berghammer 
122850b1beSTodd Fiala #include "NativeRegisterContextLinux_x86_64.h"
132850b1beSTodd Fiala 
142850b1beSTodd Fiala #include "lldb/Core/DataBufferHeap.h"
152850b1beSTodd Fiala #include "lldb/Core/Error.h"
16b9c1b51eSKate Stone #include "lldb/Core/Log.h"
172850b1beSTodd Fiala #include "lldb/Core/RegisterValue.h"
18068f8a7eSTamas Berghammer #include "lldb/Host/HostInfo.h"
19068f8a7eSTamas Berghammer 
20068f8a7eSTamas Berghammer #include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
21068f8a7eSTamas Berghammer #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
222850b1beSTodd Fiala 
232850b1beSTodd Fiala using namespace lldb_private;
24db264a6dSTamas Berghammer using namespace lldb_private::process_linux;
252850b1beSTodd Fiala 
262850b1beSTodd Fiala // ----------------------------------------------------------------------------
272850b1beSTodd Fiala // Private namespace.
282850b1beSTodd Fiala // ----------------------------------------------------------------------------
292850b1beSTodd Fiala 
30b9c1b51eSKate Stone namespace {
312850b1beSTodd Fiala // x86 32-bit general purpose registers.
32b9c1b51eSKate Stone const uint32_t g_gpr_regnums_i386[] = {
33b9c1b51eSKate Stone     lldb_eax_i386,      lldb_ebx_i386,    lldb_ecx_i386, lldb_edx_i386,
34b9c1b51eSKate Stone     lldb_edi_i386,      lldb_esi_i386,    lldb_ebp_i386, lldb_esp_i386,
35b9c1b51eSKate Stone     lldb_eip_i386,      lldb_eflags_i386, lldb_cs_i386,  lldb_fs_i386,
36b9c1b51eSKate Stone     lldb_gs_i386,       lldb_ss_i386,     lldb_ds_i386,  lldb_es_i386,
37b9c1b51eSKate Stone     lldb_ax_i386,       lldb_bx_i386,     lldb_cx_i386,  lldb_dx_i386,
38b9c1b51eSKate Stone     lldb_di_i386,       lldb_si_i386,     lldb_bp_i386,  lldb_sp_i386,
39b9c1b51eSKate Stone     lldb_ah_i386,       lldb_bh_i386,     lldb_ch_i386,  lldb_dh_i386,
40b9c1b51eSKate Stone     lldb_al_i386,       lldb_bl_i386,     lldb_cl_i386,  lldb_dl_i386,
412850b1beSTodd Fiala     LLDB_INVALID_REGNUM // register sets need to end with this flag
422850b1beSTodd Fiala };
43b9c1b51eSKate Stone static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) -
44b9c1b51eSKate Stone                       1 ==
45b9c1b51eSKate Stone                   k_num_gpr_registers_i386,
462850b1beSTodd Fiala               "g_gpr_regnums_i386 has wrong number of register infos");
472850b1beSTodd Fiala 
482850b1beSTodd Fiala // x86 32-bit floating point registers.
49b9c1b51eSKate Stone const uint32_t g_fpu_regnums_i386[] = {
50b9c1b51eSKate Stone     lldb_fctrl_i386,    lldb_fstat_i386,     lldb_ftag_i386,  lldb_fop_i386,
51b9c1b51eSKate Stone     lldb_fiseg_i386,    lldb_fioff_i386,     lldb_foseg_i386, lldb_fooff_i386,
52b9c1b51eSKate Stone     lldb_mxcsr_i386,    lldb_mxcsrmask_i386, lldb_st0_i386,   lldb_st1_i386,
53b9c1b51eSKate Stone     lldb_st2_i386,      lldb_st3_i386,       lldb_st4_i386,   lldb_st5_i386,
54b9c1b51eSKate Stone     lldb_st6_i386,      lldb_st7_i386,       lldb_mm0_i386,   lldb_mm1_i386,
55b9c1b51eSKate Stone     lldb_mm2_i386,      lldb_mm3_i386,       lldb_mm4_i386,   lldb_mm5_i386,
56b9c1b51eSKate Stone     lldb_mm6_i386,      lldb_mm7_i386,       lldb_xmm0_i386,  lldb_xmm1_i386,
57b9c1b51eSKate Stone     lldb_xmm2_i386,     lldb_xmm3_i386,      lldb_xmm4_i386,  lldb_xmm5_i386,
58b9c1b51eSKate Stone     lldb_xmm6_i386,     lldb_xmm7_i386,
592850b1beSTodd Fiala     LLDB_INVALID_REGNUM // register sets need to end with this flag
602850b1beSTodd Fiala };
61b9c1b51eSKate Stone static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) -
62b9c1b51eSKate Stone                       1 ==
63b9c1b51eSKate Stone                   k_num_fpr_registers_i386,
642850b1beSTodd Fiala               "g_fpu_regnums_i386 has wrong number of register infos");
652850b1beSTodd Fiala 
662850b1beSTodd Fiala // x86 32-bit AVX registers.
67b9c1b51eSKate Stone const uint32_t g_avx_regnums_i386[] = {
68b9c1b51eSKate Stone     lldb_ymm0_i386,     lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386,
69b9c1b51eSKate Stone     lldb_ymm4_i386,     lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386,
702850b1beSTodd Fiala     LLDB_INVALID_REGNUM // register sets need to end with this flag
712850b1beSTodd Fiala };
72b9c1b51eSKate Stone static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) -
73b9c1b51eSKate Stone                       1 ==
74b9c1b51eSKate Stone                   k_num_avx_registers_i386,
752850b1beSTodd Fiala               " g_avx_regnums_i386 has wrong number of register infos");
762850b1beSTodd Fiala 
77*cda0ae46SValentina Giusti // x64 32-bit MPX registers.
78*cda0ae46SValentina Giusti static const uint32_t g_mpx_regnums_i386[] = {
79*cda0ae46SValentina Giusti     lldb_bnd0_i386,     lldb_bnd1_i386, lldb_bnd2_i386, lldb_bnd3_i386,
80*cda0ae46SValentina Giusti     lldb_bndcfgu_i386,  lldb_bndstatus_i386,
81*cda0ae46SValentina Giusti     LLDB_INVALID_REGNUM // register sets need to end with this flag
82*cda0ae46SValentina Giusti };
83*cda0ae46SValentina Giusti static_assert((sizeof(g_mpx_regnums_i386) / sizeof(g_mpx_regnums_i386[0])) -
84*cda0ae46SValentina Giusti                       1 ==
85*cda0ae46SValentina Giusti                   k_num_mpx_registers_i386,
86*cda0ae46SValentina Giusti               "g_mpx_regnums_x86_64 has wrong number of register infos");
87*cda0ae46SValentina Giusti 
882850b1beSTodd Fiala // x86 64-bit general purpose registers.
89b9c1b51eSKate Stone static const uint32_t g_gpr_regnums_x86_64[] = {
90b9c1b51eSKate Stone     lldb_rax_x86_64,    lldb_rbx_x86_64,    lldb_rcx_x86_64, lldb_rdx_x86_64,
91b9c1b51eSKate Stone     lldb_rdi_x86_64,    lldb_rsi_x86_64,    lldb_rbp_x86_64, lldb_rsp_x86_64,
92b9c1b51eSKate Stone     lldb_r8_x86_64,     lldb_r9_x86_64,     lldb_r10_x86_64, lldb_r11_x86_64,
93b9c1b51eSKate Stone     lldb_r12_x86_64,    lldb_r13_x86_64,    lldb_r14_x86_64, lldb_r15_x86_64,
94b9c1b51eSKate Stone     lldb_rip_x86_64,    lldb_rflags_x86_64, lldb_cs_x86_64,  lldb_fs_x86_64,
95b9c1b51eSKate Stone     lldb_gs_x86_64,     lldb_ss_x86_64,     lldb_ds_x86_64,  lldb_es_x86_64,
96b9c1b51eSKate Stone     lldb_eax_x86_64,    lldb_ebx_x86_64,    lldb_ecx_x86_64, lldb_edx_x86_64,
97b9c1b51eSKate Stone     lldb_edi_x86_64,    lldb_esi_x86_64,    lldb_ebp_x86_64, lldb_esp_x86_64,
987f013bcdSZachary Turner     lldb_r8d_x86_64,  // Low 32 bits or r8
997f013bcdSZachary Turner     lldb_r9d_x86_64,  // Low 32 bits or r9
1007f013bcdSZachary Turner     lldb_r10d_x86_64, // Low 32 bits or r10
1017f013bcdSZachary Turner     lldb_r11d_x86_64, // Low 32 bits or r11
1027f013bcdSZachary Turner     lldb_r12d_x86_64, // Low 32 bits or r12
1037f013bcdSZachary Turner     lldb_r13d_x86_64, // Low 32 bits or r13
1047f013bcdSZachary Turner     lldb_r14d_x86_64, // Low 32 bits or r14
1057f013bcdSZachary Turner     lldb_r15d_x86_64, // Low 32 bits or r15
106b9c1b51eSKate Stone     lldb_ax_x86_64,     lldb_bx_x86_64,     lldb_cx_x86_64,  lldb_dx_x86_64,
107b9c1b51eSKate Stone     lldb_di_x86_64,     lldb_si_x86_64,     lldb_bp_x86_64,  lldb_sp_x86_64,
1087f013bcdSZachary Turner     lldb_r8w_x86_64,  // Low 16 bits or r8
1097f013bcdSZachary Turner     lldb_r9w_x86_64,  // Low 16 bits or r9
1107f013bcdSZachary Turner     lldb_r10w_x86_64, // Low 16 bits or r10
1117f013bcdSZachary Turner     lldb_r11w_x86_64, // Low 16 bits or r11
1127f013bcdSZachary Turner     lldb_r12w_x86_64, // Low 16 bits or r12
1137f013bcdSZachary Turner     lldb_r13w_x86_64, // Low 16 bits or r13
1147f013bcdSZachary Turner     lldb_r14w_x86_64, // Low 16 bits or r14
1157f013bcdSZachary Turner     lldb_r15w_x86_64, // Low 16 bits or r15
116b9c1b51eSKate Stone     lldb_ah_x86_64,     lldb_bh_x86_64,     lldb_ch_x86_64,  lldb_dh_x86_64,
117b9c1b51eSKate Stone     lldb_al_x86_64,     lldb_bl_x86_64,     lldb_cl_x86_64,  lldb_dl_x86_64,
118b9c1b51eSKate Stone     lldb_dil_x86_64,    lldb_sil_x86_64,    lldb_bpl_x86_64, lldb_spl_x86_64,
1197f013bcdSZachary Turner     lldb_r8l_x86_64,    // Low 8 bits or r8
1207f013bcdSZachary Turner     lldb_r9l_x86_64,    // Low 8 bits or r9
1217f013bcdSZachary Turner     lldb_r10l_x86_64,   // Low 8 bits or r10
1227f013bcdSZachary Turner     lldb_r11l_x86_64,   // Low 8 bits or r11
1237f013bcdSZachary Turner     lldb_r12l_x86_64,   // Low 8 bits or r12
1247f013bcdSZachary Turner     lldb_r13l_x86_64,   // Low 8 bits or r13
1257f013bcdSZachary Turner     lldb_r14l_x86_64,   // Low 8 bits or r14
1267f013bcdSZachary Turner     lldb_r15l_x86_64,   // Low 8 bits or r15
1272850b1beSTodd Fiala     LLDB_INVALID_REGNUM // register sets need to end with this flag
1282850b1beSTodd Fiala };
129b9c1b51eSKate Stone static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
130b9c1b51eSKate Stone                       1 ==
131b9c1b51eSKate Stone                   k_num_gpr_registers_x86_64,
1322850b1beSTodd Fiala               "g_gpr_regnums_x86_64 has wrong number of register infos");
1332850b1beSTodd Fiala 
1342850b1beSTodd Fiala // x86 64-bit floating point registers.
135b9c1b51eSKate Stone static const uint32_t g_fpu_regnums_x86_64[] = {
136b9c1b51eSKate Stone     lldb_fctrl_x86_64,     lldb_fstat_x86_64, lldb_ftag_x86_64,
137b9c1b51eSKate Stone     lldb_fop_x86_64,       lldb_fiseg_x86_64, lldb_fioff_x86_64,
138b9c1b51eSKate Stone     lldb_foseg_x86_64,     lldb_fooff_x86_64, lldb_mxcsr_x86_64,
139b9c1b51eSKate Stone     lldb_mxcsrmask_x86_64, lldb_st0_x86_64,   lldb_st1_x86_64,
140b9c1b51eSKate Stone     lldb_st2_x86_64,       lldb_st3_x86_64,   lldb_st4_x86_64,
141b9c1b51eSKate Stone     lldb_st5_x86_64,       lldb_st6_x86_64,   lldb_st7_x86_64,
142b9c1b51eSKate Stone     lldb_mm0_x86_64,       lldb_mm1_x86_64,   lldb_mm2_x86_64,
143b9c1b51eSKate Stone     lldb_mm3_x86_64,       lldb_mm4_x86_64,   lldb_mm5_x86_64,
144b9c1b51eSKate Stone     lldb_mm6_x86_64,       lldb_mm7_x86_64,   lldb_xmm0_x86_64,
145b9c1b51eSKate Stone     lldb_xmm1_x86_64,      lldb_xmm2_x86_64,  lldb_xmm3_x86_64,
146b9c1b51eSKate Stone     lldb_xmm4_x86_64,      lldb_xmm5_x86_64,  lldb_xmm6_x86_64,
147b9c1b51eSKate Stone     lldb_xmm7_x86_64,      lldb_xmm8_x86_64,  lldb_xmm9_x86_64,
148b9c1b51eSKate Stone     lldb_xmm10_x86_64,     lldb_xmm11_x86_64, lldb_xmm12_x86_64,
149b9c1b51eSKate Stone     lldb_xmm13_x86_64,     lldb_xmm14_x86_64, lldb_xmm15_x86_64,
1502850b1beSTodd Fiala     LLDB_INVALID_REGNUM // register sets need to end with this flag
1512850b1beSTodd Fiala };
152b9c1b51eSKate Stone static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
153b9c1b51eSKate Stone                       1 ==
154b9c1b51eSKate Stone                   k_num_fpr_registers_x86_64,
1552850b1beSTodd Fiala               "g_fpu_regnums_x86_64 has wrong number of register infos");
1562850b1beSTodd Fiala 
1572850b1beSTodd Fiala // x86 64-bit AVX registers.
158b9c1b51eSKate Stone static const uint32_t g_avx_regnums_x86_64[] = {
159b9c1b51eSKate Stone     lldb_ymm0_x86_64,   lldb_ymm1_x86_64,  lldb_ymm2_x86_64,  lldb_ymm3_x86_64,
160b9c1b51eSKate Stone     lldb_ymm4_x86_64,   lldb_ymm5_x86_64,  lldb_ymm6_x86_64,  lldb_ymm7_x86_64,
161b9c1b51eSKate Stone     lldb_ymm8_x86_64,   lldb_ymm9_x86_64,  lldb_ymm10_x86_64, lldb_ymm11_x86_64,
162b9c1b51eSKate Stone     lldb_ymm12_x86_64,  lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64,
1632850b1beSTodd Fiala     LLDB_INVALID_REGNUM // register sets need to end with this flag
1642850b1beSTodd Fiala };
165b9c1b51eSKate Stone static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) -
166b9c1b51eSKate Stone                       1 ==
167b9c1b51eSKate Stone                   k_num_avx_registers_x86_64,
1682850b1beSTodd Fiala               "g_avx_regnums_x86_64 has wrong number of register infos");
1692850b1beSTodd Fiala 
170*cda0ae46SValentina Giusti // x86 64-bit MPX registers.
171*cda0ae46SValentina Giusti static const uint32_t g_mpx_regnums_x86_64[] = {
172*cda0ae46SValentina Giusti     lldb_bnd0_x86_64,    lldb_bnd1_x86_64,    lldb_bnd2_x86_64,
173*cda0ae46SValentina Giusti     lldb_bnd3_x86_64,    lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64,
174*cda0ae46SValentina Giusti     LLDB_INVALID_REGNUM // register sets need to end with this flag
175*cda0ae46SValentina Giusti };
176*cda0ae46SValentina Giusti static_assert((sizeof(g_mpx_regnums_x86_64) / sizeof(g_mpx_regnums_x86_64[0])) -
177*cda0ae46SValentina Giusti                       1 ==
178*cda0ae46SValentina Giusti                   k_num_mpx_registers_x86_64,
179*cda0ae46SValentina Giusti               "g_mpx_regnums_x86_64 has wrong number of register infos");
180*cda0ae46SValentina Giusti 
1812850b1beSTodd Fiala // Number of register sets provided by this context.
182*cda0ae46SValentina Giusti enum { k_num_extended_register_sets = 2, k_num_register_sets = 4 };
1832850b1beSTodd Fiala 
1842850b1beSTodd Fiala // Register sets for x86 32-bit.
185b9c1b51eSKate Stone static const RegisterSet g_reg_sets_i386[k_num_register_sets] = {
186b9c1b51eSKate Stone     {"General Purpose Registers", "gpr", k_num_gpr_registers_i386,
187b9c1b51eSKate Stone      g_gpr_regnums_i386},
188b9c1b51eSKate Stone     {"Floating Point Registers", "fpu", k_num_fpr_registers_i386,
189b9c1b51eSKate Stone      g_fpu_regnums_i386},
190b9c1b51eSKate Stone     {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386,
191*cda0ae46SValentina Giusti      g_avx_regnums_i386},
192*cda0ae46SValentina Giusti     { "Memory Protection Extensions", "mpx", k_num_mpx_registers_i386,
193*cda0ae46SValentina Giusti      g_mpx_regnums_i386}};
1942850b1beSTodd Fiala 
1952850b1beSTodd Fiala // Register sets for x86 64-bit.
196b9c1b51eSKate Stone static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
197b9c1b51eSKate Stone     {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64,
198b9c1b51eSKate Stone      g_gpr_regnums_x86_64},
199b9c1b51eSKate Stone     {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64,
200b9c1b51eSKate Stone      g_fpu_regnums_x86_64},
201b9c1b51eSKate Stone     {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64,
202*cda0ae46SValentina Giusti      g_avx_regnums_x86_64},
203*cda0ae46SValentina Giusti     { "Memory Protection Extensions", "mpx", k_num_mpx_registers_x86_64,
204*cda0ae46SValentina Giusti      g_mpx_regnums_x86_64}};
2052850b1beSTodd Fiala }
2062850b1beSTodd Fiala 
2072850b1beSTodd Fiala #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR))
2082850b1beSTodd Fiala 
2092850b1beSTodd Fiala // ----------------------------------------------------------------------------
2102850b1beSTodd Fiala // Required ptrace defines.
2112850b1beSTodd Fiala // ----------------------------------------------------------------------------
2122850b1beSTodd Fiala 
2132850b1beSTodd Fiala // Support ptrace extensions even when compiled without required kernel support
2142850b1beSTodd Fiala #ifndef NT_X86_XSTATE
2152850b1beSTodd Fiala #define NT_X86_XSTATE 0x202
2162850b1beSTodd Fiala #endif
217296e063dSAbhishek Aggarwal #ifndef NT_PRXFPREG
218296e063dSAbhishek Aggarwal #define NT_PRXFPREG 0x46e62b7f
219296e063dSAbhishek Aggarwal #endif
2202850b1beSTodd Fiala 
221068f8a7eSTamas Berghammer NativeRegisterContextLinux *
222b9c1b51eSKate Stone NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
223b9c1b51eSKate Stone     const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
224b9c1b51eSKate Stone     uint32_t concrete_frame_idx) {
225b9c1b51eSKate Stone   return new NativeRegisterContextLinux_x86_64(target_arch, native_thread,
226b9c1b51eSKate Stone                                                concrete_frame_idx);
227068f8a7eSTamas Berghammer }
228068f8a7eSTamas Berghammer 
2292850b1beSTodd Fiala // ----------------------------------------------------------------------------
2302850b1beSTodd Fiala // NativeRegisterContextLinux_x86_64 members.
2312850b1beSTodd Fiala // ----------------------------------------------------------------------------
2322850b1beSTodd Fiala 
233068f8a7eSTamas Berghammer static RegisterInfoInterface *
234b9c1b51eSKate Stone CreateRegisterInfoInterface(const ArchSpec &target_arch) {
235b9c1b51eSKate Stone   if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
236068f8a7eSTamas Berghammer     // 32-bit hosts run with a RegisterContextLinux_i386 context.
237068f8a7eSTamas Berghammer     return new RegisterContextLinux_i386(target_arch);
238b9c1b51eSKate Stone   } else {
239068f8a7eSTamas Berghammer     assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
240068f8a7eSTamas Berghammer            "Register setting path assumes this is a 64-bit host");
241b9c1b51eSKate Stone     // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the
242b9c1b51eSKate Stone     // x86_64 register context.
243068f8a7eSTamas Berghammer     return new RegisterContextLinux_x86_64(target_arch);
244068f8a7eSTamas Berghammer   }
245068f8a7eSTamas Berghammer }
246068f8a7eSTamas Berghammer 
247b9c1b51eSKate Stone NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
248b9c1b51eSKate Stone     const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
249b9c1b51eSKate Stone     uint32_t concrete_frame_idx)
250b9c1b51eSKate Stone     : NativeRegisterContextLinux(native_thread, concrete_frame_idx,
251b9c1b51eSKate Stone                                  CreateRegisterInfoInterface(target_arch)),
252b9c1b51eSKate Stone       m_fpr_type(eFPRTypeNotValid), m_fpr(), m_iovec(), m_ymm_set(),
253*cda0ae46SValentina Giusti       m_mpx_set(), m_reg_info(), m_gpr_x86_64() {
2542850b1beSTodd Fiala   // Set up data about ranges of valid registers.
255b9c1b51eSKate Stone   switch (target_arch.GetMachine()) {
2562850b1beSTodd Fiala   case llvm::Triple::x86:
2572850b1beSTodd Fiala     m_reg_info.num_registers = k_num_registers_i386;
2582850b1beSTodd Fiala     m_reg_info.num_gpr_registers = k_num_gpr_registers_i386;
2592850b1beSTodd Fiala     m_reg_info.num_fpr_registers = k_num_fpr_registers_i386;
2602850b1beSTodd Fiala     m_reg_info.num_avx_registers = k_num_avx_registers_i386;
261*cda0ae46SValentina Giusti     m_reg_info.num_mpx_registers = k_num_mpx_registers_i386;
2622850b1beSTodd Fiala     m_reg_info.last_gpr = k_last_gpr_i386;
2632850b1beSTodd Fiala     m_reg_info.first_fpr = k_first_fpr_i386;
2642850b1beSTodd Fiala     m_reg_info.last_fpr = k_last_fpr_i386;
2657f013bcdSZachary Turner     m_reg_info.first_st = lldb_st0_i386;
2667f013bcdSZachary Turner     m_reg_info.last_st = lldb_st7_i386;
2677f013bcdSZachary Turner     m_reg_info.first_mm = lldb_mm0_i386;
2687f013bcdSZachary Turner     m_reg_info.last_mm = lldb_mm7_i386;
2697f013bcdSZachary Turner     m_reg_info.first_xmm = lldb_xmm0_i386;
2707f013bcdSZachary Turner     m_reg_info.last_xmm = lldb_xmm7_i386;
2717f013bcdSZachary Turner     m_reg_info.first_ymm = lldb_ymm0_i386;
2727f013bcdSZachary Turner     m_reg_info.last_ymm = lldb_ymm7_i386;
273*cda0ae46SValentina Giusti     m_reg_info.first_mpxr = lldb_bnd0_i386;
274*cda0ae46SValentina Giusti     m_reg_info.last_mpxr = lldb_bnd3_i386;
275*cda0ae46SValentina Giusti     m_reg_info.first_mpxc = lldb_bndcfgu_i386;
276*cda0ae46SValentina Giusti     m_reg_info.last_mpxc = lldb_bndstatus_i386;
2777f013bcdSZachary Turner     m_reg_info.first_dr = lldb_dr0_i386;
2787f013bcdSZachary Turner     m_reg_info.gpr_flags = lldb_eflags_i386;
2792850b1beSTodd Fiala     break;
2802850b1beSTodd Fiala   case llvm::Triple::x86_64:
2812850b1beSTodd Fiala     m_reg_info.num_registers = k_num_registers_x86_64;
2822850b1beSTodd Fiala     m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64;
2832850b1beSTodd Fiala     m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64;
2842850b1beSTodd Fiala     m_reg_info.num_avx_registers = k_num_avx_registers_x86_64;
285*cda0ae46SValentina Giusti     m_reg_info.num_mpx_registers = k_num_mpx_registers_x86_64;
2862850b1beSTodd Fiala     m_reg_info.last_gpr = k_last_gpr_x86_64;
2872850b1beSTodd Fiala     m_reg_info.first_fpr = k_first_fpr_x86_64;
2882850b1beSTodd Fiala     m_reg_info.last_fpr = k_last_fpr_x86_64;
2897f013bcdSZachary Turner     m_reg_info.first_st = lldb_st0_x86_64;
2907f013bcdSZachary Turner     m_reg_info.last_st = lldb_st7_x86_64;
2917f013bcdSZachary Turner     m_reg_info.first_mm = lldb_mm0_x86_64;
2927f013bcdSZachary Turner     m_reg_info.last_mm = lldb_mm7_x86_64;
2937f013bcdSZachary Turner     m_reg_info.first_xmm = lldb_xmm0_x86_64;
2947f013bcdSZachary Turner     m_reg_info.last_xmm = lldb_xmm15_x86_64;
2957f013bcdSZachary Turner     m_reg_info.first_ymm = lldb_ymm0_x86_64;
2967f013bcdSZachary Turner     m_reg_info.last_ymm = lldb_ymm15_x86_64;
297*cda0ae46SValentina Giusti     m_reg_info.first_mpxr = lldb_bnd0_x86_64;
298*cda0ae46SValentina Giusti     m_reg_info.last_mpxr = lldb_bnd3_x86_64;
299*cda0ae46SValentina Giusti     m_reg_info.first_mpxc = lldb_bndcfgu_x86_64;
300*cda0ae46SValentina Giusti     m_reg_info.last_mpxc = lldb_bndstatus_x86_64;
3017f013bcdSZachary Turner     m_reg_info.first_dr = lldb_dr0_x86_64;
3027f013bcdSZachary Turner     m_reg_info.gpr_flags = lldb_rflags_x86_64;
3032850b1beSTodd Fiala     break;
3042850b1beSTodd Fiala   default:
3052850b1beSTodd Fiala     assert(false && "Unhandled target architecture.");
3062850b1beSTodd Fiala     break;
3072850b1beSTodd Fiala   }
3082850b1beSTodd Fiala 
3092850b1beSTodd Fiala   // Initialize m_iovec to point to the buffer and buffer size
3102850b1beSTodd Fiala   // using the conventions of Berkeley style UIO structures, as required
3112850b1beSTodd Fiala   // by PTRACE extensions.
3122850b1beSTodd Fiala   m_iovec.iov_base = &m_fpr.xstate.xsave;
3132850b1beSTodd Fiala   m_iovec.iov_len = sizeof(m_fpr.xstate.xsave);
3142850b1beSTodd Fiala 
3152850b1beSTodd Fiala   // Clear out the FPR state.
3162850b1beSTodd Fiala   ::memset(&m_fpr, 0, sizeof(FPR));
3177f658eddSAbhishek Aggarwal 
3187f658eddSAbhishek Aggarwal   // Store byte offset of fctrl (i.e. first register of FPR)
3197f658eddSAbhishek Aggarwal   const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl");
3207f658eddSAbhishek Aggarwal   m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;
3212850b1beSTodd Fiala }
3222850b1beSTodd Fiala 
3232850b1beSTodd Fiala // CONSIDER after local and llgs debugging are merged, register set support can
3242850b1beSTodd Fiala // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual.
325b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_x86_64::GetRegisterSetCount() const {
3262850b1beSTodd Fiala   uint32_t sets = 0;
327b9c1b51eSKate Stone   for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
3282850b1beSTodd Fiala     if (IsRegisterSetAvailable(set_index))
3292850b1beSTodd Fiala       ++sets;
3302850b1beSTodd Fiala   }
3312850b1beSTodd Fiala 
3322850b1beSTodd Fiala   return sets;
3332850b1beSTodd Fiala }
3342850b1beSTodd Fiala 
335b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_x86_64::GetUserRegisterCount() const {
3368fa23b8eSTamas Berghammer   uint32_t count = 0;
337b9c1b51eSKate Stone   for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
338db264a6dSTamas Berghammer     const RegisterSet *set = GetRegisterSet(set_index);
3398fa23b8eSTamas Berghammer     if (set)
3408fa23b8eSTamas Berghammer       count += set->num_registers;
3418fa23b8eSTamas Berghammer   }
3428fa23b8eSTamas Berghammer   return count;
3438fa23b8eSTamas Berghammer }
3448fa23b8eSTamas Berghammer 
345db264a6dSTamas Berghammer const RegisterSet *
346b9c1b51eSKate Stone NativeRegisterContextLinux_x86_64::GetRegisterSet(uint32_t set_index) const {
3472850b1beSTodd Fiala   if (!IsRegisterSetAvailable(set_index))
3482850b1beSTodd Fiala     return nullptr;
3492850b1beSTodd Fiala 
350b9c1b51eSKate Stone   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
3512850b1beSTodd Fiala   case llvm::Triple::x86:
3522850b1beSTodd Fiala     return &g_reg_sets_i386[set_index];
3532850b1beSTodd Fiala   case llvm::Triple::x86_64:
3542850b1beSTodd Fiala     return &g_reg_sets_x86_64[set_index];
3552850b1beSTodd Fiala   default:
3562850b1beSTodd Fiala     assert(false && "Unhandled target architecture.");
3572850b1beSTodd Fiala     return nullptr;
3582850b1beSTodd Fiala   }
3592850b1beSTodd Fiala 
3602850b1beSTodd Fiala   return nullptr;
3612850b1beSTodd Fiala }
3622850b1beSTodd Fiala 
363b9c1b51eSKate Stone Error NativeRegisterContextLinux_x86_64::ReadRegister(
364b9c1b51eSKate Stone     const RegisterInfo *reg_info, RegisterValue &reg_value) {
3652850b1beSTodd Fiala   Error error;
3662850b1beSTodd Fiala 
367b9c1b51eSKate Stone   if (!reg_info) {
3682850b1beSTodd Fiala     error.SetErrorString("reg_info NULL");
3692850b1beSTodd Fiala     return error;
3702850b1beSTodd Fiala   }
3712850b1beSTodd Fiala 
3722850b1beSTodd Fiala   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
373b9c1b51eSKate Stone   if (reg == LLDB_INVALID_REGNUM) {
374b9c1b51eSKate Stone     // This is likely an internal register for lldb use only and should not be
375b9c1b51eSKate Stone     // directly queried.
376b9c1b51eSKate Stone     error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
377b9c1b51eSKate Stone                                    "register, cannot read directly",
378b9c1b51eSKate Stone                                    reg_info->name);
3792850b1beSTodd Fiala     return error;
3802850b1beSTodd Fiala   }
3812850b1beSTodd Fiala 
382b9c1b51eSKate Stone   if (IsFPR(reg, GetFPRType())) {
383068f8a7eSTamas Berghammer     error = ReadFPR();
384068f8a7eSTamas Berghammer     if (error.Fail())
3852850b1beSTodd Fiala       return error;
386b9c1b51eSKate Stone   } else {
3872850b1beSTodd Fiala     uint32_t full_reg = reg;
388b9c1b51eSKate Stone     bool is_subreg = reg_info->invalidate_regs &&
389b9c1b51eSKate Stone                      (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
3902850b1beSTodd Fiala 
391b9c1b51eSKate Stone     if (is_subreg) {
3922850b1beSTodd Fiala       // Read the full aligned 64-bit register.
3932850b1beSTodd Fiala       full_reg = reg_info->invalidate_regs[0];
3942850b1beSTodd Fiala     }
3952850b1beSTodd Fiala 
3962850b1beSTodd Fiala     error = ReadRegisterRaw(full_reg, reg_value);
3972850b1beSTodd Fiala 
398b9c1b51eSKate Stone     if (error.Success()) {
399b9c1b51eSKate Stone       // If our read was not aligned (for ah,bh,ch,dh), shift our returned value
400b9c1b51eSKate Stone       // one byte to the right.
4012850b1beSTodd Fiala       if (is_subreg && (reg_info->byte_offset & 0x1))
4022850b1beSTodd Fiala         reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
4032850b1beSTodd Fiala 
404b9c1b51eSKate Stone       // If our return byte size was greater than the return value reg size,
405b9c1b51eSKate Stone       // then
4062850b1beSTodd Fiala       // use the type specified by reg_info rather than the uint64_t default
4072850b1beSTodd Fiala       if (reg_value.GetByteSize() > reg_info->byte_size)
4082850b1beSTodd Fiala         reg_value.SetType(reg_info);
4092850b1beSTodd Fiala     }
4102850b1beSTodd Fiala     return error;
4112850b1beSTodd Fiala   }
4122850b1beSTodd Fiala 
413b9c1b51eSKate Stone   if (reg_info->encoding == lldb::eEncodingVector) {
4142850b1beSTodd Fiala     lldb::ByteOrder byte_order = GetByteOrder();
4152850b1beSTodd Fiala 
416b9c1b51eSKate Stone     if (byte_order != lldb::eByteOrderInvalid) {
4172850b1beSTodd Fiala       if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
418b9c1b51eSKate Stone         reg_value.SetBytes(
419b9c1b51eSKate Stone             m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes,
420b9c1b51eSKate Stone             reg_info->byte_size, byte_order);
4212850b1beSTodd Fiala       if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
422b9c1b51eSKate Stone         reg_value.SetBytes(
423b9c1b51eSKate Stone             m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes,
424b9c1b51eSKate Stone             reg_info->byte_size, byte_order);
4252850b1beSTodd Fiala       if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
426b9c1b51eSKate Stone         reg_value.SetBytes(
427b9c1b51eSKate Stone             m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
428b9c1b51eSKate Stone             reg_info->byte_size, byte_order);
429b9c1b51eSKate Stone       if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
4302850b1beSTodd Fiala         // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
4312850b1beSTodd Fiala         if (GetFPRType() == eFPRTypeXSAVE && CopyXSTATEtoYMM(reg, byte_order))
432b9c1b51eSKate Stone           reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
433b9c1b51eSKate Stone                              reg_info->byte_size, byte_order);
434b9c1b51eSKate Stone         else {
4352850b1beSTodd Fiala           error.SetErrorString("failed to copy ymm register value");
4362850b1beSTodd Fiala           return error;
4372850b1beSTodd Fiala         }
4382850b1beSTodd Fiala       }
439*cda0ae46SValentina Giusti       if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
440*cda0ae46SValentina Giusti         if (GetFPRType() == eFPRTypeXSAVE && CopyXSTATEtoMPX(reg))
441*cda0ae46SValentina Giusti           reg_value.SetBytes(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,
442*cda0ae46SValentina Giusti                              reg_info->byte_size, byte_order);
443*cda0ae46SValentina Giusti         else {
444*cda0ae46SValentina Giusti           error.SetErrorString("failed to copy mpx register value");
445*cda0ae46SValentina Giusti           return error;
446*cda0ae46SValentina Giusti         }
447*cda0ae46SValentina Giusti       }
448*cda0ae46SValentina Giusti       if (reg >= m_reg_info.first_mpxc && reg <= m_reg_info.last_mpxc) {
449*cda0ae46SValentina Giusti         if (GetFPRType() == eFPRTypeXSAVE && CopyXSTATEtoMPX(reg))
450*cda0ae46SValentina Giusti           reg_value.SetBytes(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,
451*cda0ae46SValentina Giusti                              reg_info->byte_size, byte_order);
452*cda0ae46SValentina Giusti         else {
453*cda0ae46SValentina Giusti           error.SetErrorString("failed to copy mpx register value");
454*cda0ae46SValentina Giusti           return error;
455*cda0ae46SValentina Giusti         }
456*cda0ae46SValentina Giusti       }
457ee44a92dSDimitar Vlahovski 
4582850b1beSTodd Fiala       if (reg_value.GetType() != RegisterValue::eTypeBytes)
459b9c1b51eSKate Stone         error.SetErrorString(
460b9c1b51eSKate Stone             "write failed - type was expected to be RegisterValue::eTypeBytes");
4612850b1beSTodd Fiala 
4622850b1beSTodd Fiala       return error;
4632850b1beSTodd Fiala     }
4642850b1beSTodd Fiala 
4652850b1beSTodd Fiala     error.SetErrorString("byte order is invalid");
4662850b1beSTodd Fiala     return error;
4672850b1beSTodd Fiala   }
4682850b1beSTodd Fiala 
4692850b1beSTodd Fiala   // Get pointer to m_fpr.xstate.fxsave variable and set the data from it.
4707f658eddSAbhishek Aggarwal 
4717f658eddSAbhishek Aggarwal   // Byte offsets of all registers are calculated wrt 'UserArea' structure.
4727f658eddSAbhishek Aggarwal   // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)}
473b9c1b51eSKate Stone   // and stores them in 'm_fpr' (of type FPR structure). To extract values of
474b9c1b51eSKate Stone   // fpu
475b9c1b51eSKate Stone   // registers, m_fpr should be read at byte offsets calculated wrt to FPR
476b9c1b51eSKate Stone   // structure.
4777f658eddSAbhishek Aggarwal 
4787f658eddSAbhishek Aggarwal   // Since, FPR structure is also one of the member of UserArea structure.
479b9c1b51eSKate Stone   // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
480b9c1b51eSKate Stone   // byte_offset(fctrl wrt UserArea)
4817f658eddSAbhishek Aggarwal   assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
482b9c1b51eSKate Stone   uint8_t *src =
483b9c1b51eSKate Stone       (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
484b9c1b51eSKate Stone   switch (reg_info->byte_size) {
485b352a1c8SAbhishek Aggarwal   case 1:
486b352a1c8SAbhishek Aggarwal     reg_value.SetUInt8(*(uint8_t *)src);
487b352a1c8SAbhishek Aggarwal     break;
4882850b1beSTodd Fiala   case 2:
4892850b1beSTodd Fiala     reg_value.SetUInt16(*(uint16_t *)src);
4902850b1beSTodd Fiala     break;
4912850b1beSTodd Fiala   case 4:
4922850b1beSTodd Fiala     reg_value.SetUInt32(*(uint32_t *)src);
4932850b1beSTodd Fiala     break;
4942850b1beSTodd Fiala   case 8:
4952850b1beSTodd Fiala     reg_value.SetUInt64(*(uint64_t *)src);
4962850b1beSTodd Fiala     break;
4972850b1beSTodd Fiala   default:
4982850b1beSTodd Fiala     assert(false && "Unhandled data size.");
499b9c1b51eSKate Stone     error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32,
500b9c1b51eSKate Stone                                    reg_info->byte_size);
5012850b1beSTodd Fiala     break;
5022850b1beSTodd Fiala   }
5032850b1beSTodd Fiala 
5042850b1beSTodd Fiala   return error;
5052850b1beSTodd Fiala }
5062850b1beSTodd Fiala 
507b9c1b51eSKate Stone Error NativeRegisterContextLinux_x86_64::WriteRegister(
508b9c1b51eSKate Stone     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
5092850b1beSTodd Fiala   assert(reg_info && "reg_info is null");
5102850b1beSTodd Fiala 
5112850b1beSTodd Fiala   const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
5122850b1beSTodd Fiala   if (reg_index == LLDB_INVALID_REGNUM)
513b9c1b51eSKate Stone     return Error("no lldb regnum for %s", reg_info && reg_info->name
514b9c1b51eSKate Stone                                               ? reg_info->name
515b9c1b51eSKate Stone                                               : "<unknown register>");
5162850b1beSTodd Fiala 
5172850b1beSTodd Fiala   if (IsGPR(reg_index))
518068f8a7eSTamas Berghammer     return WriteRegisterRaw(reg_index, reg_value);
5192850b1beSTodd Fiala 
520b9c1b51eSKate Stone   if (IsFPR(reg_index, GetFPRType())) {
521b9c1b51eSKate Stone     if (reg_info->encoding == lldb::eEncodingVector) {
5222850b1beSTodd Fiala       if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st)
523b9c1b51eSKate Stone         ::memcpy(
524b9c1b51eSKate Stone             m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_st].bytes,
525b9c1b51eSKate Stone             reg_value.GetBytes(), reg_value.GetByteSize());
5262850b1beSTodd Fiala 
5272850b1beSTodd Fiala       if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm)
528b9c1b51eSKate Stone         ::memcpy(
529b9c1b51eSKate Stone             m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes,
530b9c1b51eSKate Stone             reg_value.GetBytes(), reg_value.GetByteSize());
5312850b1beSTodd Fiala 
5322850b1beSTodd Fiala       if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm)
533b9c1b51eSKate Stone         ::memcpy(
534b9c1b51eSKate Stone             m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes,
535b9c1b51eSKate Stone             reg_value.GetBytes(), reg_value.GetByteSize());
5362850b1beSTodd Fiala 
537b9c1b51eSKate Stone       if (reg_index >= m_reg_info.first_ymm &&
538b9c1b51eSKate Stone           reg_index <= m_reg_info.last_ymm) {
5392850b1beSTodd Fiala         if (GetFPRType() != eFPRTypeXSAVE)
5402850b1beSTodd Fiala           return Error("target processor does not support AVX");
5412850b1beSTodd Fiala 
542b9c1b51eSKate Stone         // Store ymm register content, and split into the register halves in
543b9c1b51eSKate Stone         // xmm.bytes and ymmh.bytes
544b9c1b51eSKate Stone         ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
545b9c1b51eSKate Stone                  reg_value.GetBytes(), reg_value.GetByteSize());
5462850b1beSTodd Fiala         if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
5472850b1beSTodd Fiala           return Error("CopyYMMtoXSTATE() failed");
5482850b1beSTodd Fiala       }
549*cda0ae46SValentina Giusti 
550*cda0ae46SValentina Giusti       if (reg_index >= m_reg_info.first_mpxr &&
551*cda0ae46SValentina Giusti           reg_index <= m_reg_info.last_mpxr) {
552*cda0ae46SValentina Giusti         if (GetFPRType() != eFPRTypeXSAVE)
553*cda0ae46SValentina Giusti           return Error("target processor does not support MPX");
554*cda0ae46SValentina Giusti 
555*cda0ae46SValentina Giusti         ::memcpy(m_mpx_set.mpxr[reg_index - m_reg_info.first_mpxr].bytes,
556*cda0ae46SValentina Giusti                  reg_value.GetBytes(), reg_value.GetByteSize());
557*cda0ae46SValentina Giusti         if (!CopyMPXtoXSTATE(reg_index))
558*cda0ae46SValentina Giusti           return Error("CopyMPXtoXSTATE() failed");
559*cda0ae46SValentina Giusti       }
560*cda0ae46SValentina Giusti 
561*cda0ae46SValentina Giusti       if (reg_index >= m_reg_info.first_mpxc &&
562*cda0ae46SValentina Giusti           reg_index <= m_reg_info.last_mpxc) {
563*cda0ae46SValentina Giusti         if (GetFPRType() != eFPRTypeXSAVE)
564*cda0ae46SValentina Giusti           return Error("target processor does not support MPX");
565*cda0ae46SValentina Giusti 
566*cda0ae46SValentina Giusti         ::memcpy(m_mpx_set.mpxc[reg_index - m_reg_info.first_mpxc].bytes,
567*cda0ae46SValentina Giusti                  reg_value.GetBytes(), reg_value.GetByteSize());
568*cda0ae46SValentina Giusti         if (!CopyMPXtoXSTATE(reg_index))
569*cda0ae46SValentina Giusti           return Error("CopyMPXtoXSTATE() failed");
570*cda0ae46SValentina Giusti       }
571b9c1b51eSKate Stone     } else {
5722850b1beSTodd Fiala       // Get pointer to m_fpr.xstate.fxsave variable and set the data to it.
5737f658eddSAbhishek Aggarwal 
5747f658eddSAbhishek Aggarwal       // Byte offsets of all registers are calculated wrt 'UserArea' structure.
575b9c1b51eSKate Stone       // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only
576b9c1b51eSKate Stone       // fpu
577b9c1b51eSKate Stone       // registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu registers
578b9c1b51eSKate Stone       // should
5797f658eddSAbhishek Aggarwal       // be written in m_fpr at byte offsets calculated wrt FPR structure.
5807f658eddSAbhishek Aggarwal 
5817f658eddSAbhishek Aggarwal       // Since, FPR structure is also one of the member of UserArea structure.
582b9c1b51eSKate Stone       // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
583b9c1b51eSKate Stone       // byte_offset(fctrl wrt UserArea)
584b9c1b51eSKate Stone       assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) <
585b9c1b51eSKate Stone              sizeof(m_fpr));
586b9c1b51eSKate Stone       uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset -
587b9c1b51eSKate Stone                      m_fctrl_offset_in_userarea;
588b9c1b51eSKate Stone       switch (reg_info->byte_size) {
589b352a1c8SAbhishek Aggarwal       case 1:
590b352a1c8SAbhishek Aggarwal         *(uint8_t *)dst = reg_value.GetAsUInt8();
591b352a1c8SAbhishek Aggarwal         break;
5922850b1beSTodd Fiala       case 2:
5932850b1beSTodd Fiala         *(uint16_t *)dst = reg_value.GetAsUInt16();
5942850b1beSTodd Fiala         break;
5952850b1beSTodd Fiala       case 4:
5962850b1beSTodd Fiala         *(uint32_t *)dst = reg_value.GetAsUInt32();
5972850b1beSTodd Fiala         break;
5982850b1beSTodd Fiala       case 8:
5992850b1beSTodd Fiala         *(uint64_t *)dst = reg_value.GetAsUInt64();
6002850b1beSTodd Fiala         break;
6012850b1beSTodd Fiala       default:
6022850b1beSTodd Fiala         assert(false && "Unhandled data size.");
603b9c1b51eSKate Stone         return Error("unhandled register data size %" PRIu32,
604b9c1b51eSKate Stone                      reg_info->byte_size);
6052850b1beSTodd Fiala       }
6062850b1beSTodd Fiala     }
6072850b1beSTodd Fiala 
608068f8a7eSTamas Berghammer     Error error = WriteFPR();
609068f8a7eSTamas Berghammer     if (error.Fail())
610068f8a7eSTamas Berghammer       return error;
611068f8a7eSTamas Berghammer 
612b9c1b51eSKate Stone     if (IsAVX(reg_index)) {
6132850b1beSTodd Fiala       if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
6142850b1beSTodd Fiala         return Error("CopyYMMtoXSTATE() failed");
6152850b1beSTodd Fiala     }
616*cda0ae46SValentina Giusti 
617*cda0ae46SValentina Giusti     if (IsMPX(reg_index)) {
618*cda0ae46SValentina Giusti       if (!CopyMPXtoXSTATE(reg_index))
619*cda0ae46SValentina Giusti         return Error("CopyMPXtoXSTATE() failed");
620*cda0ae46SValentina Giusti     }
6212850b1beSTodd Fiala     return Error();
6222850b1beSTodd Fiala   }
623b9c1b51eSKate Stone   return Error("failed - register wasn't recognized to be a GPR or an FPR, "
624b9c1b51eSKate Stone                "write strategy unknown");
6252850b1beSTodd Fiala }
6262850b1beSTodd Fiala 
627b9c1b51eSKate Stone Error NativeRegisterContextLinux_x86_64::ReadAllRegisterValues(
628b9c1b51eSKate Stone     lldb::DataBufferSP &data_sp) {
6292850b1beSTodd Fiala   Error error;
6302850b1beSTodd Fiala 
6312850b1beSTodd Fiala   data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
632b9c1b51eSKate Stone   if (!data_sp) {
633b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
634b9c1b51eSKate Stone         "failed to allocate DataBufferHeap instance of size %" PRIu64,
635b9c1b51eSKate Stone         REG_CONTEXT_SIZE);
6362850b1beSTodd Fiala     return error;
6372850b1beSTodd Fiala   }
6382850b1beSTodd Fiala 
639068f8a7eSTamas Berghammer   error = ReadGPR();
640068f8a7eSTamas Berghammer   if (error.Fail())
6412850b1beSTodd Fiala     return error;
6422850b1beSTodd Fiala 
643068f8a7eSTamas Berghammer   error = ReadFPR();
644068f8a7eSTamas Berghammer   if (error.Fail())
6452850b1beSTodd Fiala     return error;
6462850b1beSTodd Fiala 
6472850b1beSTodd Fiala   uint8_t *dst = data_sp->GetBytes();
648b9c1b51eSKate Stone   if (dst == nullptr) {
649b9c1b51eSKate Stone     error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64
650b9c1b51eSKate Stone                                    " returned a null pointer",
651b9c1b51eSKate Stone                                    REG_CONTEXT_SIZE);
6522850b1beSTodd Fiala     return error;
6532850b1beSTodd Fiala   }
6542850b1beSTodd Fiala 
6552850b1beSTodd Fiala   ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());
6562850b1beSTodd Fiala   dst += GetRegisterInfoInterface().GetGPRSize();
6572850b1beSTodd Fiala   if (GetFPRType() == eFPRTypeFXSAVE)
6582850b1beSTodd Fiala     ::memcpy(dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
659b9c1b51eSKate Stone   else if (GetFPRType() == eFPRTypeXSAVE) {
6602850b1beSTodd Fiala     lldb::ByteOrder byte_order = GetByteOrder();
6612850b1beSTodd Fiala 
6622850b1beSTodd Fiala     // Assemble the YMM register content from the register halves.
663b9c1b51eSKate Stone     for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
664b9c1b51eSKate Stone          ++reg) {
665b9c1b51eSKate Stone       if (!CopyXSTATEtoYMM(reg, byte_order)) {
666b9c1b51eSKate Stone         error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
667b9c1b51eSKate Stone                                        "CopyXSTATEtoYMM() failed for reg num "
668b9c1b51eSKate Stone                                        "%" PRIu32,
669b9c1b51eSKate Stone                                        __FUNCTION__, reg);
6702850b1beSTodd Fiala         return error;
6712850b1beSTodd Fiala       }
6722850b1beSTodd Fiala     }
6732850b1beSTodd Fiala 
674*cda0ae46SValentina Giusti     for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc;
675*cda0ae46SValentina Giusti          ++reg) {
676*cda0ae46SValentina Giusti       if (!CopyXSTATEtoMPX(reg)) {
677*cda0ae46SValentina Giusti         error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
678*cda0ae46SValentina Giusti                                        "CopyXSTATEtoMPX() failed for reg num "
679*cda0ae46SValentina Giusti                                        "%" PRIu32,
680*cda0ae46SValentina Giusti                                        __FUNCTION__, reg);
681*cda0ae46SValentina Giusti         return error;
682*cda0ae46SValentina Giusti       }
683*cda0ae46SValentina Giusti     }
6842850b1beSTodd Fiala     // Copy the extended register state including the assembled ymm registers.
6852850b1beSTodd Fiala     ::memcpy(dst, &m_fpr, sizeof(m_fpr));
686b9c1b51eSKate Stone   } else {
6872850b1beSTodd Fiala     assert(false && "how do we save the floating point registers?");
6882850b1beSTodd Fiala     error.SetErrorString("unsure how to save the floating point registers");
6892850b1beSTodd Fiala   }
6904778e410SRavitheja Addepally   /** The following code is specific to Linux x86 based architectures,
6914778e410SRavitheja Addepally    *  where the register orig_eax (32 bit)/orig_rax (64 bit) is set to
6924778e410SRavitheja Addepally    *  -1 to solve the bug 23659, such a setting prevents the automatic
6934778e410SRavitheja Addepally    *  decrement of the instruction pointer which was causing the SIGILL
6944778e410SRavitheja Addepally    *  exception.
6954778e410SRavitheja Addepally    * **/
6964778e410SRavitheja Addepally 
6974778e410SRavitheja Addepally   RegisterValue value((uint64_t)-1);
698b9c1b51eSKate Stone   const RegisterInfo *reg_info =
699b9c1b51eSKate Stone       GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax");
7004778e410SRavitheja Addepally   if (reg_info == nullptr)
7014778e410SRavitheja Addepally     reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax");
7024778e410SRavitheja Addepally 
70364ad85ceSTamas Berghammer   if (reg_info != nullptr)
7044778e410SRavitheja Addepally     return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, value);
7052850b1beSTodd Fiala 
7062850b1beSTodd Fiala   return error;
7072850b1beSTodd Fiala }
7082850b1beSTodd Fiala 
709b9c1b51eSKate Stone Error NativeRegisterContextLinux_x86_64::WriteAllRegisterValues(
710b9c1b51eSKate Stone     const lldb::DataBufferSP &data_sp) {
7112850b1beSTodd Fiala   Error error;
7122850b1beSTodd Fiala 
713b9c1b51eSKate Stone   if (!data_sp) {
714b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
715b9c1b51eSKate Stone         "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided",
716b9c1b51eSKate Stone         __FUNCTION__);
7172850b1beSTodd Fiala     return error;
7182850b1beSTodd Fiala   }
7192850b1beSTodd Fiala 
720b9c1b51eSKate Stone   if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
721b9c1b51eSKate Stone     error.SetErrorStringWithFormat(
722b9c1b51eSKate Stone         "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched "
723b9c1b51eSKate Stone         "data size, expected %" PRIu64 ", actual %" PRIu64,
724b9c1b51eSKate Stone         __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
7252850b1beSTodd Fiala     return error;
7262850b1beSTodd Fiala   }
7272850b1beSTodd Fiala 
7282850b1beSTodd Fiala   uint8_t *src = data_sp->GetBytes();
729b9c1b51eSKate Stone   if (src == nullptr) {
730b9c1b51eSKate Stone     error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
731b9c1b51eSKate Stone                                    "DataBuffer::GetBytes() returned a null "
732b9c1b51eSKate Stone                                    "pointer",
733b9c1b51eSKate Stone                                    __FUNCTION__);
7342850b1beSTodd Fiala     return error;
7352850b1beSTodd Fiala   }
7362850b1beSTodd Fiala   ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize());
7372850b1beSTodd Fiala 
738068f8a7eSTamas Berghammer   error = WriteGPR();
739068f8a7eSTamas Berghammer   if (error.Fail())
7402850b1beSTodd Fiala     return error;
7412850b1beSTodd Fiala 
7422850b1beSTodd Fiala   src += GetRegisterInfoInterface().GetGPRSize();
7432850b1beSTodd Fiala   if (GetFPRType() == eFPRTypeFXSAVE)
7442850b1beSTodd Fiala     ::memcpy(&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave));
7452850b1beSTodd Fiala   else if (GetFPRType() == eFPRTypeXSAVE)
7462850b1beSTodd Fiala     ::memcpy(&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
7472850b1beSTodd Fiala 
748068f8a7eSTamas Berghammer   error = WriteFPR();
749068f8a7eSTamas Berghammer   if (error.Fail())
7502850b1beSTodd Fiala     return error;
7512850b1beSTodd Fiala 
752b9c1b51eSKate Stone   if (GetFPRType() == eFPRTypeXSAVE) {
7532850b1beSTodd Fiala     lldb::ByteOrder byte_order = GetByteOrder();
7542850b1beSTodd Fiala 
7552850b1beSTodd Fiala     // Parse the YMM register content from the register halves.
756b9c1b51eSKate Stone     for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
757b9c1b51eSKate Stone          ++reg) {
758b9c1b51eSKate Stone       if (!CopyYMMtoXSTATE(reg, byte_order)) {
759b9c1b51eSKate Stone         error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
760b9c1b51eSKate Stone                                        "CopyYMMtoXSTATE() failed for reg num "
761b9c1b51eSKate Stone                                        "%" PRIu32,
762b9c1b51eSKate Stone                                        __FUNCTION__, reg);
7632850b1beSTodd Fiala         return error;
7642850b1beSTodd Fiala       }
7652850b1beSTodd Fiala     }
766*cda0ae46SValentina Giusti 
767*cda0ae46SValentina Giusti     for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc;
768*cda0ae46SValentina Giusti          ++reg) {
769*cda0ae46SValentina Giusti       if (!CopyMPXtoXSTATE(reg)) {
770*cda0ae46SValentina Giusti         error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
771*cda0ae46SValentina Giusti                                          "CopyMPXtoXSTATE() failed for reg num "
772*cda0ae46SValentina Giusti                                          "%" PRIu32,
773*cda0ae46SValentina Giusti                                          __FUNCTION__, reg);
774*cda0ae46SValentina Giusti         return error;
775*cda0ae46SValentina Giusti       }
776*cda0ae46SValentina Giusti     }
7772850b1beSTodd Fiala   }
7782850b1beSTodd Fiala 
7792850b1beSTodd Fiala   return error;
7802850b1beSTodd Fiala }
7812850b1beSTodd Fiala 
782b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable(
783b9c1b51eSKate Stone     uint32_t set_index) const {
7842850b1beSTodd Fiala   // Note: Extended register sets are assumed to be at the end of g_reg_sets.
7852850b1beSTodd Fiala   uint32_t num_sets = k_num_register_sets - k_num_extended_register_sets;
7862850b1beSTodd Fiala 
787b9c1b51eSKate Stone   if (GetFPRType() == eFPRTypeXSAVE) {
7882850b1beSTodd Fiala     // AVX is the first extended register set.
789*cda0ae46SValentina Giusti     num_sets += 2;
7902850b1beSTodd Fiala   }
7912850b1beSTodd Fiala   return (set_index < num_sets);
7922850b1beSTodd Fiala }
7932850b1beSTodd Fiala 
794b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const {
7952850b1beSTodd Fiala   // GPRs come first.
7962850b1beSTodd Fiala   return reg_index <= m_reg_info.last_gpr;
7972850b1beSTodd Fiala }
7982850b1beSTodd Fiala 
7992850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::FPRType
800b9c1b51eSKate Stone NativeRegisterContextLinux_x86_64::GetFPRType() const {
801296e063dSAbhishek Aggarwal   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
802b9c1b51eSKate Stone   if (m_fpr_type == eFPRTypeNotValid) {
8032850b1beSTodd Fiala     // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx.
8042850b1beSTodd Fiala 
8052850b1beSTodd Fiala     // Try and see if AVX register retrieval works.
8062850b1beSTodd Fiala     m_fpr_type = eFPRTypeXSAVE;
807b9c1b51eSKate Stone     if (const_cast<NativeRegisterContextLinux_x86_64 *>(this)
808b9c1b51eSKate Stone             ->ReadFPR()
809b9c1b51eSKate Stone             .Fail()) {
8102850b1beSTodd Fiala       // Fall back to general floating point with no AVX support.
8112850b1beSTodd Fiala       m_fpr_type = eFPRTypeFXSAVE;
8122850b1beSTodd Fiala 
813296e063dSAbhishek Aggarwal       // Check if FXSAVE area can be read.
814b9c1b51eSKate Stone       if (const_cast<NativeRegisterContextLinux_x86_64 *>(this)
815b9c1b51eSKate Stone               ->ReadFPR()
816b9c1b51eSKate Stone               .Fail()) {
817296e063dSAbhishek Aggarwal         if (log)
818b9c1b51eSKate Stone           log->Printf("NativeRegisterContextLinux_x86_64::%s ptrace APIs "
819b9c1b51eSKate Stone                       "failed to read XSAVE/FXSAVE area",
820b9c1b51eSKate Stone                       __FUNCTION__);
821296e063dSAbhishek Aggarwal       }
822296e063dSAbhishek Aggarwal     }
823296e063dSAbhishek Aggarwal   }
8242850b1beSTodd Fiala   return m_fpr_type;
8252850b1beSTodd Fiala }
8262850b1beSTodd Fiala 
827b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const {
828b9c1b51eSKate Stone   return (m_reg_info.first_fpr <= reg_index &&
829b9c1b51eSKate Stone           reg_index <= m_reg_info.last_fpr);
8302850b1beSTodd Fiala }
8312850b1beSTodd Fiala 
832b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index,
833b9c1b51eSKate Stone                                               FPRType fpr_type) const {
8342850b1beSTodd Fiala   bool generic_fpr = IsFPR(reg_index);
8352850b1beSTodd Fiala 
8362850b1beSTodd Fiala   if (fpr_type == eFPRTypeXSAVE)
837*cda0ae46SValentina Giusti     return generic_fpr || IsAVX(reg_index) || IsMPX(reg_index);
8382850b1beSTodd Fiala   return generic_fpr;
8392850b1beSTodd Fiala }
8402850b1beSTodd Fiala 
841b9c1b51eSKate Stone Error NativeRegisterContextLinux_x86_64::WriteFPR() {
842068f8a7eSTamas Berghammer   const FPRType fpr_type = GetFPRType();
843b9c1b51eSKate Stone   const lldb_private::ArchSpec &target_arch =
844b9c1b51eSKate Stone       GetRegisterInfoInterface().GetTargetArchitecture();
845b9c1b51eSKate Stone   switch (fpr_type) {
846068f8a7eSTamas Berghammer   case FPRType::eFPRTypeFXSAVE:
847296e063dSAbhishek Aggarwal     // For 32-bit inferiors on x86_32/x86_64 architectures,
848296e063dSAbhishek Aggarwal     // FXSAVE area can be written using PTRACE_SETREGSET ptrace api
849296e063dSAbhishek Aggarwal     // For 64-bit inferiors on x86_64 architectures,
850296e063dSAbhishek Aggarwal     // FXSAVE area can be written using PTRACE_SETFPREGS ptrace api
851b9c1b51eSKate Stone     switch (target_arch.GetMachine()) {
852296e063dSAbhishek Aggarwal     case llvm::Triple::x86:
853b9c1b51eSKate Stone       return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave),
854b9c1b51eSKate Stone                               NT_PRXFPREG);
855296e063dSAbhishek Aggarwal     case llvm::Triple::x86_64:
856068f8a7eSTamas Berghammer       return NativeRegisterContextLinux::WriteFPR();
857296e063dSAbhishek Aggarwal     default:
858296e063dSAbhishek Aggarwal       assert(false && "Unhandled target architecture.");
859296e063dSAbhishek Aggarwal       break;
860296e063dSAbhishek Aggarwal     }
861068f8a7eSTamas Berghammer   case FPRType::eFPRTypeXSAVE:
862b9c1b51eSKate Stone     return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave),
863b9c1b51eSKate Stone                             NT_X86_XSTATE);
864068f8a7eSTamas Berghammer   default:
865068f8a7eSTamas Berghammer     return Error("Unrecognized FPR type");
866068f8a7eSTamas Berghammer   }
8672850b1beSTodd Fiala }
8682850b1beSTodd Fiala 
869b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const {
870b9c1b51eSKate Stone   return (m_reg_info.first_ymm <= reg_index &&
871b9c1b51eSKate Stone           reg_index <= m_reg_info.last_ymm);
8722850b1beSTodd Fiala }
8732850b1beSTodd Fiala 
874b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM(
875b9c1b51eSKate Stone     uint32_t reg_index, lldb::ByteOrder byte_order) {
8762850b1beSTodd Fiala   if (!IsAVX(reg_index))
8772850b1beSTodd Fiala     return false;
8782850b1beSTodd Fiala 
879b9c1b51eSKate Stone   if (byte_order == lldb::eByteOrderLittle) {
8802850b1beSTodd Fiala     ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
8812850b1beSTodd Fiala              m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
8822850b1beSTodd Fiala              sizeof(XMMReg));
883b9c1b51eSKate Stone     ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes +
884b9c1b51eSKate Stone                  sizeof(XMMReg),
8852850b1beSTodd Fiala              m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
8862850b1beSTodd Fiala              sizeof(YMMHReg));
8872850b1beSTodd Fiala     return true;
8882850b1beSTodd Fiala   }
8892850b1beSTodd Fiala 
890b9c1b51eSKate Stone   if (byte_order == lldb::eByteOrderBig) {
891b9c1b51eSKate Stone     ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes +
892b9c1b51eSKate Stone                  sizeof(XMMReg),
8932850b1beSTodd Fiala              m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
8942850b1beSTodd Fiala              sizeof(XMMReg));
8952850b1beSTodd Fiala     ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
8962850b1beSTodd Fiala              m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
8972850b1beSTodd Fiala              sizeof(YMMHReg));
8982850b1beSTodd Fiala     return true;
8992850b1beSTodd Fiala   }
9002850b1beSTodd Fiala   return false; // unsupported or invalid byte order
9012850b1beSTodd Fiala }
9022850b1beSTodd Fiala 
903b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(
904b9c1b51eSKate Stone     uint32_t reg, lldb::ByteOrder byte_order) {
9052850b1beSTodd Fiala   if (!IsAVX(reg))
9062850b1beSTodd Fiala     return false;
9072850b1beSTodd Fiala 
908b9c1b51eSKate Stone   if (byte_order == lldb::eByteOrderLittle) {
9092850b1beSTodd Fiala     ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
910b9c1b51eSKate Stone              m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg));
9112850b1beSTodd Fiala     ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
9122850b1beSTodd Fiala              m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
9132850b1beSTodd Fiala              sizeof(YMMHReg));
9142850b1beSTodd Fiala     return true;
9152850b1beSTodd Fiala   }
9162850b1beSTodd Fiala 
917b9c1b51eSKate Stone   if (byte_order == lldb::eByteOrderBig) {
9182850b1beSTodd Fiala     ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
9192850b1beSTodd Fiala              m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
9202850b1beSTodd Fiala              sizeof(XMMReg));
9212850b1beSTodd Fiala     ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
922b9c1b51eSKate Stone              m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg));
9232850b1beSTodd Fiala     return true;
9242850b1beSTodd Fiala   }
9252850b1beSTodd Fiala   return false; // unsupported or invalid byte order
9262850b1beSTodd Fiala }
9272850b1beSTodd Fiala 
928b9c1b51eSKate Stone void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() {
9292850b1beSTodd Fiala   const FPRType fpr_type = GetFPRType();
930b9c1b51eSKate Stone   switch (fpr_type) {
9312850b1beSTodd Fiala   case FPRType::eFPRTypeFXSAVE:
932068f8a7eSTamas Berghammer     return &m_fpr.xstate.fxsave;
9332850b1beSTodd Fiala   case FPRType::eFPRTypeXSAVE:
934068f8a7eSTamas Berghammer     return &m_iovec;
9352850b1beSTodd Fiala   default:
936068f8a7eSTamas Berghammer     return nullptr;
9372850b1beSTodd Fiala   }
9382850b1beSTodd Fiala }
9392850b1beSTodd Fiala 
940b9c1b51eSKate Stone size_t NativeRegisterContextLinux_x86_64::GetFPRSize() {
941068f8a7eSTamas Berghammer   const FPRType fpr_type = GetFPRType();
942b9c1b51eSKate Stone   switch (fpr_type) {
943068f8a7eSTamas Berghammer   case FPRType::eFPRTypeFXSAVE:
944068f8a7eSTamas Berghammer     return sizeof(m_fpr.xstate.fxsave);
945068f8a7eSTamas Berghammer   case FPRType::eFPRTypeXSAVE:
946068f8a7eSTamas Berghammer     return sizeof(m_iovec);
947068f8a7eSTamas Berghammer   default:
948068f8a7eSTamas Berghammer     return 0;
949068f8a7eSTamas Berghammer   }
9502850b1beSTodd Fiala }
9512850b1beSTodd Fiala 
952b9c1b51eSKate Stone Error NativeRegisterContextLinux_x86_64::ReadFPR() {
953068f8a7eSTamas Berghammer   const FPRType fpr_type = GetFPRType();
954b9c1b51eSKate Stone   const lldb_private::ArchSpec &target_arch =
955b9c1b51eSKate Stone       GetRegisterInfoInterface().GetTargetArchitecture();
956b9c1b51eSKate Stone   switch (fpr_type) {
957068f8a7eSTamas Berghammer   case FPRType::eFPRTypeFXSAVE:
958296e063dSAbhishek Aggarwal     // For 32-bit inferiors on x86_32/x86_64 architectures,
959296e063dSAbhishek Aggarwal     // FXSAVE area can be read using PTRACE_GETREGSET ptrace api
960296e063dSAbhishek Aggarwal     // For 64-bit inferiors on x86_64 architectures,
961296e063dSAbhishek Aggarwal     // FXSAVE area can be read using PTRACE_GETFPREGS ptrace api
962b9c1b51eSKate Stone     switch (target_arch.GetMachine()) {
963296e063dSAbhishek Aggarwal     case llvm::Triple::x86:
964296e063dSAbhishek Aggarwal       return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_PRXFPREG);
965296e063dSAbhishek Aggarwal     case llvm::Triple::x86_64:
966068f8a7eSTamas Berghammer       return NativeRegisterContextLinux::ReadFPR();
967296e063dSAbhishek Aggarwal     default:
968296e063dSAbhishek Aggarwal       assert(false && "Unhandled target architecture.");
969296e063dSAbhishek Aggarwal       break;
970296e063dSAbhishek Aggarwal     }
971068f8a7eSTamas Berghammer   case FPRType::eFPRTypeXSAVE:
972068f8a7eSTamas Berghammer     return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
973068f8a7eSTamas Berghammer   default:
974068f8a7eSTamas Berghammer     return Error("Unrecognized FPR type");
975068f8a7eSTamas Berghammer   }
9762850b1beSTodd Fiala }
9772850b1beSTodd Fiala 
978*cda0ae46SValentina Giusti bool NativeRegisterContextLinux_x86_64::IsMPX(uint32_t reg_index) const {
979*cda0ae46SValentina Giusti     return (m_reg_info.first_mpxr <= reg_index &&
980*cda0ae46SValentina Giusti             reg_index <= m_reg_info.last_mpxc);
981*cda0ae46SValentina Giusti }
982*cda0ae46SValentina Giusti 
983*cda0ae46SValentina Giusti bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) {
984*cda0ae46SValentina Giusti   if (!IsMPX(reg))
985*cda0ae46SValentina Giusti     return false;
986*cda0ae46SValentina Giusti 
987*cda0ae46SValentina Giusti   if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
988*cda0ae46SValentina Giusti     ::memcpy(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,
989*cda0ae46SValentina Giusti              m_fpr.xstate.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
990*cda0ae46SValentina Giusti              sizeof(MPXReg));
991*cda0ae46SValentina Giusti   } else {
992*cda0ae46SValentina Giusti     ::memcpy(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,
993*cda0ae46SValentina Giusti              m_fpr.xstate.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
994*cda0ae46SValentina Giusti              sizeof(MPXCsr));
995*cda0ae46SValentina Giusti   }
996*cda0ae46SValentina Giusti   return true;
997*cda0ae46SValentina Giusti }
998*cda0ae46SValentina Giusti 
999*cda0ae46SValentina Giusti bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) {
1000*cda0ae46SValentina Giusti   if (!IsMPX(reg))
1001*cda0ae46SValentina Giusti     return false;
1002*cda0ae46SValentina Giusti 
1003*cda0ae46SValentina Giusti   if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
1004*cda0ae46SValentina Giusti     ::memcpy(m_fpr.xstate.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
1005*cda0ae46SValentina Giusti              m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg));
1006*cda0ae46SValentina Giusti   } else {
1007*cda0ae46SValentina Giusti     ::memcpy(m_fpr.xstate.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
1008*cda0ae46SValentina Giusti              m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr));
1009*cda0ae46SValentina Giusti   }
1010*cda0ae46SValentina Giusti   return true;
1011*cda0ae46SValentina Giusti }
1012*cda0ae46SValentina Giusti 
1013b9c1b51eSKate Stone Error NativeRegisterContextLinux_x86_64::IsWatchpointHit(uint32_t wp_index,
1014b9c1b51eSKate Stone                                                          bool &is_hit) {
101518fe6404SChaoren Lin   if (wp_index >= NumSupportedHardwareWatchpoints())
101618fe6404SChaoren Lin     return Error("Watchpoint index out of range");
101718fe6404SChaoren Lin 
101818fe6404SChaoren Lin   RegisterValue reg_value;
10196a504f6eSChaoren Lin   Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
1020b9c1b51eSKate Stone   if (error.Fail()) {
1021c16f5dcaSChaoren Lin     is_hit = false;
1022c16f5dcaSChaoren Lin     return error;
1023c16f5dcaSChaoren Lin   }
102418fe6404SChaoren Lin 
102518fe6404SChaoren Lin   uint64_t status_bits = reg_value.GetAsUInt64();
102618fe6404SChaoren Lin 
1027c16f5dcaSChaoren Lin   is_hit = status_bits & (1 << wp_index);
102818fe6404SChaoren Lin 
102918fe6404SChaoren Lin   return error;
103018fe6404SChaoren Lin }
103118fe6404SChaoren Lin 
1032b9c1b51eSKate Stone Error NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex(
1033b9c1b51eSKate Stone     uint32_t &wp_index, lldb::addr_t trap_addr) {
1034c16f5dcaSChaoren Lin   uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
1035b9c1b51eSKate Stone   for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
1036c16f5dcaSChaoren Lin     bool is_hit;
1037c16f5dcaSChaoren Lin     Error error = IsWatchpointHit(wp_index, is_hit);
1038c16f5dcaSChaoren Lin     if (error.Fail()) {
1039c16f5dcaSChaoren Lin       wp_index = LLDB_INVALID_INDEX32;
1040c16f5dcaSChaoren Lin       return error;
1041c16f5dcaSChaoren Lin     } else if (is_hit) {
1042c16f5dcaSChaoren Lin       return error;
1043c16f5dcaSChaoren Lin     }
1044c16f5dcaSChaoren Lin   }
1045c16f5dcaSChaoren Lin   wp_index = LLDB_INVALID_INDEX32;
1046c16f5dcaSChaoren Lin   return Error();
1047c16f5dcaSChaoren Lin }
1048c16f5dcaSChaoren Lin 
1049b9c1b51eSKate Stone Error NativeRegisterContextLinux_x86_64::IsWatchpointVacant(uint32_t wp_index,
1050b9c1b51eSKate Stone                                                             bool &is_vacant) {
105118fe6404SChaoren Lin   if (wp_index >= NumSupportedHardwareWatchpoints())
105218fe6404SChaoren Lin     return Error("Watchpoint index out of range");
105318fe6404SChaoren Lin 
105418fe6404SChaoren Lin   RegisterValue reg_value;
10556a504f6eSChaoren Lin   Error error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
1056b9c1b51eSKate Stone   if (error.Fail()) {
1057c16f5dcaSChaoren Lin     is_vacant = false;
1058c16f5dcaSChaoren Lin     return error;
1059c16f5dcaSChaoren Lin   }
106018fe6404SChaoren Lin 
106118fe6404SChaoren Lin   uint64_t control_bits = reg_value.GetAsUInt64();
106218fe6404SChaoren Lin 
1063c16f5dcaSChaoren Lin   is_vacant = !(control_bits & (1 << (2 * wp_index)));
106418fe6404SChaoren Lin 
106518fe6404SChaoren Lin   return error;
106618fe6404SChaoren Lin }
106718fe6404SChaoren Lin 
1068b9c1b51eSKate Stone Error NativeRegisterContextLinux_x86_64::SetHardwareWatchpointWithIndex(
106918fe6404SChaoren Lin     lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
107018fe6404SChaoren Lin 
107118fe6404SChaoren Lin   if (wp_index >= NumSupportedHardwareWatchpoints())
107218fe6404SChaoren Lin     return Error("Watchpoint index out of range");
107318fe6404SChaoren Lin 
1074b9c1b51eSKate Stone   // Read only watchpoints aren't supported on x86_64. Fall back to read/write
1075b9c1b51eSKate Stone   // waitchpoints instead.
1076b9c1b51eSKate Stone   // TODO: Add logic to detect when a write happens and ignore that watchpoint
1077b9c1b51eSKate Stone   // hit.
1078cf8eb9daSOmair Javaid   if (watch_flags == 0x2)
107940caea63STamas Berghammer     watch_flags = 0x3;
1080cf8eb9daSOmair Javaid 
108118fe6404SChaoren Lin   if (watch_flags != 0x1 && watch_flags != 0x3)
108218fe6404SChaoren Lin     return Error("Invalid read/write bits for watchpoint");
108318fe6404SChaoren Lin 
108418fe6404SChaoren Lin   if (size != 1 && size != 2 && size != 4 && size != 8)
108518fe6404SChaoren Lin     return Error("Invalid size for watchpoint");
108618fe6404SChaoren Lin 
1087c16f5dcaSChaoren Lin   bool is_vacant;
1088c16f5dcaSChaoren Lin   Error error = IsWatchpointVacant(wp_index, is_vacant);
1089b9c1b51eSKate Stone   if (error.Fail())
1090b9c1b51eSKate Stone     return error;
1091b9c1b51eSKate Stone   if (!is_vacant)
1092b9c1b51eSKate Stone     return Error("Watchpoint index not vacant");
109318fe6404SChaoren Lin 
109418fe6404SChaoren Lin   RegisterValue reg_value;
10956a504f6eSChaoren Lin   error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
1096b9c1b51eSKate Stone   if (error.Fail())
1097b9c1b51eSKate Stone     return error;
109818fe6404SChaoren Lin 
109918fe6404SChaoren Lin   // for watchpoints 0, 1, 2, or 3, respectively,
110018fe6404SChaoren Lin   // set bits 1, 3, 5, or 7
110118fe6404SChaoren Lin   uint64_t enable_bit = 1 << (2 * wp_index);
110218fe6404SChaoren Lin 
110318fe6404SChaoren Lin   // set bits 16-17, 20-21, 24-25, or 28-29
110418fe6404SChaoren Lin   // with 0b01 for write, and 0b11 for read/write
110518fe6404SChaoren Lin   uint64_t rw_bits = watch_flags << (16 + 4 * wp_index);
110618fe6404SChaoren Lin 
110718fe6404SChaoren Lin   // set bits 18-19, 22-23, 26-27, or 30-31
110818fe6404SChaoren Lin   // with 0b00, 0b01, 0b10, or 0b11
110918fe6404SChaoren Lin   // for 1, 2, 8 (if supported), or 4 bytes, respectively
111018fe6404SChaoren Lin   uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
111118fe6404SChaoren Lin 
111218fe6404SChaoren Lin   uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
111318fe6404SChaoren Lin 
111418fe6404SChaoren Lin   uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
111518fe6404SChaoren Lin 
111618fe6404SChaoren Lin   control_bits |= enable_bit | rw_bits | size_bits;
111718fe6404SChaoren Lin 
1118068f8a7eSTamas Berghammer   error = WriteRegisterRaw(m_reg_info.first_dr + wp_index, RegisterValue(addr));
1119b9c1b51eSKate Stone   if (error.Fail())
1120b9c1b51eSKate Stone     return error;
112118fe6404SChaoren Lin 
1122b9c1b51eSKate Stone   error =
1123b9c1b51eSKate Stone       WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits));
1124b9c1b51eSKate Stone   if (error.Fail())
1125b9c1b51eSKate Stone     return error;
112618fe6404SChaoren Lin 
112718fe6404SChaoren Lin   error.Clear();
112818fe6404SChaoren Lin   return error;
112918fe6404SChaoren Lin }
113018fe6404SChaoren Lin 
1131b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::ClearHardwareWatchpoint(
1132b9c1b51eSKate Stone     uint32_t wp_index) {
113318fe6404SChaoren Lin   if (wp_index >= NumSupportedHardwareWatchpoints())
113418fe6404SChaoren Lin     return false;
113518fe6404SChaoren Lin 
113618fe6404SChaoren Lin   RegisterValue reg_value;
113718fe6404SChaoren Lin 
113818fe6404SChaoren Lin   // for watchpoints 0, 1, 2, or 3, respectively,
113918fe6404SChaoren Lin   // clear bits 0, 1, 2, or 3 of the debug status register (DR6)
11406a504f6eSChaoren Lin   Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
1141b9c1b51eSKate Stone   if (error.Fail())
1142b9c1b51eSKate Stone     return false;
114318fe6404SChaoren Lin   uint64_t bit_mask = 1 << wp_index;
114418fe6404SChaoren Lin   uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
1145068f8a7eSTamas Berghammer   error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits));
1146b9c1b51eSKate Stone   if (error.Fail())
1147b9c1b51eSKate Stone     return false;
114818fe6404SChaoren Lin 
114918fe6404SChaoren Lin   // for watchpoints 0, 1, 2, or 3, respectively,
115018fe6404SChaoren Lin   // clear bits {0-1,16-19}, {2-3,20-23}, {4-5,24-27}, or {6-7,28-31}
115118fe6404SChaoren Lin   // of the debug control register (DR7)
11526a504f6eSChaoren Lin   error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
1153b9c1b51eSKate Stone   if (error.Fail())
1154b9c1b51eSKate Stone     return false;
115518fe6404SChaoren Lin   bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
115618fe6404SChaoren Lin   uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
1157b9c1b51eSKate Stone   return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits))
1158b9c1b51eSKate Stone       .Success();
115918fe6404SChaoren Lin }
116018fe6404SChaoren Lin 
1161b9c1b51eSKate Stone Error NativeRegisterContextLinux_x86_64::ClearAllHardwareWatchpoints() {
116218fe6404SChaoren Lin   RegisterValue reg_value;
116318fe6404SChaoren Lin 
116418fe6404SChaoren Lin   // clear bits {0-4} of the debug status register (DR6)
11656a504f6eSChaoren Lin   Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
1166b9c1b51eSKate Stone   if (error.Fail())
1167b9c1b51eSKate Stone     return error;
116818fe6404SChaoren Lin   uint64_t bit_mask = 0xF;
116918fe6404SChaoren Lin   uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
1170068f8a7eSTamas Berghammer   error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits));
1171b9c1b51eSKate Stone   if (error.Fail())
1172b9c1b51eSKate Stone     return error;
117318fe6404SChaoren Lin 
117418fe6404SChaoren Lin   // clear bits {0-7,16-31} of the debug control register (DR7)
11756a504f6eSChaoren Lin   error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
1176b9c1b51eSKate Stone   if (error.Fail())
1177b9c1b51eSKate Stone     return error;
117818fe6404SChaoren Lin   bit_mask = 0xFF | (0xFFFF << 16);
117918fe6404SChaoren Lin   uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
1180068f8a7eSTamas Berghammer   return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits));
118118fe6404SChaoren Lin }
118218fe6404SChaoren Lin 
1183b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_x86_64::SetHardwareWatchpoint(
1184b9c1b51eSKate Stone     lldb::addr_t addr, size_t size, uint32_t watch_flags) {
1185c16f5dcaSChaoren Lin   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
118618fe6404SChaoren Lin   const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
1187b9c1b51eSKate Stone   for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) {
1188c16f5dcaSChaoren Lin     bool is_vacant;
1189c16f5dcaSChaoren Lin     Error error = IsWatchpointVacant(wp_index, is_vacant);
1190b9c1b51eSKate Stone     if (is_vacant) {
1191c16f5dcaSChaoren Lin       error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index);
1192c16f5dcaSChaoren Lin       if (error.Success())
119318fe6404SChaoren Lin         return wp_index;
119418fe6404SChaoren Lin     }
1195b9c1b51eSKate Stone     if (error.Fail() && log) {
1196c16f5dcaSChaoren Lin       log->Printf("NativeRegisterContextLinux_x86_64::%s Error: %s",
1197c16f5dcaSChaoren Lin                   __FUNCTION__, error.AsCString());
1198c16f5dcaSChaoren Lin     }
1199c16f5dcaSChaoren Lin   }
120018fe6404SChaoren Lin   return LLDB_INVALID_INDEX32;
120118fe6404SChaoren Lin }
120218fe6404SChaoren Lin 
120318fe6404SChaoren Lin lldb::addr_t
1204b9c1b51eSKate Stone NativeRegisterContextLinux_x86_64::GetWatchpointAddress(uint32_t wp_index) {
120518fe6404SChaoren Lin   if (wp_index >= NumSupportedHardwareWatchpoints())
120618fe6404SChaoren Lin     return LLDB_INVALID_ADDRESS;
120718fe6404SChaoren Lin   RegisterValue reg_value;
120818fe6404SChaoren Lin   if (ReadRegisterRaw(m_reg_info.first_dr + wp_index, reg_value).Fail())
120918fe6404SChaoren Lin     return LLDB_INVALID_ADDRESS;
121018fe6404SChaoren Lin   return reg_value.GetAsUInt64();
121118fe6404SChaoren Lin }
121218fe6404SChaoren Lin 
1213b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_x86_64::NumSupportedHardwareWatchpoints() {
121418fe6404SChaoren Lin   // Available debug address registers: dr0, dr1, dr2, dr3
121518fe6404SChaoren Lin   return 4;
121618fe6404SChaoren Lin }
1217068f8a7eSTamas Berghammer 
1218068f8a7eSTamas Berghammer #endif // defined(__i386__) || defined(__x86_64__)
1219