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 
102850b1beSTodd Fiala #include "NativeRegisterContextLinux_x86_64.h"
112850b1beSTodd Fiala 
12*c16f5dcaSChaoren Lin #include "lldb/Core/Log.h"
132850b1beSTodd Fiala #include "lldb/lldb-private-forward.h"
142850b1beSTodd Fiala #include "lldb/Core/DataBufferHeap.h"
152850b1beSTodd Fiala #include "lldb/Core/Error.h"
162850b1beSTodd Fiala #include "lldb/Core/RegisterValue.h"
172fe1d0abSChaoren Lin #include "lldb/Host/common/NativeProcessProtocol.h"
182fe1d0abSChaoren Lin #include "lldb/Host/common/NativeThreadProtocol.h"
192850b1beSTodd Fiala #include "Plugins/Process/Linux/NativeProcessLinux.h"
202850b1beSTodd Fiala 
212850b1beSTodd Fiala using namespace lldb_private;
222850b1beSTodd Fiala 
232850b1beSTodd Fiala // ----------------------------------------------------------------------------
242850b1beSTodd Fiala // Private namespace.
252850b1beSTodd Fiala // ----------------------------------------------------------------------------
262850b1beSTodd Fiala 
272850b1beSTodd Fiala namespace
282850b1beSTodd Fiala {
292850b1beSTodd Fiala     // x86 32-bit general purpose registers.
302850b1beSTodd Fiala     const uint32_t
312850b1beSTodd Fiala     g_gpr_regnums_i386[] =
322850b1beSTodd Fiala     {
337f013bcdSZachary Turner         lldb_eax_i386,
347f013bcdSZachary Turner         lldb_ebx_i386,
357f013bcdSZachary Turner         lldb_ecx_i386,
367f013bcdSZachary Turner         lldb_edx_i386,
377f013bcdSZachary Turner         lldb_edi_i386,
387f013bcdSZachary Turner         lldb_esi_i386,
397f013bcdSZachary Turner         lldb_ebp_i386,
407f013bcdSZachary Turner         lldb_esp_i386,
417f013bcdSZachary Turner         lldb_eip_i386,
427f013bcdSZachary Turner         lldb_eflags_i386,
437f013bcdSZachary Turner         lldb_cs_i386,
447f013bcdSZachary Turner         lldb_fs_i386,
457f013bcdSZachary Turner         lldb_gs_i386,
467f013bcdSZachary Turner         lldb_ss_i386,
477f013bcdSZachary Turner         lldb_ds_i386,
487f013bcdSZachary Turner         lldb_es_i386,
497f013bcdSZachary Turner         lldb_ax_i386,
507f013bcdSZachary Turner         lldb_bx_i386,
517f013bcdSZachary Turner         lldb_cx_i386,
527f013bcdSZachary Turner         lldb_dx_i386,
537f013bcdSZachary Turner         lldb_di_i386,
547f013bcdSZachary Turner         lldb_si_i386,
557f013bcdSZachary Turner         lldb_bp_i386,
567f013bcdSZachary Turner         lldb_sp_i386,
577f013bcdSZachary Turner         lldb_ah_i386,
587f013bcdSZachary Turner         lldb_bh_i386,
597f013bcdSZachary Turner         lldb_ch_i386,
607f013bcdSZachary Turner         lldb_dh_i386,
617f013bcdSZachary Turner         lldb_al_i386,
627f013bcdSZachary Turner         lldb_bl_i386,
637f013bcdSZachary Turner         lldb_cl_i386,
647f013bcdSZachary Turner         lldb_dl_i386,
652850b1beSTodd Fiala         LLDB_INVALID_REGNUM // register sets need to end with this flag
662850b1beSTodd Fiala     };
672850b1beSTodd Fiala     static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) - 1 == k_num_gpr_registers_i386,
682850b1beSTodd Fiala                   "g_gpr_regnums_i386 has wrong number of register infos");
692850b1beSTodd Fiala 
702850b1beSTodd Fiala     // x86 32-bit floating point registers.
712850b1beSTodd Fiala     const uint32_t
722850b1beSTodd Fiala     g_fpu_regnums_i386[] =
732850b1beSTodd Fiala     {
747f013bcdSZachary Turner         lldb_fctrl_i386,
757f013bcdSZachary Turner         lldb_fstat_i386,
767f013bcdSZachary Turner         lldb_ftag_i386,
777f013bcdSZachary Turner         lldb_fop_i386,
787f013bcdSZachary Turner         lldb_fiseg_i386,
797f013bcdSZachary Turner         lldb_fioff_i386,
807f013bcdSZachary Turner         lldb_foseg_i386,
817f013bcdSZachary Turner         lldb_fooff_i386,
827f013bcdSZachary Turner         lldb_mxcsr_i386,
837f013bcdSZachary Turner         lldb_mxcsrmask_i386,
847f013bcdSZachary Turner         lldb_st0_i386,
857f013bcdSZachary Turner         lldb_st1_i386,
867f013bcdSZachary Turner         lldb_st2_i386,
877f013bcdSZachary Turner         lldb_st3_i386,
887f013bcdSZachary Turner         lldb_st4_i386,
897f013bcdSZachary Turner         lldb_st5_i386,
907f013bcdSZachary Turner         lldb_st6_i386,
917f013bcdSZachary Turner         lldb_st7_i386,
927f013bcdSZachary Turner         lldb_mm0_i386,
937f013bcdSZachary Turner         lldb_mm1_i386,
947f013bcdSZachary Turner         lldb_mm2_i386,
957f013bcdSZachary Turner         lldb_mm3_i386,
967f013bcdSZachary Turner         lldb_mm4_i386,
977f013bcdSZachary Turner         lldb_mm5_i386,
987f013bcdSZachary Turner         lldb_mm6_i386,
997f013bcdSZachary Turner         lldb_mm7_i386,
1007f013bcdSZachary Turner         lldb_xmm0_i386,
1017f013bcdSZachary Turner         lldb_xmm1_i386,
1027f013bcdSZachary Turner         lldb_xmm2_i386,
1037f013bcdSZachary Turner         lldb_xmm3_i386,
1047f013bcdSZachary Turner         lldb_xmm4_i386,
1057f013bcdSZachary Turner         lldb_xmm5_i386,
1067f013bcdSZachary Turner         lldb_xmm6_i386,
1077f013bcdSZachary Turner         lldb_xmm7_i386,
1082850b1beSTodd Fiala         LLDB_INVALID_REGNUM // register sets need to end with this flag
1092850b1beSTodd Fiala     };
1102850b1beSTodd Fiala     static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) - 1 == k_num_fpr_registers_i386,
1112850b1beSTodd Fiala                   "g_fpu_regnums_i386 has wrong number of register infos");
1122850b1beSTodd Fiala 
1132850b1beSTodd Fiala     // x86 32-bit AVX registers.
1142850b1beSTodd Fiala     const uint32_t
1152850b1beSTodd Fiala     g_avx_regnums_i386[] =
1162850b1beSTodd Fiala     {
1177f013bcdSZachary Turner         lldb_ymm0_i386,
1187f013bcdSZachary Turner         lldb_ymm1_i386,
1197f013bcdSZachary Turner         lldb_ymm2_i386,
1207f013bcdSZachary Turner         lldb_ymm3_i386,
1217f013bcdSZachary Turner         lldb_ymm4_i386,
1227f013bcdSZachary Turner         lldb_ymm5_i386,
1237f013bcdSZachary Turner         lldb_ymm6_i386,
1247f013bcdSZachary Turner         lldb_ymm7_i386,
1252850b1beSTodd Fiala         LLDB_INVALID_REGNUM // register sets need to end with this flag
1262850b1beSTodd Fiala     };
1272850b1beSTodd Fiala     static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - 1 == k_num_avx_registers_i386,
1282850b1beSTodd Fiala                   " g_avx_regnums_i386 has wrong number of register infos");
1292850b1beSTodd Fiala 
1302850b1beSTodd Fiala     // x86 64-bit general purpose registers.
1312850b1beSTodd Fiala     static const
1322850b1beSTodd Fiala     uint32_t g_gpr_regnums_x86_64[] =
1332850b1beSTodd Fiala     {
1347f013bcdSZachary Turner         lldb_rax_x86_64,
1357f013bcdSZachary Turner         lldb_rbx_x86_64,
1367f013bcdSZachary Turner         lldb_rcx_x86_64,
1377f013bcdSZachary Turner         lldb_rdx_x86_64,
1387f013bcdSZachary Turner         lldb_rdi_x86_64,
1397f013bcdSZachary Turner         lldb_rsi_x86_64,
1407f013bcdSZachary Turner         lldb_rbp_x86_64,
1417f013bcdSZachary Turner         lldb_rsp_x86_64,
1427f013bcdSZachary Turner         lldb_r8_x86_64,
1437f013bcdSZachary Turner         lldb_r9_x86_64,
1447f013bcdSZachary Turner         lldb_r10_x86_64,
1457f013bcdSZachary Turner         lldb_r11_x86_64,
1467f013bcdSZachary Turner         lldb_r12_x86_64,
1477f013bcdSZachary Turner         lldb_r13_x86_64,
1487f013bcdSZachary Turner         lldb_r14_x86_64,
1497f013bcdSZachary Turner         lldb_r15_x86_64,
1507f013bcdSZachary Turner         lldb_rip_x86_64,
1517f013bcdSZachary Turner         lldb_rflags_x86_64,
1527f013bcdSZachary Turner         lldb_cs_x86_64,
1537f013bcdSZachary Turner         lldb_fs_x86_64,
1547f013bcdSZachary Turner         lldb_gs_x86_64,
1557f013bcdSZachary Turner         lldb_ss_x86_64,
1567f013bcdSZachary Turner         lldb_ds_x86_64,
1577f013bcdSZachary Turner         lldb_es_x86_64,
1587f013bcdSZachary Turner         lldb_eax_x86_64,
1597f013bcdSZachary Turner         lldb_ebx_x86_64,
1607f013bcdSZachary Turner         lldb_ecx_x86_64,
1617f013bcdSZachary Turner         lldb_edx_x86_64,
1627f013bcdSZachary Turner         lldb_edi_x86_64,
1637f013bcdSZachary Turner         lldb_esi_x86_64,
1647f013bcdSZachary Turner         lldb_ebp_x86_64,
1657f013bcdSZachary Turner         lldb_esp_x86_64,
1667f013bcdSZachary Turner         lldb_r8d_x86_64,    // Low 32 bits or r8
1677f013bcdSZachary Turner         lldb_r9d_x86_64,    // Low 32 bits or r9
1687f013bcdSZachary Turner         lldb_r10d_x86_64,   // Low 32 bits or r10
1697f013bcdSZachary Turner         lldb_r11d_x86_64,   // Low 32 bits or r11
1707f013bcdSZachary Turner         lldb_r12d_x86_64,   // Low 32 bits or r12
1717f013bcdSZachary Turner         lldb_r13d_x86_64,   // Low 32 bits or r13
1727f013bcdSZachary Turner         lldb_r14d_x86_64,   // Low 32 bits or r14
1737f013bcdSZachary Turner         lldb_r15d_x86_64,   // Low 32 bits or r15
1747f013bcdSZachary Turner         lldb_ax_x86_64,
1757f013bcdSZachary Turner         lldb_bx_x86_64,
1767f013bcdSZachary Turner         lldb_cx_x86_64,
1777f013bcdSZachary Turner         lldb_dx_x86_64,
1787f013bcdSZachary Turner         lldb_di_x86_64,
1797f013bcdSZachary Turner         lldb_si_x86_64,
1807f013bcdSZachary Turner         lldb_bp_x86_64,
1817f013bcdSZachary Turner         lldb_sp_x86_64,
1827f013bcdSZachary Turner         lldb_r8w_x86_64,    // Low 16 bits or r8
1837f013bcdSZachary Turner         lldb_r9w_x86_64,    // Low 16 bits or r9
1847f013bcdSZachary Turner         lldb_r10w_x86_64,   // Low 16 bits or r10
1857f013bcdSZachary Turner         lldb_r11w_x86_64,   // Low 16 bits or r11
1867f013bcdSZachary Turner         lldb_r12w_x86_64,   // Low 16 bits or r12
1877f013bcdSZachary Turner         lldb_r13w_x86_64,   // Low 16 bits or r13
1887f013bcdSZachary Turner         lldb_r14w_x86_64,   // Low 16 bits or r14
1897f013bcdSZachary Turner         lldb_r15w_x86_64,   // Low 16 bits or r15
1907f013bcdSZachary Turner         lldb_ah_x86_64,
1917f013bcdSZachary Turner         lldb_bh_x86_64,
1927f013bcdSZachary Turner         lldb_ch_x86_64,
1937f013bcdSZachary Turner         lldb_dh_x86_64,
1947f013bcdSZachary Turner         lldb_al_x86_64,
1957f013bcdSZachary Turner         lldb_bl_x86_64,
1967f013bcdSZachary Turner         lldb_cl_x86_64,
1977f013bcdSZachary Turner         lldb_dl_x86_64,
1987f013bcdSZachary Turner         lldb_dil_x86_64,
1997f013bcdSZachary Turner         lldb_sil_x86_64,
2007f013bcdSZachary Turner         lldb_bpl_x86_64,
2017f013bcdSZachary Turner         lldb_spl_x86_64,
2027f013bcdSZachary Turner         lldb_r8l_x86_64,    // Low 8 bits or r8
2037f013bcdSZachary Turner         lldb_r9l_x86_64,    // Low 8 bits or r9
2047f013bcdSZachary Turner         lldb_r10l_x86_64,   // Low 8 bits or r10
2057f013bcdSZachary Turner         lldb_r11l_x86_64,   // Low 8 bits or r11
2067f013bcdSZachary Turner         lldb_r12l_x86_64,   // Low 8 bits or r12
2077f013bcdSZachary Turner         lldb_r13l_x86_64,   // Low 8 bits or r13
2087f013bcdSZachary Turner         lldb_r14l_x86_64,   // Low 8 bits or r14
2097f013bcdSZachary Turner         lldb_r15l_x86_64,   // Low 8 bits or r15
2102850b1beSTodd Fiala         LLDB_INVALID_REGNUM // register sets need to end with this flag
2112850b1beSTodd Fiala     };
2122850b1beSTodd Fiala     static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - 1 == k_num_gpr_registers_x86_64,
2132850b1beSTodd Fiala                   "g_gpr_regnums_x86_64 has wrong number of register infos");
2142850b1beSTodd Fiala 
2152850b1beSTodd Fiala     // x86 64-bit floating point registers.
2162850b1beSTodd Fiala     static const uint32_t
2172850b1beSTodd Fiala     g_fpu_regnums_x86_64[] =
2182850b1beSTodd Fiala     {
2197f013bcdSZachary Turner         lldb_fctrl_x86_64,
2207f013bcdSZachary Turner         lldb_fstat_x86_64,
2217f013bcdSZachary Turner         lldb_ftag_x86_64,
2227f013bcdSZachary Turner         lldb_fop_x86_64,
2237f013bcdSZachary Turner         lldb_fiseg_x86_64,
2247f013bcdSZachary Turner         lldb_fioff_x86_64,
2257f013bcdSZachary Turner         lldb_foseg_x86_64,
2267f013bcdSZachary Turner         lldb_fooff_x86_64,
2277f013bcdSZachary Turner         lldb_mxcsr_x86_64,
2287f013bcdSZachary Turner         lldb_mxcsrmask_x86_64,
2297f013bcdSZachary Turner         lldb_st0_x86_64,
2307f013bcdSZachary Turner         lldb_st1_x86_64,
2317f013bcdSZachary Turner         lldb_st2_x86_64,
2327f013bcdSZachary Turner         lldb_st3_x86_64,
2337f013bcdSZachary Turner         lldb_st4_x86_64,
2347f013bcdSZachary Turner         lldb_st5_x86_64,
2357f013bcdSZachary Turner         lldb_st6_x86_64,
2367f013bcdSZachary Turner         lldb_st7_x86_64,
2377f013bcdSZachary Turner         lldb_mm0_x86_64,
2387f013bcdSZachary Turner         lldb_mm1_x86_64,
2397f013bcdSZachary Turner         lldb_mm2_x86_64,
2407f013bcdSZachary Turner         lldb_mm3_x86_64,
2417f013bcdSZachary Turner         lldb_mm4_x86_64,
2427f013bcdSZachary Turner         lldb_mm5_x86_64,
2437f013bcdSZachary Turner         lldb_mm6_x86_64,
2447f013bcdSZachary Turner         lldb_mm7_x86_64,
2457f013bcdSZachary Turner         lldb_xmm0_x86_64,
2467f013bcdSZachary Turner         lldb_xmm1_x86_64,
2477f013bcdSZachary Turner         lldb_xmm2_x86_64,
2487f013bcdSZachary Turner         lldb_xmm3_x86_64,
2497f013bcdSZachary Turner         lldb_xmm4_x86_64,
2507f013bcdSZachary Turner         lldb_xmm5_x86_64,
2517f013bcdSZachary Turner         lldb_xmm6_x86_64,
2527f013bcdSZachary Turner         lldb_xmm7_x86_64,
2537f013bcdSZachary Turner         lldb_xmm8_x86_64,
2547f013bcdSZachary Turner         lldb_xmm9_x86_64,
2557f013bcdSZachary Turner         lldb_xmm10_x86_64,
2567f013bcdSZachary Turner         lldb_xmm11_x86_64,
2577f013bcdSZachary Turner         lldb_xmm12_x86_64,
2587f013bcdSZachary Turner         lldb_xmm13_x86_64,
2597f013bcdSZachary Turner         lldb_xmm14_x86_64,
2607f013bcdSZachary Turner         lldb_xmm15_x86_64,
2612850b1beSTodd Fiala         LLDB_INVALID_REGNUM // register sets need to end with this flag
2622850b1beSTodd Fiala     };
2632850b1beSTodd Fiala     static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) - 1 == k_num_fpr_registers_x86_64,
2642850b1beSTodd Fiala                   "g_fpu_regnums_x86_64 has wrong number of register infos");
2652850b1beSTodd Fiala 
2662850b1beSTodd Fiala     // x86 64-bit AVX registers.
2672850b1beSTodd Fiala     static const uint32_t
2682850b1beSTodd Fiala     g_avx_regnums_x86_64[] =
2692850b1beSTodd Fiala     {
2707f013bcdSZachary Turner         lldb_ymm0_x86_64,
2717f013bcdSZachary Turner         lldb_ymm1_x86_64,
2727f013bcdSZachary Turner         lldb_ymm2_x86_64,
2737f013bcdSZachary Turner         lldb_ymm3_x86_64,
2747f013bcdSZachary Turner         lldb_ymm4_x86_64,
2757f013bcdSZachary Turner         lldb_ymm5_x86_64,
2767f013bcdSZachary Turner         lldb_ymm6_x86_64,
2777f013bcdSZachary Turner         lldb_ymm7_x86_64,
2787f013bcdSZachary Turner         lldb_ymm8_x86_64,
2797f013bcdSZachary Turner         lldb_ymm9_x86_64,
2807f013bcdSZachary Turner         lldb_ymm10_x86_64,
2817f013bcdSZachary Turner         lldb_ymm11_x86_64,
2827f013bcdSZachary Turner         lldb_ymm12_x86_64,
2837f013bcdSZachary Turner         lldb_ymm13_x86_64,
2847f013bcdSZachary Turner         lldb_ymm14_x86_64,
2857f013bcdSZachary Turner         lldb_ymm15_x86_64,
2862850b1beSTodd Fiala         LLDB_INVALID_REGNUM // register sets need to end with this flag
2872850b1beSTodd Fiala     };
2882850b1beSTodd Fiala     static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - 1 == k_num_avx_registers_x86_64,
2892850b1beSTodd Fiala                   "g_avx_regnums_x86_64 has wrong number of register infos");
2902850b1beSTodd Fiala 
2912850b1beSTodd Fiala     // Number of register sets provided by this context.
2922850b1beSTodd Fiala     enum
2932850b1beSTodd Fiala     {
2942850b1beSTodd Fiala         k_num_extended_register_sets = 1,
2952850b1beSTodd Fiala         k_num_register_sets = 3
2962850b1beSTodd Fiala     };
2972850b1beSTodd Fiala 
2982850b1beSTodd Fiala     // Register sets for x86 32-bit.
2992850b1beSTodd Fiala     static const RegisterSet
3002850b1beSTodd Fiala     g_reg_sets_i386[k_num_register_sets] =
3012850b1beSTodd Fiala     {
3022850b1beSTodd Fiala         { "General Purpose Registers",  "gpr", k_num_gpr_registers_i386, g_gpr_regnums_i386 },
3032850b1beSTodd Fiala         { "Floating Point Registers",   "fpu", k_num_fpr_registers_i386, g_fpu_regnums_i386 },
3042850b1beSTodd Fiala         { "Advanced Vector Extensions", "avx", k_num_avx_registers_i386, g_avx_regnums_i386 }
3052850b1beSTodd Fiala     };
3062850b1beSTodd Fiala 
3072850b1beSTodd Fiala     // Register sets for x86 64-bit.
3082850b1beSTodd Fiala     static const RegisterSet
3092850b1beSTodd Fiala     g_reg_sets_x86_64[k_num_register_sets] =
3102850b1beSTodd Fiala     {
3112850b1beSTodd Fiala         { "General Purpose Registers",  "gpr", k_num_gpr_registers_x86_64, g_gpr_regnums_x86_64 },
3122850b1beSTodd Fiala         { "Floating Point Registers",   "fpu", k_num_fpr_registers_x86_64, g_fpu_regnums_x86_64 },
3132850b1beSTodd Fiala         { "Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, g_avx_regnums_x86_64 }
3142850b1beSTodd Fiala     };
3152850b1beSTodd Fiala }
3162850b1beSTodd Fiala 
3172850b1beSTodd Fiala #define REG_CONTEXT_SIZE (GetRegisterInfoInterface ().GetGPRSize () + sizeof(FPR))
3182850b1beSTodd Fiala 
3192850b1beSTodd Fiala // ----------------------------------------------------------------------------
3202850b1beSTodd Fiala // Required ptrace defines.
3212850b1beSTodd Fiala // ----------------------------------------------------------------------------
3222850b1beSTodd Fiala 
3232850b1beSTodd Fiala // Support ptrace extensions even when compiled without required kernel support
3242850b1beSTodd Fiala #ifndef NT_X86_XSTATE
3252850b1beSTodd Fiala #define NT_X86_XSTATE 0x202
3262850b1beSTodd Fiala #endif
3272850b1beSTodd Fiala 
3282850b1beSTodd Fiala // ----------------------------------------------------------------------------
3292850b1beSTodd Fiala // NativeRegisterContextLinux_x86_64 members.
3302850b1beSTodd Fiala // ----------------------------------------------------------------------------
3312850b1beSTodd Fiala 
3322850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p) :
3332850b1beSTodd Fiala     NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p),
3342850b1beSTodd Fiala     m_fpr_type (eFPRTypeNotValid),
3352850b1beSTodd Fiala     m_fpr (),
3362850b1beSTodd Fiala     m_iovec (),
3372850b1beSTodd Fiala     m_ymm_set (),
3382850b1beSTodd Fiala     m_reg_info (),
3392850b1beSTodd Fiala     m_gpr_x86_64 ()
3402850b1beSTodd Fiala {
3412850b1beSTodd Fiala     // Set up data about ranges of valid registers.
3422850b1beSTodd Fiala     switch (reg_info_interface_p->GetTargetArchitecture ().GetMachine ())
3432850b1beSTodd Fiala     {
3442850b1beSTodd Fiala         case llvm::Triple::x86:
3452850b1beSTodd Fiala             m_reg_info.num_registers        = k_num_registers_i386;
3462850b1beSTodd Fiala             m_reg_info.num_gpr_registers    = k_num_gpr_registers_i386;
3472850b1beSTodd Fiala             m_reg_info.num_fpr_registers    = k_num_fpr_registers_i386;
3482850b1beSTodd Fiala             m_reg_info.num_avx_registers    = k_num_avx_registers_i386;
3492850b1beSTodd Fiala             m_reg_info.last_gpr             = k_last_gpr_i386;
3502850b1beSTodd Fiala             m_reg_info.first_fpr            = k_first_fpr_i386;
3512850b1beSTodd Fiala             m_reg_info.last_fpr             = k_last_fpr_i386;
3527f013bcdSZachary Turner             m_reg_info.first_st             = lldb_st0_i386;
3537f013bcdSZachary Turner             m_reg_info.last_st              = lldb_st7_i386;
3547f013bcdSZachary Turner             m_reg_info.first_mm             = lldb_mm0_i386;
3557f013bcdSZachary Turner             m_reg_info.last_mm              = lldb_mm7_i386;
3567f013bcdSZachary Turner             m_reg_info.first_xmm            = lldb_xmm0_i386;
3577f013bcdSZachary Turner             m_reg_info.last_xmm             = lldb_xmm7_i386;
3587f013bcdSZachary Turner             m_reg_info.first_ymm            = lldb_ymm0_i386;
3597f013bcdSZachary Turner             m_reg_info.last_ymm             = lldb_ymm7_i386;
3607f013bcdSZachary Turner             m_reg_info.first_dr             = lldb_dr0_i386;
3617f013bcdSZachary Turner             m_reg_info.gpr_flags            = lldb_eflags_i386;
3622850b1beSTodd Fiala             break;
3632850b1beSTodd Fiala         case llvm::Triple::x86_64:
3642850b1beSTodd Fiala             m_reg_info.num_registers        = k_num_registers_x86_64;
3652850b1beSTodd Fiala             m_reg_info.num_gpr_registers    = k_num_gpr_registers_x86_64;
3662850b1beSTodd Fiala             m_reg_info.num_fpr_registers    = k_num_fpr_registers_x86_64;
3672850b1beSTodd Fiala             m_reg_info.num_avx_registers    = k_num_avx_registers_x86_64;
3682850b1beSTodd Fiala             m_reg_info.last_gpr             = k_last_gpr_x86_64;
3692850b1beSTodd Fiala             m_reg_info.first_fpr            = k_first_fpr_x86_64;
3702850b1beSTodd Fiala             m_reg_info.last_fpr             = k_last_fpr_x86_64;
3717f013bcdSZachary Turner             m_reg_info.first_st             = lldb_st0_x86_64;
3727f013bcdSZachary Turner             m_reg_info.last_st              = lldb_st7_x86_64;
3737f013bcdSZachary Turner             m_reg_info.first_mm             = lldb_mm0_x86_64;
3747f013bcdSZachary Turner             m_reg_info.last_mm              = lldb_mm7_x86_64;
3757f013bcdSZachary Turner             m_reg_info.first_xmm            = lldb_xmm0_x86_64;
3767f013bcdSZachary Turner             m_reg_info.last_xmm             = lldb_xmm15_x86_64;
3777f013bcdSZachary Turner             m_reg_info.first_ymm            = lldb_ymm0_x86_64;
3787f013bcdSZachary Turner             m_reg_info.last_ymm             = lldb_ymm15_x86_64;
3797f013bcdSZachary Turner             m_reg_info.first_dr             = lldb_dr0_x86_64;
3807f013bcdSZachary Turner             m_reg_info.gpr_flags            = lldb_rflags_x86_64;
3812850b1beSTodd Fiala             break;
3822850b1beSTodd Fiala         default:
3832850b1beSTodd Fiala             assert(false && "Unhandled target architecture.");
3842850b1beSTodd Fiala             break;
3852850b1beSTodd Fiala     }
3862850b1beSTodd Fiala 
3872850b1beSTodd Fiala     // Initialize m_iovec to point to the buffer and buffer size
3882850b1beSTodd Fiala     // using the conventions of Berkeley style UIO structures, as required
3892850b1beSTodd Fiala     // by PTRACE extensions.
3902850b1beSTodd Fiala     m_iovec.iov_base = &m_fpr.xstate.xsave;
3912850b1beSTodd Fiala     m_iovec.iov_len = sizeof(m_fpr.xstate.xsave);
3922850b1beSTodd Fiala 
3932850b1beSTodd Fiala     // Clear out the FPR state.
3942850b1beSTodd Fiala     ::memset(&m_fpr, 0, sizeof(FPR));
3952850b1beSTodd Fiala }
3962850b1beSTodd Fiala 
3972850b1beSTodd Fiala // CONSIDER after local and llgs debugging are merged, register set support can
3982850b1beSTodd Fiala // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual.
3992850b1beSTodd Fiala uint32_t
4002850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::GetRegisterSetCount () const
4012850b1beSTodd Fiala {
4022850b1beSTodd Fiala     uint32_t sets = 0;
4032850b1beSTodd Fiala     for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
4042850b1beSTodd Fiala     {
4052850b1beSTodd Fiala         if (IsRegisterSetAvailable (set_index))
4062850b1beSTodd Fiala             ++sets;
4072850b1beSTodd Fiala     }
4082850b1beSTodd Fiala 
4092850b1beSTodd Fiala     return sets;
4102850b1beSTodd Fiala }
4112850b1beSTodd Fiala 
4128fa23b8eSTamas Berghammer uint32_t
4138fa23b8eSTamas Berghammer NativeRegisterContextLinux_x86_64::GetUserRegisterCount() const
4148fa23b8eSTamas Berghammer {
4158fa23b8eSTamas Berghammer     uint32_t count = 0;
4168fa23b8eSTamas Berghammer     for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
4178fa23b8eSTamas Berghammer     {
4188fa23b8eSTamas Berghammer         const lldb_private::RegisterSet* set = GetRegisterSet(set_index);
4198fa23b8eSTamas Berghammer         if (set)
4208fa23b8eSTamas Berghammer             count += set->num_registers;
4218fa23b8eSTamas Berghammer     }
4228fa23b8eSTamas Berghammer     return count;
4238fa23b8eSTamas Berghammer }
4248fa23b8eSTamas Berghammer 
4252850b1beSTodd Fiala const lldb_private::RegisterSet *
4262850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::GetRegisterSet (uint32_t set_index) const
4272850b1beSTodd Fiala {
4282850b1beSTodd Fiala     if (!IsRegisterSetAvailable (set_index))
4292850b1beSTodd Fiala         return nullptr;
4302850b1beSTodd Fiala 
4312850b1beSTodd Fiala     switch (GetRegisterInfoInterface ().GetTargetArchitecture ().GetMachine ())
4322850b1beSTodd Fiala     {
4332850b1beSTodd Fiala         case llvm::Triple::x86:
4342850b1beSTodd Fiala             return &g_reg_sets_i386[set_index];
4352850b1beSTodd Fiala         case llvm::Triple::x86_64:
4362850b1beSTodd Fiala             return &g_reg_sets_x86_64[set_index];
4372850b1beSTodd Fiala         default:
4382850b1beSTodd Fiala             assert (false && "Unhandled target architecture.");
4392850b1beSTodd Fiala             return nullptr;
4402850b1beSTodd Fiala     }
4412850b1beSTodd Fiala 
4422850b1beSTodd Fiala     return nullptr;
4432850b1beSTodd Fiala }
4442850b1beSTodd Fiala 
4452850b1beSTodd Fiala lldb_private::Error
4462850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::ReadRegisterRaw (uint32_t reg_index, RegisterValue &reg_value)
4472850b1beSTodd Fiala {
4482850b1beSTodd Fiala     Error error;
4492850b1beSTodd Fiala     const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index);
4502850b1beSTodd Fiala     if (!reg_info)
4512850b1beSTodd Fiala     {
4522850b1beSTodd Fiala         error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index);
4532850b1beSTodd Fiala         return error;
4542850b1beSTodd Fiala     }
4552850b1beSTodd Fiala 
4562850b1beSTodd Fiala     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
4572850b1beSTodd Fiala     if (!process_sp)
4582850b1beSTodd Fiala     {
4592850b1beSTodd Fiala         error.SetErrorString ("NativeProcessProtocol is NULL");
4602850b1beSTodd Fiala         return error;
4612850b1beSTodd Fiala     }
4622850b1beSTodd Fiala 
4632850b1beSTodd Fiala     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
46497ccc294SChaoren Lin     return process_p->ReadRegisterValue(m_thread.GetID(),
4652850b1beSTodd Fiala                                         reg_info->byte_offset,
4662850b1beSTodd Fiala                                         reg_info->name,
4672850b1beSTodd Fiala                                         reg_info->byte_size,
46897ccc294SChaoren Lin                                         reg_value);
4692850b1beSTodd Fiala }
4702850b1beSTodd Fiala 
4712850b1beSTodd Fiala lldb_private::Error
4722850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
4732850b1beSTodd Fiala {
4742850b1beSTodd Fiala     Error error;
4752850b1beSTodd Fiala 
4762850b1beSTodd Fiala     if (!reg_info)
4772850b1beSTodd Fiala     {
4782850b1beSTodd Fiala         error.SetErrorString ("reg_info NULL");
4792850b1beSTodd Fiala         return error;
4802850b1beSTodd Fiala     }
4812850b1beSTodd Fiala 
4822850b1beSTodd Fiala     const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
4832850b1beSTodd Fiala     if (reg == LLDB_INVALID_REGNUM)
4842850b1beSTodd Fiala     {
4852850b1beSTodd Fiala         // This is likely an internal register for lldb use only and should not be directly queried.
4862850b1beSTodd Fiala         error.SetErrorStringWithFormat ("register \"%s\" is an internal-only lldb register, cannot read directly", reg_info->name);
4872850b1beSTodd Fiala         return error;
4882850b1beSTodd Fiala     }
4892850b1beSTodd Fiala 
4902850b1beSTodd Fiala     if (IsFPR(reg, GetFPRType()))
4912850b1beSTodd Fiala     {
4922850b1beSTodd Fiala         if (!ReadFPR())
4932850b1beSTodd Fiala         {
4942850b1beSTodd Fiala             error.SetErrorString ("failed to read floating point register");
4952850b1beSTodd Fiala             return error;
4962850b1beSTodd Fiala         }
4972850b1beSTodd Fiala     }
4982850b1beSTodd Fiala     else
4992850b1beSTodd Fiala     {
5002850b1beSTodd Fiala         uint32_t full_reg = reg;
5012850b1beSTodd Fiala         bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
5022850b1beSTodd Fiala 
5032850b1beSTodd Fiala         if (is_subreg)
5042850b1beSTodd Fiala         {
5052850b1beSTodd Fiala             // Read the full aligned 64-bit register.
5062850b1beSTodd Fiala             full_reg = reg_info->invalidate_regs[0];
5072850b1beSTodd Fiala         }
5082850b1beSTodd Fiala 
5092850b1beSTodd Fiala         error = ReadRegisterRaw(full_reg, reg_value);
5102850b1beSTodd Fiala 
5112850b1beSTodd Fiala         if (error.Success ())
5122850b1beSTodd Fiala         {
5132850b1beSTodd Fiala             // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
5142850b1beSTodd Fiala             if (is_subreg && (reg_info->byte_offset & 0x1))
5152850b1beSTodd Fiala                 reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
5162850b1beSTodd Fiala 
5172850b1beSTodd Fiala             // If our return byte size was greater than the return value reg size, then
5182850b1beSTodd Fiala             // use the type specified by reg_info rather than the uint64_t default
5192850b1beSTodd Fiala             if (reg_value.GetByteSize() > reg_info->byte_size)
5202850b1beSTodd Fiala                 reg_value.SetType(reg_info);
5212850b1beSTodd Fiala         }
5222850b1beSTodd Fiala         return error;
5232850b1beSTodd Fiala     }
5242850b1beSTodd Fiala 
5252850b1beSTodd Fiala     if (reg_info->encoding == lldb::eEncodingVector)
5262850b1beSTodd Fiala     {
5272850b1beSTodd Fiala         lldb::ByteOrder byte_order = GetByteOrder();
5282850b1beSTodd Fiala 
5292850b1beSTodd Fiala         if (byte_order != lldb::eByteOrderInvalid)
5302850b1beSTodd Fiala         {
5312850b1beSTodd Fiala             if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
5322850b1beSTodd Fiala                 reg_value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, reg_info->byte_size, byte_order);
5332850b1beSTodd Fiala             if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
5342850b1beSTodd Fiala                 reg_value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, reg_info->byte_size, byte_order);
5352850b1beSTodd Fiala             if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
5362850b1beSTodd Fiala                 reg_value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, reg_info->byte_size, byte_order);
5372850b1beSTodd Fiala             if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm)
5382850b1beSTodd Fiala             {
5392850b1beSTodd Fiala                 // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
5402850b1beSTodd Fiala                 if (GetFPRType() == eFPRTypeXSAVE && CopyXSTATEtoYMM(reg, byte_order))
5412850b1beSTodd Fiala                     reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, reg_info->byte_size, byte_order);
5422850b1beSTodd Fiala                 else
5432850b1beSTodd Fiala                 {
5442850b1beSTodd Fiala                     error.SetErrorString ("failed to copy ymm register value");
5452850b1beSTodd Fiala                     return error;
5462850b1beSTodd Fiala                 }
5472850b1beSTodd Fiala             }
5482850b1beSTodd Fiala 
5492850b1beSTodd Fiala             if (reg_value.GetType() != RegisterValue::eTypeBytes)
5502850b1beSTodd Fiala                 error.SetErrorString ("write failed - type was expected to be RegisterValue::eTypeBytes");
5512850b1beSTodd Fiala 
5522850b1beSTodd Fiala             return error;
5532850b1beSTodd Fiala         }
5542850b1beSTodd Fiala 
5552850b1beSTodd Fiala         error.SetErrorString ("byte order is invalid");
5562850b1beSTodd Fiala         return error;
5572850b1beSTodd Fiala     }
5582850b1beSTodd Fiala 
5592850b1beSTodd Fiala     // Get pointer to m_fpr.xstate.fxsave variable and set the data from it.
5602850b1beSTodd Fiala     assert (reg_info->byte_offset < sizeof(m_fpr));
5612850b1beSTodd Fiala     uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
5622850b1beSTodd Fiala     switch (reg_info->byte_size)
5632850b1beSTodd Fiala     {
5642850b1beSTodd Fiala         case 2:
5652850b1beSTodd Fiala             reg_value.SetUInt16(*(uint16_t *)src);
5662850b1beSTodd Fiala             break;
5672850b1beSTodd Fiala         case 4:
5682850b1beSTodd Fiala             reg_value.SetUInt32(*(uint32_t *)src);
5692850b1beSTodd Fiala             break;
5702850b1beSTodd Fiala         case 8:
5712850b1beSTodd Fiala             reg_value.SetUInt64(*(uint64_t *)src);
5722850b1beSTodd Fiala             break;
5732850b1beSTodd Fiala         default:
5742850b1beSTodd Fiala             assert(false && "Unhandled data size.");
5752850b1beSTodd Fiala             error.SetErrorStringWithFormat ("unhandled byte size: %" PRIu32, reg_info->byte_size);
5762850b1beSTodd Fiala             break;
5772850b1beSTodd Fiala     }
5782850b1beSTodd Fiala 
5792850b1beSTodd Fiala     return error;
5802850b1beSTodd Fiala }
5812850b1beSTodd Fiala 
5822850b1beSTodd Fiala lldb_private::Error
5832850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::WriteRegister(const uint32_t reg,
5842850b1beSTodd Fiala                                                  const RegisterValue &value)
5852850b1beSTodd Fiala {
5862850b1beSTodd Fiala     Error error;
5872850b1beSTodd Fiala 
5882850b1beSTodd Fiala     uint32_t reg_to_write = reg;
5892850b1beSTodd Fiala     RegisterValue value_to_write = value;
5902850b1beSTodd Fiala 
5912850b1beSTodd Fiala     // Check if this is a subregister of a full register.
5922850b1beSTodd Fiala     const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
5932850b1beSTodd Fiala     if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
5942850b1beSTodd Fiala     {
5952850b1beSTodd Fiala         RegisterValue full_value;
5962850b1beSTodd Fiala         uint32_t full_reg = reg_info->invalidate_regs[0];
5972850b1beSTodd Fiala         const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
5982850b1beSTodd Fiala 
5992850b1beSTodd Fiala         // Read the full register.
6002850b1beSTodd Fiala         error = ReadRegister(full_reg_info, full_value);
6012850b1beSTodd Fiala         if (error.Fail ())
6022850b1beSTodd Fiala             return error;
6032850b1beSTodd Fiala 
6042850b1beSTodd Fiala         lldb::ByteOrder byte_order = GetByteOrder();
6052850b1beSTodd Fiala         uint8_t dst[RegisterValue::kMaxRegisterByteSize];
6062850b1beSTodd Fiala 
6072850b1beSTodd Fiala         // Get the bytes for the full register.
6082850b1beSTodd Fiala         const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
6092850b1beSTodd Fiala                                                                dst,
6102850b1beSTodd Fiala                                                                sizeof(dst),
6112850b1beSTodd Fiala                                                                byte_order,
6122850b1beSTodd Fiala                                                                error);
6132850b1beSTodd Fiala         if (error.Success() && dest_size)
6142850b1beSTodd Fiala         {
6152850b1beSTodd Fiala             uint8_t src[RegisterValue::kMaxRegisterByteSize];
6162850b1beSTodd Fiala 
6172850b1beSTodd Fiala             // Get the bytes for the source data.
6182850b1beSTodd Fiala             const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
6192850b1beSTodd Fiala             if (error.Success() && src_size && (src_size < dest_size))
6202850b1beSTodd Fiala             {
6212850b1beSTodd Fiala                 // Copy the src bytes to the destination.
6222850b1beSTodd Fiala                 memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
6232850b1beSTodd Fiala                 // Set this full register as the value to write.
6242850b1beSTodd Fiala                 value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
6252850b1beSTodd Fiala                 value_to_write.SetType(full_reg_info);
6262850b1beSTodd Fiala                 reg_to_write = full_reg;
6272850b1beSTodd Fiala             }
6282850b1beSTodd Fiala         }
6292850b1beSTodd Fiala     }
6302850b1beSTodd Fiala 
6312850b1beSTodd Fiala 
6322850b1beSTodd Fiala     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
6332850b1beSTodd Fiala     if (!process_sp)
6342850b1beSTodd Fiala     {
6352850b1beSTodd Fiala         error.SetErrorString ("NativeProcessProtocol is NULL");
6362850b1beSTodd Fiala         return error;
6372850b1beSTodd Fiala     }
6382850b1beSTodd Fiala 
6392850b1beSTodd Fiala     const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write);
6402850b1beSTodd Fiala     assert (register_to_write_info_p && "register to write does not have valid RegisterInfo");
6412850b1beSTodd Fiala     if (!register_to_write_info_p)
6422850b1beSTodd Fiala     {
6432850b1beSTodd Fiala         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write);
6442850b1beSTodd Fiala         return error;
6452850b1beSTodd Fiala     }
6462850b1beSTodd Fiala 
6472850b1beSTodd Fiala     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
64897ccc294SChaoren Lin     return process_p->WriteRegisterValue(m_thread.GetID(),
6492850b1beSTodd Fiala                                          register_to_write_info_p->byte_offset,
6502850b1beSTodd Fiala                                          register_to_write_info_p->name,
65197ccc294SChaoren Lin                                          value_to_write);
6522850b1beSTodd Fiala }
6532850b1beSTodd Fiala 
6542850b1beSTodd Fiala lldb_private::Error
6552850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
6562850b1beSTodd Fiala {
6572850b1beSTodd Fiala     assert (reg_info && "reg_info is null");
6582850b1beSTodd Fiala 
6592850b1beSTodd Fiala     const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
6602850b1beSTodd Fiala     if (reg_index == LLDB_INVALID_REGNUM)
6612850b1beSTodd Fiala         return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>");
6622850b1beSTodd Fiala 
6632850b1beSTodd Fiala     if (IsGPR(reg_index))
6642850b1beSTodd Fiala         return WriteRegister(reg_index, reg_value);
6652850b1beSTodd Fiala 
6662850b1beSTodd Fiala     if (IsFPR(reg_index, GetFPRType()))
6672850b1beSTodd Fiala     {
6682850b1beSTodd Fiala         if (reg_info->encoding == lldb::eEncodingVector)
6692850b1beSTodd Fiala         {
6702850b1beSTodd Fiala             if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st)
6712850b1beSTodd Fiala                 ::memcpy (m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_st].bytes, reg_value.GetBytes(), reg_value.GetByteSize());
6722850b1beSTodd Fiala 
6732850b1beSTodd Fiala             if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm)
6742850b1beSTodd Fiala                 ::memcpy (m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes, reg_value.GetBytes(), reg_value.GetByteSize());
6752850b1beSTodd Fiala 
6762850b1beSTodd Fiala             if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm)
6772850b1beSTodd Fiala                 ::memcpy (m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes, reg_value.GetBytes(), reg_value.GetByteSize());
6782850b1beSTodd Fiala 
6792850b1beSTodd Fiala             if (reg_index >= m_reg_info.first_ymm && reg_index <= m_reg_info.last_ymm)
6802850b1beSTodd Fiala             {
6812850b1beSTodd Fiala                 if (GetFPRType() != eFPRTypeXSAVE)
6822850b1beSTodd Fiala                     return Error ("target processor does not support AVX");
6832850b1beSTodd Fiala 
6842850b1beSTodd Fiala                 // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes
6852850b1beSTodd Fiala                 ::memcpy (m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, reg_value.GetBytes(), reg_value.GetByteSize());
6862850b1beSTodd Fiala                 if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
6872850b1beSTodd Fiala                     return Error ("CopyYMMtoXSTATE() failed");
6882850b1beSTodd Fiala             }
6892850b1beSTodd Fiala         }
6902850b1beSTodd Fiala         else
6912850b1beSTodd Fiala         {
6922850b1beSTodd Fiala             // Get pointer to m_fpr.xstate.fxsave variable and set the data to it.
6932850b1beSTodd Fiala             assert (reg_info->byte_offset < sizeof(m_fpr));
6942850b1beSTodd Fiala             uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset;
6952850b1beSTodd Fiala             switch (reg_info->byte_size)
6962850b1beSTodd Fiala             {
6972850b1beSTodd Fiala                 case 2:
6982850b1beSTodd Fiala                     *(uint16_t *)dst = reg_value.GetAsUInt16();
6992850b1beSTodd Fiala                     break;
7002850b1beSTodd Fiala                 case 4:
7012850b1beSTodd Fiala                     *(uint32_t *)dst = reg_value.GetAsUInt32();
7022850b1beSTodd Fiala                     break;
7032850b1beSTodd Fiala                 case 8:
7042850b1beSTodd Fiala                     *(uint64_t *)dst = reg_value.GetAsUInt64();
7052850b1beSTodd Fiala                     break;
7062850b1beSTodd Fiala                 default:
7072850b1beSTodd Fiala                     assert(false && "Unhandled data size.");
7082850b1beSTodd Fiala                     return Error ("unhandled register data size %" PRIu32, reg_info->byte_size);
7092850b1beSTodd Fiala             }
7102850b1beSTodd Fiala         }
7112850b1beSTodd Fiala 
7122850b1beSTodd Fiala         if (WriteFPR())
7132850b1beSTodd Fiala         {
7142850b1beSTodd Fiala             if (IsAVX(reg_index))
7152850b1beSTodd Fiala             {
7162850b1beSTodd Fiala                 if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
7172850b1beSTodd Fiala                     return Error ("CopyYMMtoXSTATE() failed");
7182850b1beSTodd Fiala             }
7192850b1beSTodd Fiala             return Error ();
7202850b1beSTodd Fiala         }
7212850b1beSTodd Fiala     }
7222850b1beSTodd Fiala     return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown");
7232850b1beSTodd Fiala }
7242850b1beSTodd Fiala 
7252850b1beSTodd Fiala lldb_private::Error
7262850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
7272850b1beSTodd Fiala {
7282850b1beSTodd Fiala     Error error;
7292850b1beSTodd Fiala 
7302850b1beSTodd Fiala     data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
7312850b1beSTodd Fiala     if (!data_sp)
7322850b1beSTodd Fiala     {
7332850b1beSTodd Fiala         error.SetErrorStringWithFormat ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE);
7342850b1beSTodd Fiala         return error;
7352850b1beSTodd Fiala     }
7362850b1beSTodd Fiala 
7372850b1beSTodd Fiala     if (!ReadGPR ())
7382850b1beSTodd Fiala     {
7392850b1beSTodd Fiala         error.SetErrorString ("ReadGPR() failed");
7402850b1beSTodd Fiala         return error;
7412850b1beSTodd Fiala     }
7422850b1beSTodd Fiala 
7432850b1beSTodd Fiala     if (!ReadFPR ())
7442850b1beSTodd Fiala     {
7452850b1beSTodd Fiala         error.SetErrorString ("ReadFPR() failed");
7462850b1beSTodd Fiala         return error;
7472850b1beSTodd Fiala     }
7482850b1beSTodd Fiala 
7492850b1beSTodd Fiala     uint8_t *dst = data_sp->GetBytes ();
7502850b1beSTodd Fiala     if (dst == nullptr)
7512850b1beSTodd Fiala     {
7522850b1beSTodd Fiala         error.SetErrorStringWithFormat ("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE);
7532850b1beSTodd Fiala         return error;
7542850b1beSTodd Fiala     }
7552850b1beSTodd Fiala 
7562850b1beSTodd Fiala     ::memcpy (dst, &m_gpr_x86_64, GetRegisterInfoInterface ().GetGPRSize ());
7572850b1beSTodd Fiala     dst += GetRegisterInfoInterface ().GetGPRSize ();
7582850b1beSTodd Fiala     if (GetFPRType () == eFPRTypeFXSAVE)
7592850b1beSTodd Fiala         ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
7602850b1beSTodd Fiala     else if (GetFPRType () == eFPRTypeXSAVE)
7612850b1beSTodd Fiala     {
7622850b1beSTodd Fiala         lldb::ByteOrder byte_order = GetByteOrder ();
7632850b1beSTodd Fiala 
7642850b1beSTodd Fiala         // Assemble the YMM register content from the register halves.
7652850b1beSTodd Fiala         for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm; ++reg)
7662850b1beSTodd Fiala         {
7672850b1beSTodd Fiala             if (!CopyXSTATEtoYMM (reg, byte_order))
7682850b1beSTodd Fiala             {
7692850b1beSTodd Fiala                 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s CopyXSTATEtoYMM() failed for reg num %" PRIu32, __FUNCTION__, reg);
7702850b1beSTodd Fiala                 return error;
7712850b1beSTodd Fiala             }
7722850b1beSTodd Fiala         }
7732850b1beSTodd Fiala 
7742850b1beSTodd Fiala         // Copy the extended register state including the assembled ymm registers.
7752850b1beSTodd Fiala         ::memcpy (dst, &m_fpr, sizeof (m_fpr));
7762850b1beSTodd Fiala     }
7772850b1beSTodd Fiala     else
7782850b1beSTodd Fiala     {
7792850b1beSTodd Fiala         assert (false && "how do we save the floating point registers?");
7802850b1beSTodd Fiala         error.SetErrorString ("unsure how to save the floating point registers");
7812850b1beSTodd Fiala     }
7822850b1beSTodd Fiala 
7832850b1beSTodd Fiala     return error;
7842850b1beSTodd Fiala }
7852850b1beSTodd Fiala 
7862850b1beSTodd Fiala lldb_private::Error
7872850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
7882850b1beSTodd Fiala {
7892850b1beSTodd Fiala     Error error;
7902850b1beSTodd Fiala 
7912850b1beSTodd Fiala     if (!data_sp)
7922850b1beSTodd Fiala     {
7932850b1beSTodd Fiala         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__);
7942850b1beSTodd Fiala         return error;
7952850b1beSTodd Fiala     }
7962850b1beSTodd Fiala 
7972850b1beSTodd Fiala     if (data_sp->GetByteSize () != REG_CONTEXT_SIZE)
7982850b1beSTodd Fiala     {
7992850b1beSTodd Fiala         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize ());
8002850b1beSTodd Fiala         return error;
8012850b1beSTodd Fiala     }
8022850b1beSTodd Fiala 
8032850b1beSTodd Fiala 
8042850b1beSTodd Fiala     uint8_t *src = data_sp->GetBytes ();
8052850b1beSTodd Fiala     if (src == nullptr)
8062850b1beSTodd Fiala     {
8072850b1beSTodd Fiala         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__);
8082850b1beSTodd Fiala         return error;
8092850b1beSTodd Fiala     }
8102850b1beSTodd Fiala     ::memcpy (&m_gpr_x86_64, src, GetRegisterInfoInterface ().GetGPRSize ());
8112850b1beSTodd Fiala 
8122850b1beSTodd Fiala     if (!WriteGPR ())
8132850b1beSTodd Fiala     {
8142850b1beSTodd Fiala         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__);
8152850b1beSTodd Fiala         return error;
8162850b1beSTodd Fiala     }
8172850b1beSTodd Fiala 
8182850b1beSTodd Fiala     src += GetRegisterInfoInterface ().GetGPRSize ();
8192850b1beSTodd Fiala     if (GetFPRType () == eFPRTypeFXSAVE)
8202850b1beSTodd Fiala         ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave));
8212850b1beSTodd Fiala     else if (GetFPRType () == eFPRTypeXSAVE)
8222850b1beSTodd Fiala         ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
8232850b1beSTodd Fiala 
8242850b1beSTodd Fiala     if (!WriteFPR ())
8252850b1beSTodd Fiala     {
8262850b1beSTodd Fiala         error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__);
8272850b1beSTodd Fiala         return error;
8282850b1beSTodd Fiala     }
8292850b1beSTodd Fiala 
8302850b1beSTodd Fiala     if (GetFPRType() == eFPRTypeXSAVE)
8312850b1beSTodd Fiala     {
8322850b1beSTodd Fiala         lldb::ByteOrder byte_order = GetByteOrder();
8332850b1beSTodd Fiala 
8342850b1beSTodd Fiala         // Parse the YMM register content from the register halves.
8352850b1beSTodd Fiala         for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm; ++reg)
8362850b1beSTodd Fiala         {
8372850b1beSTodd Fiala             if (!CopyYMMtoXSTATE (reg, byte_order))
8382850b1beSTodd Fiala             {
8392850b1beSTodd Fiala                 error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s CopyYMMtoXSTATE() failed for reg num %" PRIu32, __FUNCTION__, reg);
8402850b1beSTodd Fiala                 return error;
8412850b1beSTodd Fiala             }
8422850b1beSTodd Fiala         }
8432850b1beSTodd Fiala     }
8442850b1beSTodd Fiala 
8452850b1beSTodd Fiala     return error;
8462850b1beSTodd Fiala }
8472850b1beSTodd Fiala 
8482850b1beSTodd Fiala bool
8492850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable (uint32_t set_index) const
8502850b1beSTodd Fiala {
8512850b1beSTodd Fiala     // Note: Extended register sets are assumed to be at the end of g_reg_sets.
8522850b1beSTodd Fiala     uint32_t num_sets = k_num_register_sets - k_num_extended_register_sets;
8532850b1beSTodd Fiala 
8542850b1beSTodd Fiala     if (GetFPRType () == eFPRTypeXSAVE)
8552850b1beSTodd Fiala     {
8562850b1beSTodd Fiala         // AVX is the first extended register set.
8572850b1beSTodd Fiala         ++num_sets;
8582850b1beSTodd Fiala     }
8592850b1beSTodd Fiala     return (set_index < num_sets);
8602850b1beSTodd Fiala }
8612850b1beSTodd Fiala 
8622850b1beSTodd Fiala lldb::ByteOrder
8632850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::GetByteOrder() const
8642850b1beSTodd Fiala {
8652850b1beSTodd Fiala     // Get the target process whose privileged thread was used for the register read.
8662850b1beSTodd Fiala     lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
8672850b1beSTodd Fiala 
8682850b1beSTodd Fiala     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
8692850b1beSTodd Fiala     if (!process_sp)
8702850b1beSTodd Fiala         return byte_order;
8712850b1beSTodd Fiala 
8722850b1beSTodd Fiala     if (!process_sp->GetByteOrder (byte_order))
8732850b1beSTodd Fiala     {
8742850b1beSTodd Fiala         // FIXME log here
8752850b1beSTodd Fiala     }
8762850b1beSTodd Fiala 
8772850b1beSTodd Fiala     return byte_order;
8782850b1beSTodd Fiala }
8792850b1beSTodd Fiala 
8802850b1beSTodd Fiala bool
8812850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const
8822850b1beSTodd Fiala {
8832850b1beSTodd Fiala     // GPRs come first.
8842850b1beSTodd Fiala     return reg_index <= m_reg_info.last_gpr;
8852850b1beSTodd Fiala }
8862850b1beSTodd Fiala 
8872850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::FPRType
8882850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::GetFPRType () const
8892850b1beSTodd Fiala {
8902850b1beSTodd Fiala     if (m_fpr_type == eFPRTypeNotValid)
8912850b1beSTodd Fiala     {
8922850b1beSTodd Fiala         // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx.
8932850b1beSTodd Fiala 
8942850b1beSTodd Fiala         // Try and see if AVX register retrieval works.
8952850b1beSTodd Fiala         m_fpr_type = eFPRTypeXSAVE;
8962850b1beSTodd Fiala         if (!const_cast<NativeRegisterContextLinux_x86_64*> (this)->ReadFPR ())
8972850b1beSTodd Fiala         {
8982850b1beSTodd Fiala             // Fall back to general floating point with no AVX support.
8992850b1beSTodd Fiala             m_fpr_type = eFPRTypeFXSAVE;
9002850b1beSTodd Fiala         }
9012850b1beSTodd Fiala     }
9022850b1beSTodd Fiala 
9032850b1beSTodd Fiala     return m_fpr_type;
9042850b1beSTodd Fiala }
9052850b1beSTodd Fiala 
9062850b1beSTodd Fiala bool
9072850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const
9082850b1beSTodd Fiala {
9092850b1beSTodd Fiala     return (m_reg_info.first_fpr <= reg_index && reg_index <= m_reg_info.last_fpr);
9102850b1beSTodd Fiala }
9112850b1beSTodd Fiala 
9122850b1beSTodd Fiala bool
9132850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index, FPRType fpr_type) const
9142850b1beSTodd Fiala {
9152850b1beSTodd Fiala     bool generic_fpr = IsFPR(reg_index);
9162850b1beSTodd Fiala 
9172850b1beSTodd Fiala     if (fpr_type == eFPRTypeXSAVE)
9182850b1beSTodd Fiala         return generic_fpr || IsAVX(reg_index);
9192850b1beSTodd Fiala     return generic_fpr;
9202850b1beSTodd Fiala }
9212850b1beSTodd Fiala 
9222850b1beSTodd Fiala bool
9232850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::WriteFPR()
9242850b1beSTodd Fiala {
9252850b1beSTodd Fiala     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
9262850b1beSTodd Fiala     if (!process_sp)
9272850b1beSTodd Fiala         return false;
9282850b1beSTodd Fiala     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
9292850b1beSTodd Fiala 
9302850b1beSTodd Fiala     if (GetFPRType() == eFPRTypeFXSAVE)
93197ccc294SChaoren Lin         return process_p->WriteFPR (m_thread.GetID (), &m_fpr.xstate.fxsave, sizeof (m_fpr.xstate.fxsave)).Success();
9322850b1beSTodd Fiala 
9332850b1beSTodd Fiala     if (GetFPRType() == eFPRTypeXSAVE)
93497ccc294SChaoren Lin         return process_p->WriteRegisterSet (m_thread.GetID (), &m_iovec, sizeof (m_fpr.xstate.xsave), NT_X86_XSTATE).Success();
9352850b1beSTodd Fiala     return false;
9362850b1beSTodd Fiala }
9372850b1beSTodd Fiala 
9382850b1beSTodd Fiala bool
9392850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const
9402850b1beSTodd Fiala {
9412850b1beSTodd Fiala     return (m_reg_info.first_ymm <= reg_index && reg_index <= m_reg_info.last_ymm);
9422850b1beSTodd Fiala }
9432850b1beSTodd Fiala 
9442850b1beSTodd Fiala bool
9452850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM (uint32_t reg_index, lldb::ByteOrder byte_order)
9462850b1beSTodd Fiala {
9472850b1beSTodd Fiala     if (!IsAVX (reg_index))
9482850b1beSTodd Fiala         return false;
9492850b1beSTodd Fiala 
9502850b1beSTodd Fiala     if (byte_order == lldb::eByteOrderLittle)
9512850b1beSTodd Fiala     {
9522850b1beSTodd Fiala         ::memcpy (m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
9532850b1beSTodd Fiala                  m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
9542850b1beSTodd Fiala                  sizeof (XMMReg));
9552850b1beSTodd Fiala         ::memcpy (m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + sizeof (XMMReg),
9562850b1beSTodd Fiala                  m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
9572850b1beSTodd Fiala                  sizeof (YMMHReg));
9582850b1beSTodd Fiala         return true;
9592850b1beSTodd Fiala     }
9602850b1beSTodd Fiala 
9612850b1beSTodd Fiala     if (byte_order == lldb::eByteOrderBig)
9622850b1beSTodd Fiala     {
9632850b1beSTodd Fiala         ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + sizeof (XMMReg),
9642850b1beSTodd Fiala                  m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
9652850b1beSTodd Fiala                  sizeof (XMMReg));
9662850b1beSTodd Fiala         ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
9672850b1beSTodd Fiala                  m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
9682850b1beSTodd Fiala                  sizeof (YMMHReg));
9692850b1beSTodd Fiala         return true;
9702850b1beSTodd Fiala     }
9712850b1beSTodd Fiala     return false; // unsupported or invalid byte order
9722850b1beSTodd Fiala 
9732850b1beSTodd Fiala }
9742850b1beSTodd Fiala 
9752850b1beSTodd Fiala bool
9762850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order)
9772850b1beSTodd Fiala {
9782850b1beSTodd Fiala     if (!IsAVX(reg))
9792850b1beSTodd Fiala         return false;
9802850b1beSTodd Fiala 
9812850b1beSTodd Fiala     if (byte_order == lldb::eByteOrderLittle)
9822850b1beSTodd Fiala     {
9832850b1beSTodd Fiala         ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
9842850b1beSTodd Fiala                  m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
9852850b1beSTodd Fiala                  sizeof(XMMReg));
9862850b1beSTodd Fiala         ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
9872850b1beSTodd Fiala                  m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
9882850b1beSTodd Fiala                  sizeof(YMMHReg));
9892850b1beSTodd Fiala         return true;
9902850b1beSTodd Fiala     }
9912850b1beSTodd Fiala 
9922850b1beSTodd Fiala     if (byte_order == lldb::eByteOrderBig)
9932850b1beSTodd Fiala     {
9942850b1beSTodd Fiala         ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
9952850b1beSTodd Fiala                  m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
9962850b1beSTodd Fiala                  sizeof(XMMReg));
9972850b1beSTodd Fiala         ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
9982850b1beSTodd Fiala                  m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
9992850b1beSTodd Fiala                  sizeof(YMMHReg));
10002850b1beSTodd Fiala         return true;
10012850b1beSTodd Fiala     }
10022850b1beSTodd Fiala     return false; // unsupported or invalid byte order
10032850b1beSTodd Fiala }
10042850b1beSTodd Fiala 
10052850b1beSTodd Fiala bool
10062850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::ReadFPR ()
10072850b1beSTodd Fiala {
10082850b1beSTodd Fiala     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
10092850b1beSTodd Fiala     if (!process_sp)
10102850b1beSTodd Fiala         return false;
10112850b1beSTodd Fiala     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
10122850b1beSTodd Fiala 
10132850b1beSTodd Fiala     const FPRType fpr_type = GetFPRType ();
10142850b1beSTodd Fiala     switch (fpr_type)
10152850b1beSTodd Fiala     {
10162850b1beSTodd Fiala     case FPRType::eFPRTypeFXSAVE:
101797ccc294SChaoren Lin         return process_p->ReadFPR (m_thread.GetID (), &m_fpr.xstate.fxsave, sizeof (m_fpr.xstate.fxsave)).Success();
10182850b1beSTodd Fiala 
10192850b1beSTodd Fiala     case FPRType::eFPRTypeXSAVE:
102097ccc294SChaoren Lin         return process_p->ReadRegisterSet (m_thread.GetID (), &m_iovec, sizeof (m_fpr.xstate.xsave), NT_X86_XSTATE).Success();
10212850b1beSTodd Fiala 
10222850b1beSTodd Fiala     default:
10232850b1beSTodd Fiala         return false;
10242850b1beSTodd Fiala     }
10252850b1beSTodd Fiala }
10262850b1beSTodd Fiala 
10272850b1beSTodd Fiala bool
10282850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::ReadGPR()
10292850b1beSTodd Fiala {
10302850b1beSTodd Fiala     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
10312850b1beSTodd Fiala     if (!process_sp)
10322850b1beSTodd Fiala         return false;
10332850b1beSTodd Fiala     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
10342850b1beSTodd Fiala 
103597ccc294SChaoren Lin     return process_p->ReadGPR (m_thread.GetID (), &m_gpr_x86_64, GetRegisterInfoInterface ().GetGPRSize ()).Success();
10362850b1beSTodd Fiala }
10372850b1beSTodd Fiala 
10382850b1beSTodd Fiala bool
10392850b1beSTodd Fiala NativeRegisterContextLinux_x86_64::WriteGPR()
10402850b1beSTodd Fiala {
10412850b1beSTodd Fiala     NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
10422850b1beSTodd Fiala     if (!process_sp)
10432850b1beSTodd Fiala         return false;
10442850b1beSTodd Fiala     NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
10452850b1beSTodd Fiala 
104697ccc294SChaoren Lin     return process_p->WriteGPR (m_thread.GetID (), &m_gpr_x86_64, GetRegisterInfoInterface ().GetGPRSize ()).Success();
10472850b1beSTodd Fiala }
10482850b1beSTodd Fiala 
104918fe6404SChaoren Lin Error
1050*c16f5dcaSChaoren Lin NativeRegisterContextLinux_x86_64::IsWatchpointHit(uint32_t wp_index, bool &is_hit)
105118fe6404SChaoren Lin {
105218fe6404SChaoren Lin     if (wp_index >= NumSupportedHardwareWatchpoints())
105318fe6404SChaoren Lin         return Error("Watchpoint index out of range");
105418fe6404SChaoren Lin 
105518fe6404SChaoren Lin     RegisterValue reg_value;
10566a504f6eSChaoren Lin     Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
1057*c16f5dcaSChaoren Lin     if (error.Fail())
1058*c16f5dcaSChaoren Lin     {
1059*c16f5dcaSChaoren Lin         is_hit = false;
1060*c16f5dcaSChaoren Lin         return error;
1061*c16f5dcaSChaoren Lin     }
106218fe6404SChaoren Lin 
106318fe6404SChaoren Lin     uint64_t status_bits = reg_value.GetAsUInt64();
106418fe6404SChaoren Lin 
1065*c16f5dcaSChaoren Lin     is_hit = status_bits & (1 << wp_index);
106618fe6404SChaoren Lin 
106718fe6404SChaoren Lin     return error;
106818fe6404SChaoren Lin }
106918fe6404SChaoren Lin 
107018fe6404SChaoren Lin Error
1071*c16f5dcaSChaoren Lin NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex(uint32_t &wp_index) {
1072*c16f5dcaSChaoren Lin     uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
1073*c16f5dcaSChaoren Lin     for (wp_index = 0; wp_index < num_hw_wps; ++wp_index)
1074*c16f5dcaSChaoren Lin     {
1075*c16f5dcaSChaoren Lin         bool is_hit;
1076*c16f5dcaSChaoren Lin         Error error = IsWatchpointHit(wp_index, is_hit);
1077*c16f5dcaSChaoren Lin         if (error.Fail()) {
1078*c16f5dcaSChaoren Lin             wp_index = LLDB_INVALID_INDEX32;
1079*c16f5dcaSChaoren Lin             return error;
1080*c16f5dcaSChaoren Lin         } else if (is_hit) {
1081*c16f5dcaSChaoren Lin             return error;
1082*c16f5dcaSChaoren Lin         }
1083*c16f5dcaSChaoren Lin     }
1084*c16f5dcaSChaoren Lin     wp_index = LLDB_INVALID_INDEX32;
1085*c16f5dcaSChaoren Lin     return Error();
1086*c16f5dcaSChaoren Lin }
1087*c16f5dcaSChaoren Lin 
1088*c16f5dcaSChaoren Lin Error
1089*c16f5dcaSChaoren Lin NativeRegisterContextLinux_x86_64::IsWatchpointVacant(uint32_t wp_index, bool &is_vacant)
109018fe6404SChaoren Lin {
109118fe6404SChaoren Lin     if (wp_index >= NumSupportedHardwareWatchpoints())
109218fe6404SChaoren Lin         return Error ("Watchpoint index out of range");
109318fe6404SChaoren Lin 
109418fe6404SChaoren Lin     RegisterValue reg_value;
10956a504f6eSChaoren Lin     Error error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
1096*c16f5dcaSChaoren Lin     if (error.Fail())
1097*c16f5dcaSChaoren Lin     {
1098*c16f5dcaSChaoren Lin         is_vacant = false;
1099*c16f5dcaSChaoren Lin         return error;
1100*c16f5dcaSChaoren Lin     }
110118fe6404SChaoren Lin 
110218fe6404SChaoren Lin     uint64_t control_bits = reg_value.GetAsUInt64();
110318fe6404SChaoren Lin 
1104*c16f5dcaSChaoren Lin     is_vacant = !(control_bits & (1 << (2 * wp_index)));
110518fe6404SChaoren Lin 
110618fe6404SChaoren Lin     return error;
110718fe6404SChaoren Lin }
110818fe6404SChaoren Lin 
110918fe6404SChaoren Lin Error
111018fe6404SChaoren Lin NativeRegisterContextLinux_x86_64::SetHardwareWatchpointWithIndex(
111118fe6404SChaoren Lin         lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) {
111218fe6404SChaoren Lin 
111318fe6404SChaoren Lin     if (wp_index >= NumSupportedHardwareWatchpoints())
111418fe6404SChaoren Lin         return Error ("Watchpoint index out of range");
111518fe6404SChaoren Lin 
111618fe6404SChaoren Lin     if (watch_flags != 0x1 && watch_flags != 0x3)
111718fe6404SChaoren Lin         return Error ("Invalid read/write bits for watchpoint");
111818fe6404SChaoren Lin 
111918fe6404SChaoren Lin     if (size != 1 && size != 2 && size != 4 && size != 8)
112018fe6404SChaoren Lin         return Error ("Invalid size for watchpoint");
112118fe6404SChaoren Lin 
1122*c16f5dcaSChaoren Lin     bool is_vacant;
1123*c16f5dcaSChaoren Lin     Error error = IsWatchpointVacant (wp_index, is_vacant);
112418fe6404SChaoren Lin     if (error.Fail()) return error;
1125*c16f5dcaSChaoren Lin     if (!is_vacant) return Error("Watchpoint index not vacant");
112618fe6404SChaoren Lin 
112718fe6404SChaoren Lin     RegisterValue reg_value;
11286a504f6eSChaoren Lin     error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
112918fe6404SChaoren Lin     if (error.Fail()) return error;
113018fe6404SChaoren Lin 
113118fe6404SChaoren Lin     // for watchpoints 0, 1, 2, or 3, respectively,
113218fe6404SChaoren Lin     // set bits 1, 3, 5, or 7
113318fe6404SChaoren Lin     uint64_t enable_bit = 1 << (2 * wp_index);
113418fe6404SChaoren Lin 
113518fe6404SChaoren Lin     // set bits 16-17, 20-21, 24-25, or 28-29
113618fe6404SChaoren Lin     // with 0b01 for write, and 0b11 for read/write
113718fe6404SChaoren Lin     uint64_t rw_bits = watch_flags << (16 + 4 * wp_index);
113818fe6404SChaoren Lin 
113918fe6404SChaoren Lin     // set bits 18-19, 22-23, 26-27, or 30-31
114018fe6404SChaoren Lin     // with 0b00, 0b01, 0b10, or 0b11
114118fe6404SChaoren Lin     // for 1, 2, 8 (if supported), or 4 bytes, respectively
114218fe6404SChaoren Lin     uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
114318fe6404SChaoren Lin 
114418fe6404SChaoren Lin     uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
114518fe6404SChaoren Lin 
114618fe6404SChaoren Lin     uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
114718fe6404SChaoren Lin 
114818fe6404SChaoren Lin     control_bits |= enable_bit | rw_bits | size_bits;
114918fe6404SChaoren Lin 
115018fe6404SChaoren Lin     error = WriteRegister(m_reg_info.first_dr + wp_index, RegisterValue(addr));
115118fe6404SChaoren Lin     if (error.Fail()) return error;
115218fe6404SChaoren Lin 
11536a504f6eSChaoren Lin     error = WriteRegister(m_reg_info.first_dr + 7, RegisterValue(control_bits));
115418fe6404SChaoren Lin     if (error.Fail()) return error;
115518fe6404SChaoren Lin 
115618fe6404SChaoren Lin     error.Clear();
115718fe6404SChaoren Lin     return error;
115818fe6404SChaoren Lin }
115918fe6404SChaoren Lin 
116018fe6404SChaoren Lin bool
116118fe6404SChaoren Lin NativeRegisterContextLinux_x86_64::ClearHardwareWatchpoint(uint32_t wp_index)
116218fe6404SChaoren Lin {
116318fe6404SChaoren Lin     if (wp_index >= NumSupportedHardwareWatchpoints())
116418fe6404SChaoren Lin         return false;
116518fe6404SChaoren Lin 
116618fe6404SChaoren Lin     RegisterValue reg_value;
116718fe6404SChaoren Lin 
116818fe6404SChaoren Lin     // for watchpoints 0, 1, 2, or 3, respectively,
116918fe6404SChaoren Lin     // clear bits 0, 1, 2, or 3 of the debug status register (DR6)
11706a504f6eSChaoren Lin     Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
117118fe6404SChaoren Lin     if (error.Fail()) return false;
117218fe6404SChaoren Lin     uint64_t bit_mask = 1 << wp_index;
117318fe6404SChaoren Lin     uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
11746a504f6eSChaoren Lin     error = WriteRegister(m_reg_info.first_dr + 6, RegisterValue(status_bits));
117518fe6404SChaoren Lin     if (error.Fail()) return false;
117618fe6404SChaoren Lin 
117718fe6404SChaoren Lin     // for watchpoints 0, 1, 2, or 3, respectively,
117818fe6404SChaoren Lin     // clear bits {0-1,16-19}, {2-3,20-23}, {4-5,24-27}, or {6-7,28-31}
117918fe6404SChaoren Lin     // of the debug control register (DR7)
11806a504f6eSChaoren Lin     error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
118118fe6404SChaoren Lin     if (error.Fail()) return false;
118218fe6404SChaoren Lin     bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
118318fe6404SChaoren Lin     uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
11846a504f6eSChaoren Lin     return WriteRegister(m_reg_info.first_dr + 7, RegisterValue(control_bits)).Success();
118518fe6404SChaoren Lin }
118618fe6404SChaoren Lin 
118718fe6404SChaoren Lin Error
118818fe6404SChaoren Lin NativeRegisterContextLinux_x86_64::ClearAllHardwareWatchpoints()
118918fe6404SChaoren Lin {
119018fe6404SChaoren Lin     RegisterValue reg_value;
119118fe6404SChaoren Lin 
119218fe6404SChaoren Lin     // clear bits {0-4} of the debug status register (DR6)
11936a504f6eSChaoren Lin     Error error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
119418fe6404SChaoren Lin     if (error.Fail()) return error;
119518fe6404SChaoren Lin     uint64_t bit_mask = 0xF;
119618fe6404SChaoren Lin     uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
11976a504f6eSChaoren Lin     error = WriteRegister(m_reg_info.first_dr + 6, RegisterValue(status_bits));
119818fe6404SChaoren Lin     if (error.Fail()) return error;
119918fe6404SChaoren Lin 
120018fe6404SChaoren Lin     // clear bits {0-7,16-31} of the debug control register (DR7)
12016a504f6eSChaoren Lin     error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
120218fe6404SChaoren Lin     if (error.Fail()) return error;
120318fe6404SChaoren Lin     bit_mask = 0xFF | (0xFFFF << 16);
120418fe6404SChaoren Lin     uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
12056a504f6eSChaoren Lin     return WriteRegister(m_reg_info.first_dr + 7, RegisterValue(control_bits));
120618fe6404SChaoren Lin }
120718fe6404SChaoren Lin 
120818fe6404SChaoren Lin uint32_t
120918fe6404SChaoren Lin NativeRegisterContextLinux_x86_64::SetHardwareWatchpoint(
121018fe6404SChaoren Lin         lldb::addr_t addr, size_t size, uint32_t watch_flags)
121118fe6404SChaoren Lin {
1212*c16f5dcaSChaoren Lin     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
121318fe6404SChaoren Lin     const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
121418fe6404SChaoren Lin     for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index)
121518fe6404SChaoren Lin     {
1216*c16f5dcaSChaoren Lin         bool is_vacant;
1217*c16f5dcaSChaoren Lin         Error error = IsWatchpointVacant(wp_index, is_vacant);
1218*c16f5dcaSChaoren Lin         if (is_vacant)
1219*c16f5dcaSChaoren Lin         {
1220*c16f5dcaSChaoren Lin             error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index);
1221*c16f5dcaSChaoren Lin             if (error.Success())
122218fe6404SChaoren Lin                 return wp_index;
122318fe6404SChaoren Lin         }
1224*c16f5dcaSChaoren Lin         if (error.Fail() && log)
1225*c16f5dcaSChaoren Lin         {
1226*c16f5dcaSChaoren Lin             log->Printf("NativeRegisterContextLinux_x86_64::%s Error: %s",
1227*c16f5dcaSChaoren Lin                     __FUNCTION__, error.AsCString());
1228*c16f5dcaSChaoren Lin         }
1229*c16f5dcaSChaoren Lin     }
123018fe6404SChaoren Lin     return LLDB_INVALID_INDEX32;
123118fe6404SChaoren Lin }
123218fe6404SChaoren Lin 
123318fe6404SChaoren Lin lldb::addr_t
123418fe6404SChaoren Lin NativeRegisterContextLinux_x86_64::GetWatchpointAddress(uint32_t wp_index)
123518fe6404SChaoren Lin {
123618fe6404SChaoren Lin     if (wp_index >= NumSupportedHardwareWatchpoints())
123718fe6404SChaoren Lin         return LLDB_INVALID_ADDRESS;
123818fe6404SChaoren Lin     RegisterValue reg_value;
123918fe6404SChaoren Lin     if (ReadRegisterRaw(m_reg_info.first_dr + wp_index, reg_value).Fail())
124018fe6404SChaoren Lin         return LLDB_INVALID_ADDRESS;
124118fe6404SChaoren Lin     return reg_value.GetAsUInt64();
124218fe6404SChaoren Lin }
124318fe6404SChaoren Lin 
124418fe6404SChaoren Lin uint32_t
124518fe6404SChaoren Lin NativeRegisterContextLinux_x86_64::NumSupportedHardwareWatchpoints ()
124618fe6404SChaoren Lin {
124718fe6404SChaoren Lin     // Available debug address registers: dr0, dr1, dr2, dr3
124818fe6404SChaoren Lin     return 4;
124918fe6404SChaoren Lin }
1250