summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp')
-rwxr-xr-xlldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp149
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())
OpenPOWER on IntegriCloud