summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
diff options
context:
space:
mode:
authorValentina Giusti <valentina.giusti@intel.com>2016-09-05 17:43:10 +0000
committerValentina Giusti <valentina.giusti@intel.com>2016-09-05 17:43:10 +0000
commitf105abbc0d0bf316f43ca6a3e0b2aae6daedf1d6 (patch)
tree9547ee4b31a6203a7a6e3745ae475ad792befc46 /lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
parent9bd34f975157df546bd57e7a5d86a8aace7d573b (diff)
downloadbcm5719-llvm-f105abbc0d0bf316f43ca6a3e0b2aae6daedf1d6.tar.gz
bcm5719-llvm-f105abbc0d0bf316f43ca6a3e0b2aae6daedf1d6.zip
Intel(R) Memory Protection Extensions (Intel(R) MPX) support.
Summary: The Intel(R) Memory Protection Extensions (Intel(R) MPX) associates pointers to bounds, against which the software can check memory references to prevent out of bound memory access. This patch allows accessing the MPX registers: * bnd0-3: 128-bit registers to hold the bound values, * bndcfgu, bndstatus: 64-bit configuration registers, This patch also adds read/write tests for the MPX registers in the register command tests and adds a new subdirectory for MPX specific tests. Signed-off-by: Valentina Giusti <valentina.giusti@intel.com> Reviewers: labath, granata.enrico, lldb-commits, clayborg Subscribers: lldb-commits Differential Revision: https://reviews.llvm.org/D24187 llvm-svn: 280668
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp')
-rwxr-xr-xlldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp179
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)
{
OpenPOWER on IntegriCloud