diff options
author | Valentina Giusti <valentina.giusti@intel.com> | 2016-09-08 14:16:45 +0000 |
---|---|---|
committer | Valentina Giusti <valentina.giusti@intel.com> | 2016-09-08 14:16:45 +0000 |
commit | cda0ae46ac9b368ee7cbb0da5aa447563dec0aae (patch) | |
tree | 6c509d4f4177d7f0e36df592219884b079561915 /lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp | |
parent | 4d1e4d76ee4636b6605e6d119322b767efc93b70 (diff) | |
download | bcm5719-llvm-cda0ae46ac9b368ee7cbb0da5aa447563dec0aae.tar.gz bcm5719-llvm-cda0ae46ac9b368ee7cbb0da5aa447563dec0aae.zip |
Fix for rL280668, Intel(R) Memory Protection Extensions (Intel(R) MPX) support.
Summary: Signed-off-by: Valentina Giusti <valentina.giusti@intel.com>
Reviewers: dvlahovski, granata.enrico, clayborg, labath
Subscribers: lldb-commits
Differential Revision: https://reviews.llvm.org/D24255
llvm-svn: 280942
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp')
-rwxr-xr-x | lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp | 149 |
1 files changed, 143 insertions, 6 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp index 369a8033a62..e7ae1f721ef 100755 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -74,6 +74,17 @@ static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - 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[] = { lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64, @@ -156,8 +167,19 @@ static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - 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 }; +enum { k_num_extended_register_sets = 2, k_num_register_sets = 4 }; // Register sets for x86 32-bit. static const RegisterSet g_reg_sets_i386[k_num_register_sets] = { @@ -166,7 +188,9 @@ static const RegisterSet g_reg_sets_i386[k_num_register_sets] = { {"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}}; + 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] = { @@ -175,7 +199,9 @@ static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = { {"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}}; + g_avx_regnums_x86_64}, + { "Memory Protection Extensions", "mpx", k_num_mpx_registers_x86_64, + g_mpx_regnums_x86_64}}; } #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR)) @@ -224,7 +250,7 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( : NativeRegisterContextLinux(native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)), m_fpr_type(eFPRTypeNotValid), m_fpr(), m_iovec(), m_ymm_set(), - m_reg_info(), m_gpr_x86_64() { + m_mpx_set(), m_reg_info(), m_gpr_x86_64() { // Set up data about ranges of valid registers. switch (target_arch.GetMachine()) { case llvm::Triple::x86: @@ -232,6 +258,7 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( 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; @@ -243,6 +270,10 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( 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; @@ -251,6 +282,7 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( 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; @@ -262,6 +294,10 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( 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; @@ -400,6 +436,24 @@ Error NativeRegisterContextLinux_x86_64::ReadRegister( 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( @@ -492,6 +546,28 @@ Error NativeRegisterContextLinux_x86_64::WriteRegister( 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 { // Get pointer to m_fpr.xstate.fxsave variable and set the data to it. @@ -537,6 +613,11 @@ Error NativeRegisterContextLinux_x86_64::WriteRegister( 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, " @@ -590,6 +671,16 @@ Error NativeRegisterContextLinux_x86_64::ReadAllRegisterValues( } } + 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)); } else { @@ -672,6 +763,17 @@ Error NativeRegisterContextLinux_x86_64::WriteAllRegisterValues( 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; @@ -684,7 +786,7 @@ bool NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable( if (GetFPRType() == eFPRTypeXSAVE) { // AVX is the first extended register set. - ++num_sets; + num_sets += 2; } return (set_index < num_sets); } @@ -732,7 +834,7 @@ bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index, 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; } @@ -873,6 +975,41 @@ Error 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) { if (wp_index >= NumSupportedHardwareWatchpoints()) |