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