180814287SRaphael Isemann //===-- NativeRegisterContextLinux_x86_64.cpp -----------------------------===//
22850b1beSTodd Fiala //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62850b1beSTodd Fiala //
72850b1beSTodd Fiala //===----------------------------------------------------------------------===//
82850b1beSTodd Fiala
9068f8a7eSTamas Berghammer #if defined(__i386__) || defined(__x86_64__)
10068f8a7eSTamas Berghammer
112850b1beSTodd Fiala #include "NativeRegisterContextLinux_x86_64.h"
122850b1beSTodd Fiala
13d1486e65SPavel Labath #include "Plugins/Process/Linux/NativeThreadLinux.h"
14d1486e65SPavel Labath #include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
15d1486e65SPavel Labath #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
16068f8a7eSTamas Berghammer #include "lldb/Host/HostInfo.h"
17666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
186f9e6901SZachary Turner #include "lldb/Utility/Log.h"
19d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h"
2097206d57SZachary Turner #include "lldb/Utility/Status.h"
2138a82413SPavel Labath #include <cpuid.h>
226ec13991SPavel Labath #include <linux/elf.h>
236ec13991SPavel Labath
2425c6a507SJoseph Tremoulet // Newer toolchains define __get_cpuid_count in cpuid.h, but some
2525c6a507SJoseph Tremoulet // older-but-still-supported ones (e.g. gcc 5.4.0) don't, so we
2625c6a507SJoseph Tremoulet // define it locally here, following the definition in clang/lib/Headers.
get_cpuid_count(unsigned int __leaf,unsigned int __subleaf,unsigned int * __eax,unsigned int * __ebx,unsigned int * __ecx,unsigned int * __edx)2725c6a507SJoseph Tremoulet static inline int get_cpuid_count(unsigned int __leaf,
2825c6a507SJoseph Tremoulet unsigned int __subleaf,
2925c6a507SJoseph Tremoulet unsigned int *__eax, unsigned int *__ebx,
3025c6a507SJoseph Tremoulet unsigned int *__ecx, unsigned int *__edx)
3125c6a507SJoseph Tremoulet {
32248a1305SKonrad Kleine unsigned int __max_leaf = __get_cpuid_max(__leaf & 0x80000000, nullptr);
3325c6a507SJoseph Tremoulet
3425c6a507SJoseph Tremoulet if (__max_leaf == 0 || __max_leaf < __leaf)
3525c6a507SJoseph Tremoulet return 0;
3625c6a507SJoseph Tremoulet
3725c6a507SJoseph Tremoulet __cpuid_count(__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx);
3825c6a507SJoseph Tremoulet return 1;
3925c6a507SJoseph Tremoulet }
4025c6a507SJoseph Tremoulet
412850b1beSTodd Fiala using namespace lldb_private;
42db264a6dSTamas Berghammer using namespace lldb_private::process_linux;
432850b1beSTodd Fiala
442850b1beSTodd Fiala // x86 32-bit general purpose registers.
453f3ab03aSPavel Labath static const uint32_t g_gpr_regnums_i386[] = {
46b9c1b51eSKate Stone lldb_eax_i386, lldb_ebx_i386, lldb_ecx_i386, lldb_edx_i386,
47b9c1b51eSKate Stone lldb_edi_i386, lldb_esi_i386, lldb_ebp_i386, lldb_esp_i386,
48b9c1b51eSKate Stone lldb_eip_i386, lldb_eflags_i386, lldb_cs_i386, lldb_fs_i386,
49b9c1b51eSKate Stone lldb_gs_i386, lldb_ss_i386, lldb_ds_i386, lldb_es_i386,
50b9c1b51eSKate Stone lldb_ax_i386, lldb_bx_i386, lldb_cx_i386, lldb_dx_i386,
51b9c1b51eSKate Stone lldb_di_i386, lldb_si_i386, lldb_bp_i386, lldb_sp_i386,
52b9c1b51eSKate Stone lldb_ah_i386, lldb_bh_i386, lldb_ch_i386, lldb_dh_i386,
53b9c1b51eSKate Stone lldb_al_i386, lldb_bl_i386, lldb_cl_i386, lldb_dl_i386,
542850b1beSTodd Fiala LLDB_INVALID_REGNUM // register sets need to end with this flag
552850b1beSTodd Fiala };
56b9c1b51eSKate Stone static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) -
57b9c1b51eSKate Stone 1 ==
58b9c1b51eSKate Stone k_num_gpr_registers_i386,
592850b1beSTodd Fiala "g_gpr_regnums_i386 has wrong number of register infos");
602850b1beSTodd Fiala
612850b1beSTodd Fiala // x86 32-bit floating point registers.
623f3ab03aSPavel Labath static const uint32_t g_fpu_regnums_i386[] = {
63b9c1b51eSKate Stone lldb_fctrl_i386, lldb_fstat_i386, lldb_ftag_i386, lldb_fop_i386,
64b9c1b51eSKate Stone lldb_fiseg_i386, lldb_fioff_i386, lldb_foseg_i386, lldb_fooff_i386,
65b9c1b51eSKate Stone lldb_mxcsr_i386, lldb_mxcsrmask_i386, lldb_st0_i386, lldb_st1_i386,
66b9c1b51eSKate Stone lldb_st2_i386, lldb_st3_i386, lldb_st4_i386, lldb_st5_i386,
67b9c1b51eSKate Stone lldb_st6_i386, lldb_st7_i386, lldb_mm0_i386, lldb_mm1_i386,
68b9c1b51eSKate Stone lldb_mm2_i386, lldb_mm3_i386, lldb_mm4_i386, lldb_mm5_i386,
69b9c1b51eSKate Stone lldb_mm6_i386, lldb_mm7_i386, lldb_xmm0_i386, lldb_xmm1_i386,
70b9c1b51eSKate Stone lldb_xmm2_i386, lldb_xmm3_i386, lldb_xmm4_i386, lldb_xmm5_i386,
71b9c1b51eSKate Stone lldb_xmm6_i386, lldb_xmm7_i386,
722850b1beSTodd Fiala LLDB_INVALID_REGNUM // register sets need to end with this flag
732850b1beSTodd Fiala };
74b9c1b51eSKate Stone static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) -
75b9c1b51eSKate Stone 1 ==
76b9c1b51eSKate Stone k_num_fpr_registers_i386,
772850b1beSTodd Fiala "g_fpu_regnums_i386 has wrong number of register infos");
782850b1beSTodd Fiala
792850b1beSTodd Fiala // x86 32-bit AVX registers.
803f3ab03aSPavel Labath static const uint32_t g_avx_regnums_i386[] = {
81b9c1b51eSKate Stone lldb_ymm0_i386, lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386,
82b9c1b51eSKate Stone lldb_ymm4_i386, lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386,
832850b1beSTodd Fiala LLDB_INVALID_REGNUM // register sets need to end with this flag
842850b1beSTodd Fiala };
85b9c1b51eSKate Stone static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) -
86b9c1b51eSKate Stone 1 ==
87b9c1b51eSKate Stone k_num_avx_registers_i386,
882850b1beSTodd Fiala " g_avx_regnums_i386 has wrong number of register infos");
892850b1beSTodd Fiala
90cda0ae46SValentina Giusti // x64 32-bit MPX registers.
91cda0ae46SValentina Giusti static const uint32_t g_mpx_regnums_i386[] = {
92cda0ae46SValentina Giusti lldb_bnd0_i386, lldb_bnd1_i386, lldb_bnd2_i386, lldb_bnd3_i386,
93cda0ae46SValentina Giusti lldb_bndcfgu_i386, lldb_bndstatus_i386,
94cda0ae46SValentina Giusti LLDB_INVALID_REGNUM // register sets need to end with this flag
95cda0ae46SValentina Giusti };
96cda0ae46SValentina Giusti static_assert((sizeof(g_mpx_regnums_i386) / sizeof(g_mpx_regnums_i386[0])) -
97cda0ae46SValentina Giusti 1 ==
98cda0ae46SValentina Giusti k_num_mpx_registers_i386,
99cda0ae46SValentina Giusti "g_mpx_regnums_x86_64 has wrong number of register infos");
100cda0ae46SValentina Giusti
1012850b1beSTodd Fiala // x86 64-bit general purpose registers.
102b9c1b51eSKate Stone static const uint32_t g_gpr_regnums_x86_64[] = {
103b9c1b51eSKate Stone lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64,
104b9c1b51eSKate Stone lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rbp_x86_64, lldb_rsp_x86_64,
105b9c1b51eSKate Stone lldb_r8_x86_64, lldb_r9_x86_64, lldb_r10_x86_64, lldb_r11_x86_64,
106b9c1b51eSKate Stone lldb_r12_x86_64, lldb_r13_x86_64, lldb_r14_x86_64, lldb_r15_x86_64,
107b9c1b51eSKate Stone lldb_rip_x86_64, lldb_rflags_x86_64, lldb_cs_x86_64, lldb_fs_x86_64,
108b9c1b51eSKate Stone lldb_gs_x86_64, lldb_ss_x86_64, lldb_ds_x86_64, lldb_es_x86_64,
109b9c1b51eSKate Stone lldb_eax_x86_64, lldb_ebx_x86_64, lldb_ecx_x86_64, lldb_edx_x86_64,
110b9c1b51eSKate Stone lldb_edi_x86_64, lldb_esi_x86_64, lldb_ebp_x86_64, lldb_esp_x86_64,
1117f013bcdSZachary Turner lldb_r8d_x86_64, // Low 32 bits or r8
1127f013bcdSZachary Turner lldb_r9d_x86_64, // Low 32 bits or r9
1137f013bcdSZachary Turner lldb_r10d_x86_64, // Low 32 bits or r10
1147f013bcdSZachary Turner lldb_r11d_x86_64, // Low 32 bits or r11
1157f013bcdSZachary Turner lldb_r12d_x86_64, // Low 32 bits or r12
1167f013bcdSZachary Turner lldb_r13d_x86_64, // Low 32 bits or r13
1177f013bcdSZachary Turner lldb_r14d_x86_64, // Low 32 bits or r14
1187f013bcdSZachary Turner lldb_r15d_x86_64, // Low 32 bits or r15
119b9c1b51eSKate Stone lldb_ax_x86_64, lldb_bx_x86_64, lldb_cx_x86_64, lldb_dx_x86_64,
120b9c1b51eSKate Stone lldb_di_x86_64, lldb_si_x86_64, lldb_bp_x86_64, lldb_sp_x86_64,
1217f013bcdSZachary Turner lldb_r8w_x86_64, // Low 16 bits or r8
1227f013bcdSZachary Turner lldb_r9w_x86_64, // Low 16 bits or r9
1237f013bcdSZachary Turner lldb_r10w_x86_64, // Low 16 bits or r10
1247f013bcdSZachary Turner lldb_r11w_x86_64, // Low 16 bits or r11
1257f013bcdSZachary Turner lldb_r12w_x86_64, // Low 16 bits or r12
1267f013bcdSZachary Turner lldb_r13w_x86_64, // Low 16 bits or r13
1277f013bcdSZachary Turner lldb_r14w_x86_64, // Low 16 bits or r14
1287f013bcdSZachary Turner lldb_r15w_x86_64, // Low 16 bits or r15
129b9c1b51eSKate Stone lldb_ah_x86_64, lldb_bh_x86_64, lldb_ch_x86_64, lldb_dh_x86_64,
130b9c1b51eSKate Stone lldb_al_x86_64, lldb_bl_x86_64, lldb_cl_x86_64, lldb_dl_x86_64,
131b9c1b51eSKate Stone lldb_dil_x86_64, lldb_sil_x86_64, lldb_bpl_x86_64, lldb_spl_x86_64,
1327f013bcdSZachary Turner lldb_r8l_x86_64, // Low 8 bits or r8
1337f013bcdSZachary Turner lldb_r9l_x86_64, // Low 8 bits or r9
1347f013bcdSZachary Turner lldb_r10l_x86_64, // Low 8 bits or r10
1357f013bcdSZachary Turner lldb_r11l_x86_64, // Low 8 bits or r11
1367f013bcdSZachary Turner lldb_r12l_x86_64, // Low 8 bits or r12
1377f013bcdSZachary Turner lldb_r13l_x86_64, // Low 8 bits or r13
1387f013bcdSZachary Turner lldb_r14l_x86_64, // Low 8 bits or r14
1397f013bcdSZachary Turner lldb_r15l_x86_64, // Low 8 bits or r15
1402850b1beSTodd Fiala LLDB_INVALID_REGNUM // register sets need to end with this flag
1412850b1beSTodd Fiala };
142b9c1b51eSKate Stone static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
143b9c1b51eSKate Stone 1 ==
144b9c1b51eSKate Stone k_num_gpr_registers_x86_64,
1452850b1beSTodd Fiala "g_gpr_regnums_x86_64 has wrong number of register infos");
1462850b1beSTodd Fiala
1472850b1beSTodd Fiala // x86 64-bit floating point registers.
148b9c1b51eSKate Stone static const uint32_t g_fpu_regnums_x86_64[] = {
149b9c1b51eSKate Stone lldb_fctrl_x86_64, lldb_fstat_x86_64, lldb_ftag_x86_64,
150b9c1b51eSKate Stone lldb_fop_x86_64, lldb_fiseg_x86_64, lldb_fioff_x86_64,
151d8ff269fSMichał Górny lldb_fip_x86_64, lldb_foseg_x86_64, lldb_fooff_x86_64,
152d8ff269fSMichał Górny lldb_fdp_x86_64, lldb_mxcsr_x86_64, lldb_mxcsrmask_x86_64,
153d8ff269fSMichał Górny lldb_st0_x86_64, lldb_st1_x86_64, lldb_st2_x86_64,
154d8ff269fSMichał Górny lldb_st3_x86_64, lldb_st4_x86_64, lldb_st5_x86_64,
155d8ff269fSMichał Górny lldb_st6_x86_64, lldb_st7_x86_64, lldb_mm0_x86_64,
156d8ff269fSMichał Górny lldb_mm1_x86_64, lldb_mm2_x86_64, lldb_mm3_x86_64,
157d8ff269fSMichał Górny lldb_mm4_x86_64, lldb_mm5_x86_64, lldb_mm6_x86_64,
158d8ff269fSMichał Górny lldb_mm7_x86_64, lldb_xmm0_x86_64, lldb_xmm1_x86_64,
159d8ff269fSMichał Górny lldb_xmm2_x86_64, lldb_xmm3_x86_64, lldb_xmm4_x86_64,
160d8ff269fSMichał Górny lldb_xmm5_x86_64, lldb_xmm6_x86_64, lldb_xmm7_x86_64,
161d8ff269fSMichał Górny lldb_xmm8_x86_64, lldb_xmm9_x86_64, lldb_xmm10_x86_64,
162d8ff269fSMichał Górny lldb_xmm11_x86_64, lldb_xmm12_x86_64, lldb_xmm13_x86_64,
163d8ff269fSMichał Górny lldb_xmm14_x86_64, lldb_xmm15_x86_64,
1642850b1beSTodd Fiala LLDB_INVALID_REGNUM // register sets need to end with this flag
1652850b1beSTodd Fiala };
166b9c1b51eSKate Stone static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
167b9c1b51eSKate Stone 1 ==
168b9c1b51eSKate Stone k_num_fpr_registers_x86_64,
1692850b1beSTodd Fiala "g_fpu_regnums_x86_64 has wrong number of register infos");
1702850b1beSTodd Fiala
1712850b1beSTodd Fiala // x86 64-bit AVX registers.
172b9c1b51eSKate Stone static const uint32_t g_avx_regnums_x86_64[] = {
173b9c1b51eSKate Stone lldb_ymm0_x86_64, lldb_ymm1_x86_64, lldb_ymm2_x86_64, lldb_ymm3_x86_64,
174b9c1b51eSKate Stone lldb_ymm4_x86_64, lldb_ymm5_x86_64, lldb_ymm6_x86_64, lldb_ymm7_x86_64,
175b9c1b51eSKate Stone lldb_ymm8_x86_64, lldb_ymm9_x86_64, lldb_ymm10_x86_64, lldb_ymm11_x86_64,
176b9c1b51eSKate Stone lldb_ymm12_x86_64, lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64,
1772850b1beSTodd Fiala LLDB_INVALID_REGNUM // register sets need to end with this flag
1782850b1beSTodd Fiala };
179b9c1b51eSKate Stone static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) -
180b9c1b51eSKate Stone 1 ==
181b9c1b51eSKate Stone k_num_avx_registers_x86_64,
1822850b1beSTodd Fiala "g_avx_regnums_x86_64 has wrong number of register infos");
1832850b1beSTodd Fiala
184cda0ae46SValentina Giusti // x86 64-bit MPX registers.
185cda0ae46SValentina Giusti static const uint32_t g_mpx_regnums_x86_64[] = {
186cda0ae46SValentina Giusti lldb_bnd0_x86_64, lldb_bnd1_x86_64, lldb_bnd2_x86_64,
187cda0ae46SValentina Giusti lldb_bnd3_x86_64, lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64,
188cda0ae46SValentina Giusti LLDB_INVALID_REGNUM // register sets need to end with this flag
189cda0ae46SValentina Giusti };
190cda0ae46SValentina Giusti static_assert((sizeof(g_mpx_regnums_x86_64) / sizeof(g_mpx_regnums_x86_64[0])) -
191cda0ae46SValentina Giusti 1 ==
192cda0ae46SValentina Giusti k_num_mpx_registers_x86_64,
193cda0ae46SValentina Giusti "g_mpx_regnums_x86_64 has wrong number of register infos");
194cda0ae46SValentina Giusti
1952850b1beSTodd Fiala // Number of register sets provided by this context.
1963f3ab03aSPavel Labath constexpr unsigned k_num_extended_register_sets = 2, k_num_register_sets = 4;
1972850b1beSTodd Fiala
1982850b1beSTodd Fiala // Register sets for x86 32-bit.
199b9c1b51eSKate Stone static const RegisterSet g_reg_sets_i386[k_num_register_sets] = {
200b9c1b51eSKate Stone {"General Purpose Registers", "gpr", k_num_gpr_registers_i386,
201b9c1b51eSKate Stone g_gpr_regnums_i386},
202b9c1b51eSKate Stone {"Floating Point Registers", "fpu", k_num_fpr_registers_i386,
203b9c1b51eSKate Stone g_fpu_regnums_i386},
204b9c1b51eSKate Stone {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386,
205cda0ae46SValentina Giusti g_avx_regnums_i386},
206cda0ae46SValentina Giusti { "Memory Protection Extensions", "mpx", k_num_mpx_registers_i386,
207cda0ae46SValentina Giusti g_mpx_regnums_i386}};
2082850b1beSTodd Fiala
2092850b1beSTodd Fiala // Register sets for x86 64-bit.
210b9c1b51eSKate Stone static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
211b9c1b51eSKate Stone {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64,
212b9c1b51eSKate Stone g_gpr_regnums_x86_64},
213b9c1b51eSKate Stone {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64,
214b9c1b51eSKate Stone g_fpu_regnums_x86_64},
215b9c1b51eSKate Stone {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64,
216cda0ae46SValentina Giusti g_avx_regnums_x86_64},
217cda0ae46SValentina Giusti { "Memory Protection Extensions", "mpx", k_num_mpx_registers_x86_64,
218cda0ae46SValentina Giusti g_mpx_regnums_x86_64}};
2192850b1beSTodd Fiala
2202850b1beSTodd Fiala #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR))
2212850b1beSTodd Fiala
2222850b1beSTodd Fiala // Required ptrace defines.
2232850b1beSTodd Fiala
2242850b1beSTodd Fiala // Support ptrace extensions even when compiled without required kernel support
2252850b1beSTodd Fiala #ifndef NT_X86_XSTATE
2262850b1beSTodd Fiala #define NT_X86_XSTATE 0x202
2272850b1beSTodd Fiala #endif
228296e063dSAbhishek Aggarwal #ifndef NT_PRXFPREG
229296e063dSAbhishek Aggarwal #define NT_PRXFPREG 0x46e62b7f
230296e063dSAbhishek Aggarwal #endif
2312850b1beSTodd Fiala
2326ec13991SPavel Labath // On x86_64 NT_PRFPREG is used to access the FXSAVE area. On i386, we need to
2336ec13991SPavel Labath // use NT_PRXFPREG.
fxsr_regset(const ArchSpec & arch)2346ec13991SPavel Labath static inline unsigned int fxsr_regset(const ArchSpec &arch) {
2356ec13991SPavel Labath return arch.GetAddressByteSize() == 8 ? NT_PRFPREG : NT_PRXFPREG;
2366ec13991SPavel Labath }
2376ec13991SPavel Labath
2385f957b54SValentina Giusti // Required MPX define.
2395f957b54SValentina Giusti
2405f957b54SValentina Giusti // Support MPX extensions also if compiled with compiler without MPX support.
2415f957b54SValentina Giusti #ifndef bit_MPX
2425f957b54SValentina Giusti #define bit_MPX 0x4000
2435f957b54SValentina Giusti #endif
2445f957b54SValentina Giusti
2455f957b54SValentina Giusti // XCR0 extended register sets masks.
2465f957b54SValentina Giusti #define mask_XSTATE_AVX (1ULL << 2)
2475f957b54SValentina Giusti #define mask_XSTATE_BNDREGS (1ULL << 3)
2485f957b54SValentina Giusti #define mask_XSTATE_BNDCFG (1ULL << 4)
2495f957b54SValentina Giusti #define mask_XSTATE_MPX (mask_XSTATE_BNDREGS | mask_XSTATE_BNDCFG)
2505f957b54SValentina Giusti
251d37349f3SPavel Labath std::unique_ptr<NativeRegisterContextLinux>
CreateHostNativeRegisterContextLinux(const ArchSpec & target_arch,NativeThreadLinux & native_thread)252b9c1b51eSKate Stone NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
253d1486e65SPavel Labath const ArchSpec &target_arch, NativeThreadLinux &native_thread) {
254d37349f3SPavel Labath return std::unique_ptr<NativeRegisterContextLinux>(
255d37349f3SPavel Labath new NativeRegisterContextLinux_x86_64(target_arch, native_thread));
256068f8a7eSTamas Berghammer }
257068f8a7eSTamas Berghammer
2582850b1beSTodd Fiala // NativeRegisterContextLinux_x86_64 members.
2592850b1beSTodd Fiala
260068f8a7eSTamas Berghammer static RegisterInfoInterface *
CreateRegisterInfoInterface(const ArchSpec & target_arch)261b9c1b51eSKate Stone CreateRegisterInfoInterface(const ArchSpec &target_arch) {
262b9c1b51eSKate Stone if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
263068f8a7eSTamas Berghammer // 32-bit hosts run with a RegisterContextLinux_i386 context.
264068f8a7eSTamas Berghammer return new RegisterContextLinux_i386(target_arch);
265b9c1b51eSKate Stone } else {
266068f8a7eSTamas Berghammer assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
267068f8a7eSTamas Berghammer "Register setting path assumes this is a 64-bit host");
268b9c1b51eSKate Stone // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the
269b9c1b51eSKate Stone // x86_64 register context.
270068f8a7eSTamas Berghammer return new RegisterContextLinux_x86_64(target_arch);
271068f8a7eSTamas Berghammer }
272068f8a7eSTamas Berghammer }
273068f8a7eSTamas Berghammer
27438a82413SPavel Labath // Return the size of the XSTATE area supported on this cpu. It is necessary to
27538a82413SPavel Labath // allocate the full size of the area even if we do not use/recognise all of it
27638a82413SPavel Labath // because ptrace(PTRACE_SETREGSET, NT_X86_XSTATE) will refuse to write to it if
27738a82413SPavel Labath // we do not pass it a buffer of sufficient size. The size is always at least
27838a82413SPavel Labath // sizeof(FPR) so that the allocated buffer can be safely cast to FPR*.
GetXSTATESize()27938a82413SPavel Labath static std::size_t GetXSTATESize() {
28038a82413SPavel Labath unsigned int eax, ebx, ecx, edx;
28138a82413SPavel Labath // First check whether the XSTATE are is supported at all.
28238a82413SPavel Labath if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx) || !(ecx & bit_XSAVE))
28338a82413SPavel Labath return sizeof(FPR);
28438a82413SPavel Labath
28538a82413SPavel Labath // Then fetch the maximum size of the area.
28625c6a507SJoseph Tremoulet if (!get_cpuid_count(0x0d, 0, &eax, &ebx, &ecx, &edx))
28738a82413SPavel Labath return sizeof(FPR);
28838a82413SPavel Labath return std::max<std::size_t>(ecx, sizeof(FPR));
28938a82413SPavel Labath }
29038a82413SPavel Labath
NativeRegisterContextLinux_x86_64(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)291b9c1b51eSKate Stone NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
292d37349f3SPavel Labath const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
293f5ca2756SMichał Górny : NativeRegisterContextRegisterInfo(
294f5ca2756SMichał Górny native_thread, CreateRegisterInfoInterface(target_arch)),
2953bea7306SPavel Labath NativeRegisterContextLinux(native_thread),
2963bea7306SPavel Labath NativeRegisterContextDBReg_x86(native_thread),
29738a82413SPavel Labath m_xstate_type(XStateType::Invalid), m_ymm_set(), m_mpx_set(),
29838a82413SPavel Labath m_reg_info(), m_gpr_x86_64() {
2992850b1beSTodd Fiala // Set up data about ranges of valid registers.
300b9c1b51eSKate Stone switch (target_arch.GetMachine()) {
3012850b1beSTodd Fiala case llvm::Triple::x86:
3022850b1beSTodd Fiala m_reg_info.num_registers = k_num_registers_i386;
3032850b1beSTodd Fiala m_reg_info.num_gpr_registers = k_num_gpr_registers_i386;
3042850b1beSTodd Fiala m_reg_info.num_fpr_registers = k_num_fpr_registers_i386;
3052850b1beSTodd Fiala m_reg_info.num_avx_registers = k_num_avx_registers_i386;
306cda0ae46SValentina Giusti m_reg_info.num_mpx_registers = k_num_mpx_registers_i386;
3072850b1beSTodd Fiala m_reg_info.last_gpr = k_last_gpr_i386;
3082850b1beSTodd Fiala m_reg_info.first_fpr = k_first_fpr_i386;
3092850b1beSTodd Fiala m_reg_info.last_fpr = k_last_fpr_i386;
3107f013bcdSZachary Turner m_reg_info.first_st = lldb_st0_i386;
3117f013bcdSZachary Turner m_reg_info.last_st = lldb_st7_i386;
3127f013bcdSZachary Turner m_reg_info.first_mm = lldb_mm0_i386;
3137f013bcdSZachary Turner m_reg_info.last_mm = lldb_mm7_i386;
3147f013bcdSZachary Turner m_reg_info.first_xmm = lldb_xmm0_i386;
3157f013bcdSZachary Turner m_reg_info.last_xmm = lldb_xmm7_i386;
3167f013bcdSZachary Turner m_reg_info.first_ymm = lldb_ymm0_i386;
3177f013bcdSZachary Turner m_reg_info.last_ymm = lldb_ymm7_i386;
318cda0ae46SValentina Giusti m_reg_info.first_mpxr = lldb_bnd0_i386;
319cda0ae46SValentina Giusti m_reg_info.last_mpxr = lldb_bnd3_i386;
320cda0ae46SValentina Giusti m_reg_info.first_mpxc = lldb_bndcfgu_i386;
321cda0ae46SValentina Giusti m_reg_info.last_mpxc = lldb_bndstatus_i386;
3227f013bcdSZachary Turner m_reg_info.first_dr = lldb_dr0_i386;
323f5ca2756SMichał Górny m_reg_info.last_dr = lldb_dr7_i386;
3247f013bcdSZachary Turner m_reg_info.gpr_flags = lldb_eflags_i386;
3252850b1beSTodd Fiala break;
3262850b1beSTodd Fiala case llvm::Triple::x86_64:
3272850b1beSTodd Fiala m_reg_info.num_registers = k_num_registers_x86_64;
3282850b1beSTodd Fiala m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64;
3292850b1beSTodd Fiala m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64;
3302850b1beSTodd Fiala m_reg_info.num_avx_registers = k_num_avx_registers_x86_64;
331cda0ae46SValentina Giusti m_reg_info.num_mpx_registers = k_num_mpx_registers_x86_64;
3322850b1beSTodd Fiala m_reg_info.last_gpr = k_last_gpr_x86_64;
3332850b1beSTodd Fiala m_reg_info.first_fpr = k_first_fpr_x86_64;
3342850b1beSTodd Fiala m_reg_info.last_fpr = k_last_fpr_x86_64;
3357f013bcdSZachary Turner m_reg_info.first_st = lldb_st0_x86_64;
3367f013bcdSZachary Turner m_reg_info.last_st = lldb_st7_x86_64;
3377f013bcdSZachary Turner m_reg_info.first_mm = lldb_mm0_x86_64;
3387f013bcdSZachary Turner m_reg_info.last_mm = lldb_mm7_x86_64;
3397f013bcdSZachary Turner m_reg_info.first_xmm = lldb_xmm0_x86_64;
3407f013bcdSZachary Turner m_reg_info.last_xmm = lldb_xmm15_x86_64;
3417f013bcdSZachary Turner m_reg_info.first_ymm = lldb_ymm0_x86_64;
3427f013bcdSZachary Turner m_reg_info.last_ymm = lldb_ymm15_x86_64;
343cda0ae46SValentina Giusti m_reg_info.first_mpxr = lldb_bnd0_x86_64;
344cda0ae46SValentina Giusti m_reg_info.last_mpxr = lldb_bnd3_x86_64;
345cda0ae46SValentina Giusti m_reg_info.first_mpxc = lldb_bndcfgu_x86_64;
346cda0ae46SValentina Giusti m_reg_info.last_mpxc = lldb_bndstatus_x86_64;
3477f013bcdSZachary Turner m_reg_info.first_dr = lldb_dr0_x86_64;
348f5ca2756SMichał Górny m_reg_info.last_dr = lldb_dr7_x86_64;
3497f013bcdSZachary Turner m_reg_info.gpr_flags = lldb_rflags_x86_64;
3502850b1beSTodd Fiala break;
3512850b1beSTodd Fiala default:
3522850b1beSTodd Fiala assert(false && "Unhandled target architecture.");
3532850b1beSTodd Fiala break;
3542850b1beSTodd Fiala }
3552850b1beSTodd Fiala
35638a82413SPavel Labath std::size_t xstate_size = GetXSTATESize();
35738a82413SPavel Labath m_xstate.reset(static_cast<FPR *>(std::malloc(xstate_size)));
35838a82413SPavel Labath m_iovec.iov_base = m_xstate.get();
35938a82413SPavel Labath m_iovec.iov_len = xstate_size;
3602850b1beSTodd Fiala
3612850b1beSTodd Fiala // Clear out the FPR state.
36238a82413SPavel Labath ::memset(m_xstate.get(), 0, xstate_size);
3637f658eddSAbhishek Aggarwal
3647f658eddSAbhishek Aggarwal // Store byte offset of fctrl (i.e. first register of FPR)
3657f658eddSAbhishek Aggarwal const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl");
3667f658eddSAbhishek Aggarwal m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;
3672850b1beSTodd Fiala }
3682850b1beSTodd Fiala
3692850b1beSTodd Fiala // CONSIDER after local and llgs debugging are merged, register set support can
3702850b1beSTodd Fiala // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual.
GetRegisterSetCount() const371b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_x86_64::GetRegisterSetCount() const {
3722850b1beSTodd Fiala uint32_t sets = 0;
373b9c1b51eSKate Stone for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
3742850b1beSTodd Fiala if (IsRegisterSetAvailable(set_index))
3752850b1beSTodd Fiala ++sets;
3762850b1beSTodd Fiala }
3772850b1beSTodd Fiala
3782850b1beSTodd Fiala return sets;
3792850b1beSTodd Fiala }
3802850b1beSTodd Fiala
GetUserRegisterCount() const381b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_x86_64::GetUserRegisterCount() const {
3828fa23b8eSTamas Berghammer uint32_t count = 0;
383b9c1b51eSKate Stone for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
384db264a6dSTamas Berghammer const RegisterSet *set = GetRegisterSet(set_index);
3858fa23b8eSTamas Berghammer if (set)
3868fa23b8eSTamas Berghammer count += set->num_registers;
3878fa23b8eSTamas Berghammer }
3888fa23b8eSTamas Berghammer return count;
3898fa23b8eSTamas Berghammer }
3908fa23b8eSTamas Berghammer
391db264a6dSTamas Berghammer const RegisterSet *
GetRegisterSet(uint32_t set_index) const392b9c1b51eSKate Stone NativeRegisterContextLinux_x86_64::GetRegisterSet(uint32_t set_index) const {
3932850b1beSTodd Fiala if (!IsRegisterSetAvailable(set_index))
3942850b1beSTodd Fiala return nullptr;
3952850b1beSTodd Fiala
396b9c1b51eSKate Stone switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
3972850b1beSTodd Fiala case llvm::Triple::x86:
3982850b1beSTodd Fiala return &g_reg_sets_i386[set_index];
3992850b1beSTodd Fiala case llvm::Triple::x86_64:
4002850b1beSTodd Fiala return &g_reg_sets_x86_64[set_index];
4012850b1beSTodd Fiala default:
4022850b1beSTodd Fiala assert(false && "Unhandled target architecture.");
4032850b1beSTodd Fiala return nullptr;
4042850b1beSTodd Fiala }
4052850b1beSTodd Fiala
4062850b1beSTodd Fiala return nullptr;
4072850b1beSTodd Fiala }
4082850b1beSTodd Fiala
40997206d57SZachary Turner Status
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)41097206d57SZachary Turner NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
41197206d57SZachary Turner RegisterValue ®_value) {
41297206d57SZachary Turner Status error;
4132850b1beSTodd Fiala
414b9c1b51eSKate Stone if (!reg_info) {
4152850b1beSTodd Fiala error.SetErrorString("reg_info NULL");
4162850b1beSTodd Fiala return error;
4172850b1beSTodd Fiala }
4182850b1beSTodd Fiala
4192850b1beSTodd Fiala const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
420b9c1b51eSKate Stone if (reg == LLDB_INVALID_REGNUM) {
421b9c1b51eSKate Stone // This is likely an internal register for lldb use only and should not be
422b9c1b51eSKate Stone // directly queried.
423b9c1b51eSKate Stone error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
424b9c1b51eSKate Stone "register, cannot read directly",
425b9c1b51eSKate Stone reg_info->name);
4262850b1beSTodd Fiala return error;
4272850b1beSTodd Fiala }
4282850b1beSTodd Fiala
4295f957b54SValentina Giusti if (IsFPR(reg) || IsAVX(reg) || IsMPX(reg)) {
430068f8a7eSTamas Berghammer error = ReadFPR();
431068f8a7eSTamas Berghammer if (error.Fail())
4322850b1beSTodd Fiala return error;
433b9c1b51eSKate Stone } else {
4342850b1beSTodd Fiala uint32_t full_reg = reg;
435b9c1b51eSKate Stone bool is_subreg = reg_info->invalidate_regs &&
436b9c1b51eSKate Stone (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
4372850b1beSTodd Fiala
438b9c1b51eSKate Stone if (is_subreg) {
4392850b1beSTodd Fiala // Read the full aligned 64-bit register.
4402850b1beSTodd Fiala full_reg = reg_info->invalidate_regs[0];
4412850b1beSTodd Fiala }
4422850b1beSTodd Fiala
4432850b1beSTodd Fiala error = ReadRegisterRaw(full_reg, reg_value);
4442850b1beSTodd Fiala
445b9c1b51eSKate Stone if (error.Success()) {
44605097246SAdrian Prantl // If our read was not aligned (for ah,bh,ch,dh), shift our returned
44705097246SAdrian Prantl // value one byte to the right.
4482850b1beSTodd Fiala if (is_subreg && (reg_info->byte_offset & 0x1))
4492850b1beSTodd Fiala reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
4502850b1beSTodd Fiala
451b9c1b51eSKate Stone // If our return byte size was greater than the return value reg size,
45205097246SAdrian Prantl // then use the type specified by reg_info rather than the uint64_t
45305097246SAdrian Prantl // default
4542850b1beSTodd Fiala if (reg_value.GetByteSize() > reg_info->byte_size)
4552850b1beSTodd Fiala reg_value.SetType(reg_info);
4562850b1beSTodd Fiala }
4572850b1beSTodd Fiala return error;
4582850b1beSTodd Fiala }
4592850b1beSTodd Fiala
460b9c1b51eSKate Stone if (reg_info->encoding == lldb::eEncodingVector) {
4612850b1beSTodd Fiala lldb::ByteOrder byte_order = GetByteOrder();
4622850b1beSTodd Fiala
463b9c1b51eSKate Stone if (byte_order != lldb::eByteOrderInvalid) {
4642850b1beSTodd Fiala if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
46538a82413SPavel Labath reg_value.SetBytes(
46638a82413SPavel Labath m_xstate->fxsave.stmm[reg - m_reg_info.first_st].bytes,
467b9c1b51eSKate Stone reg_info->byte_size, byte_order);
4682850b1beSTodd Fiala if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
46938a82413SPavel Labath reg_value.SetBytes(
47038a82413SPavel Labath m_xstate->fxsave.stmm[reg - m_reg_info.first_mm].bytes,
471b9c1b51eSKate Stone reg_info->byte_size, byte_order);
4722850b1beSTodd Fiala if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
47338a82413SPavel Labath reg_value.SetBytes(
47438a82413SPavel Labath m_xstate->fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
475b9c1b51eSKate Stone reg_info->byte_size, byte_order);
476b9c1b51eSKate Stone if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
47705097246SAdrian Prantl // Concatenate ymm using the register halves in xmm.bytes and
47805097246SAdrian Prantl // ymmh.bytes
4795f957b54SValentina Giusti if (CopyXSTATEtoYMM(reg, byte_order))
480b9c1b51eSKate Stone reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
481b9c1b51eSKate Stone reg_info->byte_size, byte_order);
482b9c1b51eSKate Stone else {
4832850b1beSTodd Fiala error.SetErrorString("failed to copy ymm register value");
4842850b1beSTodd Fiala return error;
4852850b1beSTodd Fiala }
4862850b1beSTodd Fiala }
487cda0ae46SValentina Giusti if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
4885f957b54SValentina Giusti if (CopyXSTATEtoMPX(reg))
489cda0ae46SValentina Giusti reg_value.SetBytes(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,
490cda0ae46SValentina Giusti reg_info->byte_size, byte_order);
491cda0ae46SValentina Giusti else {
492cda0ae46SValentina Giusti error.SetErrorString("failed to copy mpx register value");
493cda0ae46SValentina Giusti return error;
494cda0ae46SValentina Giusti }
495cda0ae46SValentina Giusti }
496cda0ae46SValentina Giusti if (reg >= m_reg_info.first_mpxc && reg <= m_reg_info.last_mpxc) {
4975f957b54SValentina Giusti if (CopyXSTATEtoMPX(reg))
498cda0ae46SValentina Giusti reg_value.SetBytes(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,
499cda0ae46SValentina Giusti reg_info->byte_size, byte_order);
500cda0ae46SValentina Giusti else {
501cda0ae46SValentina Giusti error.SetErrorString("failed to copy mpx register value");
502cda0ae46SValentina Giusti return error;
503cda0ae46SValentina Giusti }
504cda0ae46SValentina Giusti }
505ee44a92dSDimitar Vlahovski
5062850b1beSTodd Fiala if (reg_value.GetType() != RegisterValue::eTypeBytes)
507b9c1b51eSKate Stone error.SetErrorString(
508b9c1b51eSKate Stone "write failed - type was expected to be RegisterValue::eTypeBytes");
5092850b1beSTodd Fiala
5102850b1beSTodd Fiala return error;
5112850b1beSTodd Fiala }
5122850b1beSTodd Fiala
5132850b1beSTodd Fiala error.SetErrorString("byte order is invalid");
5142850b1beSTodd Fiala return error;
5152850b1beSTodd Fiala }
5162850b1beSTodd Fiala
51738a82413SPavel Labath // Get pointer to m_xstate->fxsave variable and set the data from it.
5187f658eddSAbhishek Aggarwal
5197f658eddSAbhishek Aggarwal // Byte offsets of all registers are calculated wrt 'UserArea' structure.
5207f658eddSAbhishek Aggarwal // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)}
521b9c1b51eSKate Stone // and stores them in 'm_fpr' (of type FPR structure). To extract values of
52205097246SAdrian Prantl // fpu registers, m_fpr should be read at byte offsets calculated wrt to FPR
523b9c1b51eSKate Stone // structure.
5247f658eddSAbhishek Aggarwal
5257f658eddSAbhishek Aggarwal // Since, FPR structure is also one of the member of UserArea structure.
526b9c1b51eSKate Stone // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
527b9c1b51eSKate Stone // byte_offset(fctrl wrt UserArea)
52838a82413SPavel Labath assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(FPR));
52938a82413SPavel Labath uint8_t *src = (uint8_t *)m_xstate.get() + reg_info->byte_offset -
53038a82413SPavel Labath m_fctrl_offset_in_userarea;
5318aea95f3SMichał Górny
5328aea95f3SMichał Górny if (src == reinterpret_cast<uint8_t *>(&m_xstate->fxsave.ftag)) {
5338aea95f3SMichał Górny reg_value.SetUInt16(AbridgedToFullTagWord(
5348aea95f3SMichał Górny m_xstate->fxsave.ftag, m_xstate->fxsave.fstat, m_xstate->fxsave.stmm));
5358aea95f3SMichał Górny return error;
5368aea95f3SMichał Górny }
5378aea95f3SMichał Górny
538b9c1b51eSKate Stone switch (reg_info->byte_size) {
539b352a1c8SAbhishek Aggarwal case 1:
540b352a1c8SAbhishek Aggarwal reg_value.SetUInt8(*(uint8_t *)src);
541b352a1c8SAbhishek Aggarwal break;
5422850b1beSTodd Fiala case 2:
5432850b1beSTodd Fiala reg_value.SetUInt16(*(uint16_t *)src);
5442850b1beSTodd Fiala break;
5452850b1beSTodd Fiala case 4:
5462850b1beSTodd Fiala reg_value.SetUInt32(*(uint32_t *)src);
5472850b1beSTodd Fiala break;
5482850b1beSTodd Fiala case 8:
5492850b1beSTodd Fiala reg_value.SetUInt64(*(uint64_t *)src);
5502850b1beSTodd Fiala break;
5512850b1beSTodd Fiala default:
5522850b1beSTodd Fiala assert(false && "Unhandled data size.");
553b9c1b51eSKate Stone error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32,
554b9c1b51eSKate Stone reg_info->byte_size);
5552850b1beSTodd Fiala break;
5562850b1beSTodd Fiala }
5572850b1beSTodd Fiala
5582850b1beSTodd Fiala return error;
5592850b1beSTodd Fiala }
5602850b1beSTodd Fiala
UpdateXSTATEforWrite(uint32_t reg_index)561d2cfe0e5SPavel Labath void NativeRegisterContextLinux_x86_64::UpdateXSTATEforWrite(
562d2cfe0e5SPavel Labath uint32_t reg_index) {
56338a82413SPavel Labath XSAVE_HDR::XFeature &xstate_bv = m_xstate->xsave.header.xstate_bv;
564d2cfe0e5SPavel Labath if (IsFPR(reg_index)) {
565d2cfe0e5SPavel Labath // IsFPR considers both %st and %xmm registers as floating point, but these
566d2cfe0e5SPavel Labath // map to two features. Set both flags, just in case.
567d2cfe0e5SPavel Labath xstate_bv |= XSAVE_HDR::XFeature::FP | XSAVE_HDR::XFeature::SSE;
568d2cfe0e5SPavel Labath } else if (IsAVX(reg_index)) {
569d2cfe0e5SPavel Labath // Lower bytes of some %ymm registers are shared with %xmm registers.
570d2cfe0e5SPavel Labath xstate_bv |= XSAVE_HDR::XFeature::YMM | XSAVE_HDR::XFeature::SSE;
571d2cfe0e5SPavel Labath } else if (IsMPX(reg_index)) {
572d2cfe0e5SPavel Labath // MPX registers map to two XSAVE features.
573d2cfe0e5SPavel Labath xstate_bv |= XSAVE_HDR::XFeature::BNDREGS | XSAVE_HDR::XFeature::BNDCSR;
574d2cfe0e5SPavel Labath }
575d2cfe0e5SPavel Labath }
576d2cfe0e5SPavel Labath
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)57797206d57SZachary Turner Status NativeRegisterContextLinux_x86_64::WriteRegister(
578b9c1b51eSKate Stone const RegisterInfo *reg_info, const RegisterValue ®_value) {
5792850b1beSTodd Fiala assert(reg_info && "reg_info is null");
5802850b1beSTodd Fiala
5812850b1beSTodd Fiala const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
5822850b1beSTodd Fiala if (reg_index == LLDB_INVALID_REGNUM)
58397206d57SZachary Turner return Status("no lldb regnum for %s", reg_info && reg_info->name
584b9c1b51eSKate Stone ? reg_info->name
585b9c1b51eSKate Stone : "<unknown register>");
5862850b1beSTodd Fiala
587d2cfe0e5SPavel Labath UpdateXSTATEforWrite(reg_index);
588d2cfe0e5SPavel Labath
589f5ca2756SMichał Górny if (IsGPR(reg_index) || IsDR(reg_index))
590068f8a7eSTamas Berghammer return WriteRegisterRaw(reg_index, reg_value);
5912850b1beSTodd Fiala
5925f957b54SValentina Giusti if (IsFPR(reg_index) || IsAVX(reg_index) || IsMPX(reg_index)) {
593b9c1b51eSKate Stone if (reg_info->encoding == lldb::eEncodingVector) {
5942850b1beSTodd Fiala if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st)
59538a82413SPavel Labath ::memcpy(m_xstate->fxsave.stmm[reg_index - m_reg_info.first_st].bytes,
596b9c1b51eSKate Stone reg_value.GetBytes(), reg_value.GetByteSize());
5972850b1beSTodd Fiala
5982850b1beSTodd Fiala if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm)
59938a82413SPavel Labath ::memcpy(m_xstate->fxsave.stmm[reg_index - m_reg_info.first_mm].bytes,
600b9c1b51eSKate Stone reg_value.GetBytes(), reg_value.GetByteSize());
6012850b1beSTodd Fiala
6022850b1beSTodd Fiala if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm)
60338a82413SPavel Labath ::memcpy(m_xstate->fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes,
604b9c1b51eSKate Stone reg_value.GetBytes(), reg_value.GetByteSize());
6052850b1beSTodd Fiala
606b9c1b51eSKate Stone if (reg_index >= m_reg_info.first_ymm &&
607b9c1b51eSKate Stone reg_index <= m_reg_info.last_ymm) {
608b9c1b51eSKate Stone // Store ymm register content, and split into the register halves in
609b9c1b51eSKate Stone // xmm.bytes and ymmh.bytes
610b9c1b51eSKate Stone ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
611b9c1b51eSKate Stone reg_value.GetBytes(), reg_value.GetByteSize());
6122850b1beSTodd Fiala if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
61397206d57SZachary Turner return Status("CopyYMMtoXSTATE() failed");
6142850b1beSTodd Fiala }
615cda0ae46SValentina Giusti
616cda0ae46SValentina Giusti if (reg_index >= m_reg_info.first_mpxr &&
617cda0ae46SValentina Giusti reg_index <= m_reg_info.last_mpxr) {
618cda0ae46SValentina Giusti ::memcpy(m_mpx_set.mpxr[reg_index - m_reg_info.first_mpxr].bytes,
619cda0ae46SValentina Giusti reg_value.GetBytes(), reg_value.GetByteSize());
620cda0ae46SValentina Giusti if (!CopyMPXtoXSTATE(reg_index))
62197206d57SZachary Turner return Status("CopyMPXtoXSTATE() failed");
622cda0ae46SValentina Giusti }
623cda0ae46SValentina Giusti
624cda0ae46SValentina Giusti if (reg_index >= m_reg_info.first_mpxc &&
625cda0ae46SValentina Giusti reg_index <= m_reg_info.last_mpxc) {
626cda0ae46SValentina Giusti ::memcpy(m_mpx_set.mpxc[reg_index - m_reg_info.first_mpxc].bytes,
627cda0ae46SValentina Giusti reg_value.GetBytes(), reg_value.GetByteSize());
628cda0ae46SValentina Giusti if (!CopyMPXtoXSTATE(reg_index))
62997206d57SZachary Turner return Status("CopyMPXtoXSTATE() failed");
630cda0ae46SValentina Giusti }
631b9c1b51eSKate Stone } else {
63238a82413SPavel Labath // Get pointer to m_xstate->fxsave variable and set the data to it.
6337f658eddSAbhishek Aggarwal
6347f658eddSAbhishek Aggarwal // Byte offsets of all registers are calculated wrt 'UserArea' structure.
63505097246SAdrian Prantl // However, WriteFPR() takes m_fpr (of type FPR structure) and writes
63605097246SAdrian Prantl // only fpu registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu
63705097246SAdrian Prantl // registers should be written in m_fpr at byte offsets calculated wrt
63805097246SAdrian Prantl // FPR structure.
6397f658eddSAbhishek Aggarwal
6407f658eddSAbhishek Aggarwal // Since, FPR structure is also one of the member of UserArea structure.
641b9c1b51eSKate Stone // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
642b9c1b51eSKate Stone // byte_offset(fctrl wrt UserArea)
643b9c1b51eSKate Stone assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) <
64438a82413SPavel Labath sizeof(FPR));
64538a82413SPavel Labath uint8_t *dst = (uint8_t *)m_xstate.get() + reg_info->byte_offset -
646b9c1b51eSKate Stone m_fctrl_offset_in_userarea;
6478aea95f3SMichał Górny
6488aea95f3SMichał Górny if (dst == reinterpret_cast<uint8_t *>(&m_xstate->fxsave.ftag))
6498aea95f3SMichał Górny m_xstate->fxsave.ftag = FullToAbridgedTagWord(reg_value.GetAsUInt16());
6508aea95f3SMichał Górny else {
651b9c1b51eSKate Stone switch (reg_info->byte_size) {
652b352a1c8SAbhishek Aggarwal case 1:
653b352a1c8SAbhishek Aggarwal *(uint8_t *)dst = reg_value.GetAsUInt8();
654b352a1c8SAbhishek Aggarwal break;
6552850b1beSTodd Fiala case 2:
6562850b1beSTodd Fiala *(uint16_t *)dst = reg_value.GetAsUInt16();
6572850b1beSTodd Fiala break;
6582850b1beSTodd Fiala case 4:
6592850b1beSTodd Fiala *(uint32_t *)dst = reg_value.GetAsUInt32();
6602850b1beSTodd Fiala break;
6612850b1beSTodd Fiala case 8:
6622850b1beSTodd Fiala *(uint64_t *)dst = reg_value.GetAsUInt64();
6632850b1beSTodd Fiala break;
6642850b1beSTodd Fiala default:
6652850b1beSTodd Fiala assert(false && "Unhandled data size.");
66697206d57SZachary Turner return Status("unhandled register data size %" PRIu32,
667b9c1b51eSKate Stone reg_info->byte_size);
6682850b1beSTodd Fiala }
6692850b1beSTodd Fiala }
6708aea95f3SMichał Górny }
6712850b1beSTodd Fiala
67297206d57SZachary Turner Status error = WriteFPR();
673068f8a7eSTamas Berghammer if (error.Fail())
674068f8a7eSTamas Berghammer return error;
675068f8a7eSTamas Berghammer
676b9c1b51eSKate Stone if (IsAVX(reg_index)) {
6772850b1beSTodd Fiala if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
67897206d57SZachary Turner return Status("CopyYMMtoXSTATE() failed");
6792850b1beSTodd Fiala }
680cda0ae46SValentina Giusti
681cda0ae46SValentina Giusti if (IsMPX(reg_index)) {
682cda0ae46SValentina Giusti if (!CopyMPXtoXSTATE(reg_index))
68397206d57SZachary Turner return Status("CopyMPXtoXSTATE() failed");
684cda0ae46SValentina Giusti }
68597206d57SZachary Turner return Status();
6862850b1beSTodd Fiala }
68797206d57SZachary Turner return Status("failed - register wasn't recognized to be a GPR or an FPR, "
688b9c1b51eSKate Stone "write strategy unknown");
6892850b1beSTodd Fiala }
6902850b1beSTodd Fiala
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)69197206d57SZachary Turner Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues(
692c2f64601SJonas Devlieghere lldb::WritableDataBufferSP &data_sp) {
69397206d57SZachary Turner Status error;
6942850b1beSTodd Fiala
6952850b1beSTodd Fiala data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
696068f8a7eSTamas Berghammer error = ReadGPR();
697068f8a7eSTamas Berghammer if (error.Fail())
6982850b1beSTodd Fiala return error;
6992850b1beSTodd Fiala
700068f8a7eSTamas Berghammer error = ReadFPR();
701068f8a7eSTamas Berghammer if (error.Fail())
7022850b1beSTodd Fiala return error;
7032850b1beSTodd Fiala
7042850b1beSTodd Fiala uint8_t *dst = data_sp->GetBytes();
7052850b1beSTodd Fiala ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());
7062850b1beSTodd Fiala dst += GetRegisterInfoInterface().GetGPRSize();
70758db5bb2SValentina Giusti if (m_xstate_type == XStateType::FXSAVE)
70838a82413SPavel Labath ::memcpy(dst, &m_xstate->fxsave, sizeof(m_xstate->fxsave));
70958db5bb2SValentina Giusti else if (m_xstate_type == XStateType::XSAVE) {
7102850b1beSTodd Fiala lldb::ByteOrder byte_order = GetByteOrder();
7112850b1beSTodd Fiala
71297e57e9bSValentina Giusti if (IsCPUFeatureAvailable(RegSet::avx)) {
7132850b1beSTodd Fiala // Assemble the YMM register content from the register halves.
714b9c1b51eSKate Stone for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
715b9c1b51eSKate Stone ++reg) {
716b9c1b51eSKate Stone if (!CopyXSTATEtoYMM(reg, byte_order)) {
7175f957b54SValentina Giusti error.SetErrorStringWithFormat(
7185f957b54SValentina Giusti "NativeRegisterContextLinux_x86_64::%s "
719b9c1b51eSKate Stone "CopyXSTATEtoYMM() failed for reg num "
720b9c1b51eSKate Stone "%" PRIu32,
721b9c1b51eSKate Stone __FUNCTION__, reg);
7222850b1beSTodd Fiala return error;
7232850b1beSTodd Fiala }
7242850b1beSTodd Fiala }
7255f957b54SValentina Giusti }
7262850b1beSTodd Fiala
72797e57e9bSValentina Giusti if (IsCPUFeatureAvailable(RegSet::mpx)) {
728cda0ae46SValentina Giusti for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc;
729cda0ae46SValentina Giusti ++reg) {
730cda0ae46SValentina Giusti if (!CopyXSTATEtoMPX(reg)) {
7315f957b54SValentina Giusti error.SetErrorStringWithFormat(
7325f957b54SValentina Giusti "NativeRegisterContextLinux_x86_64::%s "
733cda0ae46SValentina Giusti "CopyXSTATEtoMPX() failed for reg num "
734cda0ae46SValentina Giusti "%" PRIu32,
735cda0ae46SValentina Giusti __FUNCTION__, reg);
736cda0ae46SValentina Giusti return error;
737cda0ae46SValentina Giusti }
738cda0ae46SValentina Giusti }
7395f957b54SValentina Giusti }
7402850b1beSTodd Fiala // Copy the extended register state including the assembled ymm registers.
74138a82413SPavel Labath ::memcpy(dst, m_xstate.get(), sizeof(FPR));
742b9c1b51eSKate Stone } else {
7432850b1beSTodd Fiala assert(false && "how do we save the floating point registers?");
7442850b1beSTodd Fiala error.SetErrorString("unsure how to save the floating point registers");
7452850b1beSTodd Fiala }
7464778e410SRavitheja Addepally /** The following code is specific to Linux x86 based architectures,
7474778e410SRavitheja Addepally * where the register orig_eax (32 bit)/orig_rax (64 bit) is set to
7484778e410SRavitheja Addepally * -1 to solve the bug 23659, such a setting prevents the automatic
7494778e410SRavitheja Addepally * decrement of the instruction pointer which was causing the SIGILL
7504778e410SRavitheja Addepally * exception.
7514778e410SRavitheja Addepally * **/
7524778e410SRavitheja Addepally
7534778e410SRavitheja Addepally RegisterValue value((uint64_t)-1);
754b9c1b51eSKate Stone const RegisterInfo *reg_info =
755b9c1b51eSKate Stone GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax");
7564778e410SRavitheja Addepally if (reg_info == nullptr)
7574778e410SRavitheja Addepally reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax");
7584778e410SRavitheja Addepally
75964ad85ceSTamas Berghammer if (reg_info != nullptr)
7604778e410SRavitheja Addepally return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, value);
7612850b1beSTodd Fiala
7622850b1beSTodd Fiala return error;
7632850b1beSTodd Fiala }
7642850b1beSTodd Fiala
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)76597206d57SZachary Turner Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues(
766b9c1b51eSKate Stone const lldb::DataBufferSP &data_sp) {
76797206d57SZachary Turner Status error;
7682850b1beSTodd Fiala
769b9c1b51eSKate Stone if (!data_sp) {
770b9c1b51eSKate Stone error.SetErrorStringWithFormat(
771b9c1b51eSKate Stone "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided",
772b9c1b51eSKate Stone __FUNCTION__);
7732850b1beSTodd Fiala return error;
7742850b1beSTodd Fiala }
7752850b1beSTodd Fiala
776b9c1b51eSKate Stone if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
777993f2a42SPavel Labath error.SetErrorStringWithFormatv(
778993f2a42SPavel Labath "data_sp contained mismatched data size, expected {0}, actual {1}",
779993f2a42SPavel Labath REG_CONTEXT_SIZE, data_sp->GetByteSize());
7802850b1beSTodd Fiala return error;
7812850b1beSTodd Fiala }
7822850b1beSTodd Fiala
783*ed9a14f9SJonas Devlieghere const uint8_t *src = data_sp->GetBytes();
784b9c1b51eSKate Stone if (src == nullptr) {
785b9c1b51eSKate Stone error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
786b9c1b51eSKate Stone "DataBuffer::GetBytes() returned a null "
787b9c1b51eSKate Stone "pointer",
788b9c1b51eSKate Stone __FUNCTION__);
7892850b1beSTodd Fiala return error;
7902850b1beSTodd Fiala }
7912850b1beSTodd Fiala ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize());
7922850b1beSTodd Fiala
793068f8a7eSTamas Berghammer error = WriteGPR();
794068f8a7eSTamas Berghammer if (error.Fail())
7952850b1beSTodd Fiala return error;
7962850b1beSTodd Fiala
7972850b1beSTodd Fiala src += GetRegisterInfoInterface().GetGPRSize();
79858db5bb2SValentina Giusti if (m_xstate_type == XStateType::FXSAVE)
79938a82413SPavel Labath ::memcpy(&m_xstate->fxsave, src, sizeof(m_xstate->fxsave));
80058db5bb2SValentina Giusti else if (m_xstate_type == XStateType::XSAVE)
80138a82413SPavel Labath ::memcpy(&m_xstate->xsave, src, sizeof(m_xstate->xsave));
8022850b1beSTodd Fiala
803068f8a7eSTamas Berghammer error = WriteFPR();
804068f8a7eSTamas Berghammer if (error.Fail())
8052850b1beSTodd Fiala return error;
8062850b1beSTodd Fiala
80758db5bb2SValentina Giusti if (m_xstate_type == XStateType::XSAVE) {
8082850b1beSTodd Fiala lldb::ByteOrder byte_order = GetByteOrder();
8092850b1beSTodd Fiala
81097e57e9bSValentina Giusti if (IsCPUFeatureAvailable(RegSet::avx)) {
8112850b1beSTodd Fiala // Parse the YMM register content from the register halves.
812b9c1b51eSKate Stone for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
813b9c1b51eSKate Stone ++reg) {
814b9c1b51eSKate Stone if (!CopyYMMtoXSTATE(reg, byte_order)) {
8155f957b54SValentina Giusti error.SetErrorStringWithFormat(
8165f957b54SValentina Giusti "NativeRegisterContextLinux_x86_64::%s "
817b9c1b51eSKate Stone "CopyYMMtoXSTATE() failed for reg num "
818b9c1b51eSKate Stone "%" PRIu32,
819b9c1b51eSKate Stone __FUNCTION__, reg);
8202850b1beSTodd Fiala return error;
8212850b1beSTodd Fiala }
8222850b1beSTodd Fiala }
8235f957b54SValentina Giusti }
824cda0ae46SValentina Giusti
82597e57e9bSValentina Giusti if (IsCPUFeatureAvailable(RegSet::mpx)) {
826cda0ae46SValentina Giusti for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc;
827cda0ae46SValentina Giusti ++reg) {
828cda0ae46SValentina Giusti if (!CopyMPXtoXSTATE(reg)) {
8295f957b54SValentina Giusti error.SetErrorStringWithFormat(
8305f957b54SValentina Giusti "NativeRegisterContextLinux_x86_64::%s "
831cda0ae46SValentina Giusti "CopyMPXtoXSTATE() failed for reg num "
832cda0ae46SValentina Giusti "%" PRIu32,
833cda0ae46SValentina Giusti __FUNCTION__, reg);
834cda0ae46SValentina Giusti return error;
835cda0ae46SValentina Giusti }
836cda0ae46SValentina Giusti }
8372850b1beSTodd Fiala }
8385f957b54SValentina Giusti }
8392850b1beSTodd Fiala
8402850b1beSTodd Fiala return error;
8412850b1beSTodd Fiala }
8422850b1beSTodd Fiala
IsCPUFeatureAvailable(RegSet feature_code) const8435f957b54SValentina Giusti bool NativeRegisterContextLinux_x86_64::IsCPUFeatureAvailable(
8445f957b54SValentina Giusti RegSet feature_code) const {
84558db5bb2SValentina Giusti if (m_xstate_type == XStateType::Invalid) {
84658db5bb2SValentina Giusti if (const_cast<NativeRegisterContextLinux_x86_64 *>(this)->ReadFPR().Fail())
8475f957b54SValentina Giusti return false;
84858db5bb2SValentina Giusti }
8495f957b54SValentina Giusti switch (feature_code) {
85058db5bb2SValentina Giusti case RegSet::gpr:
85158db5bb2SValentina Giusti case RegSet::fpu:
8525f957b54SValentina Giusti return true;
85358db5bb2SValentina Giusti case RegSet::avx: // Check if CPU has AVX and if there is kernel support, by
85458db5bb2SValentina Giusti // reading in the XCR0 area of XSAVE.
85538a82413SPavel Labath if ((m_xstate->xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX)
8565f957b54SValentina Giusti return true;
85758db5bb2SValentina Giusti break;
85858db5bb2SValentina Giusti case RegSet::mpx: // Check if CPU has MPX and if there is kernel support, by
85958db5bb2SValentina Giusti // reading in the XCR0 area of XSAVE.
86038a82413SPavel Labath if ((m_xstate->xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX)
86158db5bb2SValentina Giusti return true;
86258db5bb2SValentina Giusti break;
8635f957b54SValentina Giusti }
8645f957b54SValentina Giusti return false;
8655f957b54SValentina Giusti }
8665f957b54SValentina Giusti
IsRegisterSetAvailable(uint32_t set_index) const867b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable(
868b9c1b51eSKate Stone uint32_t set_index) const {
8692850b1beSTodd Fiala uint32_t num_sets = k_num_register_sets - k_num_extended_register_sets;
8702850b1beSTodd Fiala
87197e57e9bSValentina Giusti switch (static_cast<RegSet>(set_index)) {
87297e57e9bSValentina Giusti case RegSet::gpr:
87397e57e9bSValentina Giusti case RegSet::fpu:
8742850b1beSTodd Fiala return (set_index < num_sets);
87597e57e9bSValentina Giusti case RegSet::avx:
87697e57e9bSValentina Giusti return IsCPUFeatureAvailable(RegSet::avx);
87797e57e9bSValentina Giusti case RegSet::mpx:
87897e57e9bSValentina Giusti return IsCPUFeatureAvailable(RegSet::mpx);
8795f957b54SValentina Giusti }
88058db5bb2SValentina Giusti return false;
8812850b1beSTodd Fiala }
8822850b1beSTodd Fiala
IsGPR(uint32_t reg_index) const883b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const {
8842850b1beSTodd Fiala // GPRs come first.
8852850b1beSTodd Fiala return reg_index <= m_reg_info.last_gpr;
8862850b1beSTodd Fiala }
8872850b1beSTodd Fiala
IsFPR(uint32_t reg_index) const888b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const {
889b9c1b51eSKate Stone return (m_reg_info.first_fpr <= reg_index &&
890b9c1b51eSKate Stone reg_index <= m_reg_info.last_fpr);
8912850b1beSTodd Fiala }
8922850b1beSTodd Fiala
IsDR(uint32_t reg_index) const893f5ca2756SMichał Górny bool NativeRegisterContextLinux_x86_64::IsDR(uint32_t reg_index) const {
894f5ca2756SMichał Górny return (m_reg_info.first_dr <= reg_index &&
895f5ca2756SMichał Górny reg_index <= m_reg_info.last_dr);
896f5ca2756SMichał Górny }
897f5ca2756SMichał Górny
WriteFPR()89897206d57SZachary Turner Status NativeRegisterContextLinux_x86_64::WriteFPR() {
89958db5bb2SValentina Giusti switch (m_xstate_type) {
90097e57e9bSValentina Giusti case XStateType::FXSAVE:
9016ec13991SPavel Labath return WriteRegisterSet(
90238a82413SPavel Labath &m_iovec, sizeof(m_xstate->fxsave),
9036ec13991SPavel Labath fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture()));
90497e57e9bSValentina Giusti case XStateType::XSAVE:
90538a82413SPavel Labath return WriteRegisterSet(&m_iovec, sizeof(m_xstate->xsave), NT_X86_XSTATE);
906068f8a7eSTamas Berghammer default:
90797206d57SZachary Turner return Status("Unrecognized FPR type.");
908068f8a7eSTamas Berghammer }
9092850b1beSTodd Fiala }
9102850b1beSTodd Fiala
IsAVX(uint32_t reg_index) const911b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const {
91297e57e9bSValentina Giusti if (!IsCPUFeatureAvailable(RegSet::avx))
9135f957b54SValentina Giusti return false;
914b9c1b51eSKate Stone return (m_reg_info.first_ymm <= reg_index &&
915b9c1b51eSKate Stone reg_index <= m_reg_info.last_ymm);
9162850b1beSTodd Fiala }
9172850b1beSTodd Fiala
CopyXSTATEtoYMM(uint32_t reg_index,lldb::ByteOrder byte_order)918b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM(
919b9c1b51eSKate Stone uint32_t reg_index, lldb::ByteOrder byte_order) {
9202850b1beSTodd Fiala if (!IsAVX(reg_index))
9212850b1beSTodd Fiala return false;
9222850b1beSTodd Fiala
923b9c1b51eSKate Stone if (byte_order == lldb::eByteOrderLittle) {
92488058292SMichal Gorny uint32_t reg_no = reg_index - m_reg_info.first_ymm;
92588058292SMichal Gorny m_ymm_set.ymm[reg_no] = XStateToYMM(
92688058292SMichal Gorny m_xstate->fxsave.xmm[reg_no].bytes,
92788058292SMichal Gorny m_xstate->xsave.ymmh[reg_no].bytes);
9282850b1beSTodd Fiala return true;
9292850b1beSTodd Fiala }
9302850b1beSTodd Fiala
9312850b1beSTodd Fiala return false; // unsupported or invalid byte order
9322850b1beSTodd Fiala }
9332850b1beSTodd Fiala
CopyYMMtoXSTATE(uint32_t reg,lldb::ByteOrder byte_order)934b9c1b51eSKate Stone bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(
935b9c1b51eSKate Stone uint32_t reg, lldb::ByteOrder byte_order) {
9362850b1beSTodd Fiala if (!IsAVX(reg))
9372850b1beSTodd Fiala return false;
9382850b1beSTodd Fiala
939b9c1b51eSKate Stone if (byte_order == lldb::eByteOrderLittle) {
94088058292SMichal Gorny uint32_t reg_no = reg - m_reg_info.first_ymm;
94188058292SMichal Gorny YMMToXState(m_ymm_set.ymm[reg_no],
94288058292SMichal Gorny m_xstate->fxsave.xmm[reg_no].bytes,
94388058292SMichal Gorny m_xstate->xsave.ymmh[reg_no].bytes);
9442850b1beSTodd Fiala return true;
9452850b1beSTodd Fiala }
9462850b1beSTodd Fiala
9472850b1beSTodd Fiala return false; // unsupported or invalid byte order
9482850b1beSTodd Fiala }
9492850b1beSTodd Fiala
GetFPRBuffer()950b9c1b51eSKate Stone void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() {
95158db5bb2SValentina Giusti switch (m_xstate_type) {
95297e57e9bSValentina Giusti case XStateType::FXSAVE:
95338a82413SPavel Labath return &m_xstate->fxsave;
95497e57e9bSValentina Giusti case XStateType::XSAVE:
955068f8a7eSTamas Berghammer return &m_iovec;
9562850b1beSTodd Fiala default:
957068f8a7eSTamas Berghammer return nullptr;
9582850b1beSTodd Fiala }
9592850b1beSTodd Fiala }
9602850b1beSTodd Fiala
GetFPRSize()961b9c1b51eSKate Stone size_t NativeRegisterContextLinux_x86_64::GetFPRSize() {
96258db5bb2SValentina Giusti switch (m_xstate_type) {
96397e57e9bSValentina Giusti case XStateType::FXSAVE:
96438a82413SPavel Labath return sizeof(m_xstate->fxsave);
96597e57e9bSValentina Giusti case XStateType::XSAVE:
966068f8a7eSTamas Berghammer return sizeof(m_iovec);
967068f8a7eSTamas Berghammer default:
968068f8a7eSTamas Berghammer return 0;
969068f8a7eSTamas Berghammer }
9702850b1beSTodd Fiala }
9712850b1beSTodd Fiala
ReadFPR()97297206d57SZachary Turner Status NativeRegisterContextLinux_x86_64::ReadFPR() {
97397206d57SZachary Turner Status error;
97458db5bb2SValentina Giusti
97558db5bb2SValentina Giusti // Probe XSAVE and if it is not supported fall back to FXSAVE.
97658db5bb2SValentina Giusti if (m_xstate_type != XStateType::FXSAVE) {
97738a82413SPavel Labath error = ReadRegisterSet(&m_iovec, sizeof(m_xstate->xsave), NT_X86_XSTATE);
97858db5bb2SValentina Giusti if (!error.Fail()) {
97958db5bb2SValentina Giusti m_xstate_type = XStateType::XSAVE;
98058db5bb2SValentina Giusti return error;
981296e063dSAbhishek Aggarwal }
982068f8a7eSTamas Berghammer }
9836ec13991SPavel Labath error = ReadRegisterSet(
98438a82413SPavel Labath &m_iovec, sizeof(m_xstate->xsave),
9856ec13991SPavel Labath fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture()));
98658db5bb2SValentina Giusti if (!error.Fail()) {
98758db5bb2SValentina Giusti m_xstate_type = XStateType::FXSAVE;
98858db5bb2SValentina Giusti return error;
98958db5bb2SValentina Giusti }
99097206d57SZachary Turner return Status("Unrecognized FPR type.");
9912850b1beSTodd Fiala }
9922850b1beSTodd Fiala
IsMPX(uint32_t reg_index) const993cda0ae46SValentina Giusti bool NativeRegisterContextLinux_x86_64::IsMPX(uint32_t reg_index) const {
99497e57e9bSValentina Giusti if (!IsCPUFeatureAvailable(RegSet::mpx))
9955f957b54SValentina Giusti return false;
996cda0ae46SValentina Giusti return (m_reg_info.first_mpxr <= reg_index &&
997cda0ae46SValentina Giusti reg_index <= m_reg_info.last_mpxc);
998cda0ae46SValentina Giusti }
999cda0ae46SValentina Giusti
CopyXSTATEtoMPX(uint32_t reg)1000cda0ae46SValentina Giusti bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) {
1001cda0ae46SValentina Giusti if (!IsMPX(reg))
1002cda0ae46SValentina Giusti return false;
1003cda0ae46SValentina Giusti
1004cda0ae46SValentina Giusti if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
1005cda0ae46SValentina Giusti ::memcpy(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,
100638a82413SPavel Labath m_xstate->xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
1007cda0ae46SValentina Giusti sizeof(MPXReg));
1008cda0ae46SValentina Giusti } else {
1009cda0ae46SValentina Giusti ::memcpy(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,
101038a82413SPavel Labath m_xstate->xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
1011cda0ae46SValentina Giusti sizeof(MPXCsr));
1012cda0ae46SValentina Giusti }
1013cda0ae46SValentina Giusti return true;
1014cda0ae46SValentina Giusti }
1015cda0ae46SValentina Giusti
CopyMPXtoXSTATE(uint32_t reg)1016cda0ae46SValentina Giusti bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) {
1017cda0ae46SValentina Giusti if (!IsMPX(reg))
1018cda0ae46SValentina Giusti return false;
1019cda0ae46SValentina Giusti
1020cda0ae46SValentina Giusti if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
102138a82413SPavel Labath ::memcpy(m_xstate->xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
1022cda0ae46SValentina Giusti m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg));
1023cda0ae46SValentina Giusti } else {
102438a82413SPavel Labath ::memcpy(m_xstate->xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
1025cda0ae46SValentina Giusti m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr));
1026cda0ae46SValentina Giusti }
1027cda0ae46SValentina Giusti return true;
1028cda0ae46SValentina Giusti }
1029cda0ae46SValentina Giusti
1030e46c6644SGuilherme Andrade uint32_t
GetPtraceOffset(uint32_t reg_index)1031e46c6644SGuilherme Andrade NativeRegisterContextLinux_x86_64::GetPtraceOffset(uint32_t reg_index) {
1032e46c6644SGuilherme Andrade // If register is MPX, remove extra factor from gdb offset
1033e46c6644SGuilherme Andrade return GetRegisterInfoAtIndex(reg_index)->byte_offset -
1034e46c6644SGuilherme Andrade (IsMPX(reg_index) ? 128 : 0);
1035e46c6644SGuilherme Andrade }
1036e46c6644SGuilherme Andrade
10372c4226f8SPavel Labath llvm::Optional<NativeRegisterContextLinux::SyscallData>
GetSyscallData()10382c4226f8SPavel Labath NativeRegisterContextLinux_x86_64::GetSyscallData() {
10392c4226f8SPavel Labath switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
10402c4226f8SPavel Labath case llvm::Triple::x86: {
10412c4226f8SPavel Labath static const uint8_t Int80[] = {0xcd, 0x80};
10422c4226f8SPavel Labath static const uint32_t Args[] = {lldb_eax_i386, lldb_ebx_i386, lldb_ecx_i386,
10432c4226f8SPavel Labath lldb_edx_i386, lldb_esi_i386, lldb_edi_i386,
10442c4226f8SPavel Labath lldb_ebp_i386};
10452c4226f8SPavel Labath return SyscallData{Int80, Args, lldb_eax_i386};
10462c4226f8SPavel Labath }
10472c4226f8SPavel Labath case llvm::Triple::x86_64: {
10482c4226f8SPavel Labath static const uint8_t Syscall[] = {0x0f, 0x05};
10492c4226f8SPavel Labath static const uint32_t Args[] = {
10502c4226f8SPavel Labath lldb_rax_x86_64, lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rdx_x86_64,
10512c4226f8SPavel Labath lldb_r10_x86_64, lldb_r8_x86_64, lldb_r9_x86_64};
10522c4226f8SPavel Labath return SyscallData{Syscall, Args, lldb_rax_x86_64};
10532c4226f8SPavel Labath }
10542c4226f8SPavel Labath default:
10552c4226f8SPavel Labath llvm_unreachable("Unhandled architecture!");
10562c4226f8SPavel Labath }
10572c4226f8SPavel Labath }
10582c4226f8SPavel Labath
10592c4226f8SPavel Labath llvm::Optional<NativeRegisterContextLinux::MmapData>
GetMmapData()10602c4226f8SPavel Labath NativeRegisterContextLinux_x86_64::GetMmapData() {
10612c4226f8SPavel Labath switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
10622c4226f8SPavel Labath case llvm::Triple::x86:
10632c4226f8SPavel Labath return MmapData{192, 91};
10642c4226f8SPavel Labath case llvm::Triple::x86_64:
10652c4226f8SPavel Labath return MmapData{9, 11};
10662c4226f8SPavel Labath default:
10672c4226f8SPavel Labath llvm_unreachable("Unhandled architecture!");
10682c4226f8SPavel Labath }
10692c4226f8SPavel Labath }
10702c4226f8SPavel Labath
1071068f8a7eSTamas Berghammer #endif // defined(__i386__) || defined(__x86_64__)
1072