summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Linux
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
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')
-rwxr-xr-xlldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp179
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h17
2 files changed, 185 insertions, 11 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)
{
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
index b04be4bb768..5ac5f85ce57 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
@@ -111,6 +111,7 @@ namespace process_linux {
uint32_t num_gpr_registers;
uint32_t num_fpr_registers;
uint32_t num_avx_registers;
+ uint32_t num_mpx_registers;
uint32_t last_gpr;
uint32_t first_fpr;
@@ -124,6 +125,10 @@ namespace process_linux {
uint32_t last_xmm;
uint32_t first_ymm;
uint32_t last_ymm;
+ uint32_t first_mpxr;
+ uint32_t last_mpxr;
+ uint32_t first_mpxc;
+ uint32_t last_mpxc;
uint32_t first_dr;
uint32_t gpr_flags;
@@ -134,6 +139,7 @@ namespace process_linux {
FPR m_fpr;
IOVEC m_iovec;
YMM m_ymm_set;
+ MPX m_mpx_set;
RegInfo m_reg_info;
uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64];
uint32_t m_fctrl_offset_in_userarea;
@@ -160,7 +166,16 @@ namespace process_linux {
CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order);
bool
- IsAVX (uint32_t reg_index) const;
+ CopyXSTATEtoMPX(uint32_t reg);
+
+ bool
+ CopyMPXtoXSTATE(uint32_t reg);
+
+ bool
+ IsAVX(uint32_t reg_index) const;
+
+ bool
+ IsMPX(uint32_t reg_index) const;
};
} // namespace process_linux
OpenPOWER on IntegriCloud