diff options
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp')
-rwxr-xr-x | lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp | 179 |
1 files changed, 169 insertions, 10 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp index 2080d2ede37..93ee50273b9 100755 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -130,6 +130,21 @@ namespace static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - 1 == k_num_avx_registers_i386, " g_avx_regnums_i386 has wrong number of register infos"); + // x64 32-bit MPX registers. + static const uint32_t + g_mpx_regnums_i386[] = + { + lldb_bnd0_i386, + lldb_bnd1_i386, + lldb_bnd2_i386, + lldb_bnd3_i386, + lldb_bndcfgu_i386, + lldb_bndstatus_i386, + LLDB_INVALID_REGNUM // register sets need to end with this flag + }; + static_assert((sizeof(g_mpx_regnums_i386) / sizeof(g_mpx_regnums_i386[0])) - 1 == k_num_mpx_registers_i386, + "g_mpx_regnums_x86_64 has wrong number of register infos"); + // x86 64-bit general purpose registers. static const uint32_t g_gpr_regnums_x86_64[] = @@ -291,29 +306,47 @@ namespace static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - 1 == k_num_avx_registers_x86_64, "g_avx_regnums_x86_64 has wrong number of register infos"); + // x86 64-bit MPX registers. + static const uint32_t + g_mpx_regnums_x86_64[] = + { + lldb_bnd0_x86_64, + lldb_bnd1_x86_64, + lldb_bnd2_x86_64, + lldb_bnd3_x86_64, + lldb_bndcfgu_x86_64, + lldb_bndstatus_x86_64, + LLDB_INVALID_REGNUM // register sets need to end with this flag + }; + static_assert((sizeof(g_mpx_regnums_x86_64) / sizeof(g_mpx_regnums_x86_64[0])) - 1 == k_num_mpx_registers_x86_64, + "g_mpx_regnums_x86_64 has wrong number of register infos"); + // Number of register sets provided by this context. enum { k_num_extended_register_sets = 1, - k_num_register_sets = 3 + k_num_register_sets = 4 }; // Register sets for x86 32-bit. static const RegisterSet g_reg_sets_i386[k_num_register_sets] = { - { "General Purpose Registers", "gpr", k_num_gpr_registers_i386, g_gpr_regnums_i386 }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_i386, g_fpu_regnums_i386 }, - { "Advanced Vector Extensions", "avx", k_num_avx_registers_i386, g_avx_regnums_i386 } + { "General Purpose Registers", "gpr", k_num_gpr_registers_i386, g_gpr_regnums_i386 }, + { "Floating Point Registers", "fpu", k_num_fpr_registers_i386, g_fpu_regnums_i386 }, + { "Advanced Vector Extensions", "avx", k_num_avx_registers_i386, g_avx_regnums_i386 }, + { "Memory Protection Extensions", "mpx", k_num_mpx_registers_i386, g_mpx_regnums_i386 } }; // Register sets for x86 64-bit. static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = { - { "General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, g_gpr_regnums_x86_64 }, - { "Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, g_fpu_regnums_x86_64 }, - { "Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, g_avx_regnums_x86_64 } + { "General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, g_gpr_regnums_x86_64 }, + { "Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, g_fpu_regnums_x86_64 }, + { "Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, g_avx_regnums_x86_64 }, + { "Memory Protection Extensions", "mpx", k_num_mpx_registers_x86_64, g_mpx_regnums_x86_64 } + }; } @@ -368,6 +401,7 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (const Arch m_fpr (), m_iovec (), m_ymm_set (), + m_mpx_set (), m_reg_info (), m_gpr_x86_64 () { @@ -379,6 +413,7 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (const Arch m_reg_info.num_gpr_registers = k_num_gpr_registers_i386; m_reg_info.num_fpr_registers = k_num_fpr_registers_i386; m_reg_info.num_avx_registers = k_num_avx_registers_i386; + m_reg_info.num_mpx_registers = k_num_mpx_registers_i386; m_reg_info.last_gpr = k_last_gpr_i386; m_reg_info.first_fpr = k_first_fpr_i386; m_reg_info.last_fpr = k_last_fpr_i386; @@ -390,6 +425,10 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (const Arch m_reg_info.last_xmm = lldb_xmm7_i386; m_reg_info.first_ymm = lldb_ymm0_i386; m_reg_info.last_ymm = lldb_ymm7_i386; + m_reg_info.first_mpxr = lldb_bnd0_i386; + m_reg_info.last_mpxr = lldb_bnd3_i386; + m_reg_info.first_mpxc = lldb_bndcfgu_i386; + m_reg_info.last_mpxc = lldb_bndstatus_i386; m_reg_info.first_dr = lldb_dr0_i386; m_reg_info.gpr_flags = lldb_eflags_i386; break; @@ -398,6 +437,7 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (const Arch m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64; m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64; m_reg_info.num_avx_registers = k_num_avx_registers_x86_64; + m_reg_info.num_mpx_registers = k_num_mpx_registers_x86_64; m_reg_info.last_gpr = k_last_gpr_x86_64; m_reg_info.first_fpr = k_first_fpr_x86_64; m_reg_info.last_fpr = k_last_fpr_x86_64; @@ -409,6 +449,10 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (const Arch m_reg_info.last_xmm = lldb_xmm15_x86_64; m_reg_info.first_ymm = lldb_ymm0_x86_64; m_reg_info.last_ymm = lldb_ymm15_x86_64; + m_reg_info.first_mpxr = lldb_bnd0_x86_64; + m_reg_info.last_mpxr = lldb_bnd3_x86_64; + m_reg_info.first_mpxc = lldb_bndcfgu_x86_64; + m_reg_info.last_mpxc = lldb_bndstatus_x86_64; m_reg_info.first_dr = lldb_dr0_x86_64; m_reg_info.gpr_flags = lldb_rflags_x86_64; break; @@ -554,7 +598,28 @@ NativeRegisterContextLinux_x86_64::ReadRegister (const RegisterInfo *reg_info, R return error; } } - + if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) + { + if (GetFPRType() == eFPRTypeXSAVE && CopyXSTATEtoMPX(reg)) + reg_value.SetBytes(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, reg_info->byte_size, + byte_order); + else + { + error.SetErrorString("failed to copy mpx register value"); + return error; + } + } + if (reg >= m_reg_info.first_mpxc && reg <= m_reg_info.last_mpxc) + { + if (GetFPRType() == eFPRTypeXSAVE && CopyXSTATEtoMPX(reg)) + reg_value.SetBytes(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, reg_info->byte_size, + byte_order); + else + { + error.SetErrorString("failed to copy mpx register value"); + return error; + } + } if (reg_value.GetType() != RegisterValue::eTypeBytes) error.SetErrorString ("write failed - type was expected to be RegisterValue::eTypeBytes"); @@ -634,6 +699,26 @@ NativeRegisterContextLinux_x86_64::WriteRegister (const RegisterInfo *reg_info, if (!CopyYMMtoXSTATE(reg_index, GetByteOrder())) return Error ("CopyYMMtoXSTATE() failed"); } + if (reg_index >= m_reg_info.first_mpxr && reg_index <= m_reg_info.last_mpxr) + { + if (GetFPRType() != eFPRTypeXSAVE) + return Error("target processor does not support MPX"); + + ::memcpy(m_mpx_set.mpxr[reg_index - m_reg_info.first_mpxr].bytes, reg_value.GetBytes(), + reg_value.GetByteSize()); + if (!CopyMPXtoXSTATE(reg_index)) + return Error("CopyMPXtoXSTATE() failed"); + } + if (reg_index >= m_reg_info.first_mpxc && reg_index <= m_reg_info.last_mpxc) + { + if (GetFPRType() != eFPRTypeXSAVE) + return Error("target processor does not support MPX"); + + ::memcpy(m_mpx_set.mpxc[reg_index - m_reg_info.first_mpxc].bytes, reg_value.GetBytes(), + reg_value.GetByteSize()); + if (!CopyMPXtoXSTATE(reg_index)) + return Error("CopyMPXtoXSTATE() failed"); + } } else { @@ -677,6 +762,12 @@ NativeRegisterContextLinux_x86_64::WriteRegister (const RegisterInfo *reg_info, if (!CopyYMMtoXSTATE(reg_index, GetByteOrder())) return Error ("CopyYMMtoXSTATE() failed"); } + + if (IsMPX(reg_index)) + { + if (!CopyMPXtoXSTATE(reg_index)) + return Error("CopyMPXtoXSTATE() failed"); + } return Error (); } return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown"); @@ -727,6 +818,17 @@ NativeRegisterContextLinux_x86_64::ReadAllRegisterValues (lldb::DataBufferSP &da } } + for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc; ++reg) + { + if (!CopyXSTATEtoMPX(reg)) + { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_x86_64::%s CopyXSTATEtoMPX() failed for reg num %" PRIu32, __FUNCTION__, + reg); + return error; + } + } + // Copy the extended register state including the assembled ymm registers. ::memcpy (dst, &m_fpr, sizeof (m_fpr)); } @@ -806,6 +908,17 @@ NativeRegisterContextLinux_x86_64::WriteAllRegisterValues (const lldb::DataBuffe return error; } } + + for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc; ++reg) + { + if (!CopyMPXtoXSTATE(reg)) + { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_x86_64::%s CopyMPXtoXSTATE() failed for reg num %" PRIu32, __FUNCTION__, + reg); + return error; + } + } } return error; @@ -820,7 +933,7 @@ NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable (uint32_t set_index) c if (GetFPRType () == eFPRTypeXSAVE) { // AVX is the first extended register set. - ++num_sets; + num_sets += 2; } return (set_index < num_sets); } @@ -870,7 +983,8 @@ NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index, FPRType fpr_type) c bool generic_fpr = IsFPR(reg_index); if (fpr_type == eFPRTypeXSAVE) - return generic_fpr || IsAVX(reg_index); + return generic_fpr || IsAVX(reg_index) || IsMPX(reg_index); + return generic_fpr; } @@ -1005,6 +1119,7 @@ NativeRegisterContextLinux_x86_64::ReadFPR () { const FPRType fpr_type = GetFPRType (); const lldb_private::ArchSpec& target_arch = GetRegisterInfoInterface().GetTargetArchitecture(); + switch (fpr_type) { case FPRType::eFPRTypeFXSAVE: @@ -1029,6 +1144,50 @@ NativeRegisterContextLinux_x86_64::ReadFPR () } } +bool +NativeRegisterContextLinux_x86_64::IsMPX(uint32_t reg_index) const +{ + return (m_reg_info.first_mpxr <= reg_index && reg_index <= m_reg_info.last_mpxc); +} + +bool +NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) +{ + if (!IsMPX(reg)) + return false; + + if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) + { + ::memcpy(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, + m_fpr.xstate.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg)); + } + else + { + ::memcpy(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, + m_fpr.xstate.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr)); + } + return true; +} + +bool +NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) +{ + if (!IsMPX(reg)) + return false; + + if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) + { + ::memcpy(m_fpr.xstate.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, + m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg)); + } + else + { + ::memcpy(m_fpr.xstate.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, + m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr)); + } + return true; +} + Error NativeRegisterContextLinux_x86_64::IsWatchpointHit(uint32_t wp_index, bool &is_hit) { |