|
|
|
@@ -19,9 +19,26 @@
|
|
|
|
|
|
|
|
|
|
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
|
|
|
|
|
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
|
|
|
|
|
|
|
|
|
|
#include <cpuid.h>
|
|
|
|
|
#include <linux/elf.h>
|
|
|
|
|
|
|
|
|
|
// Newer toolchains define __get_cpuid_count in cpuid.h, but some
|
|
|
|
|
// older-but-still-supported ones (e.g. gcc 5.4.0) don't, so we
|
|
|
|
|
// define it locally here, following the definition in clang/lib/Headers.
|
|
|
|
|
static inline int get_cpuid_count(unsigned int __leaf,
|
|
|
|
|
unsigned int __subleaf,
|
|
|
|
|
unsigned int *__eax, unsigned int *__ebx,
|
|
|
|
|
unsigned int *__ecx, unsigned int *__edx)
|
|
|
|
|
{
|
|
|
|
|
unsigned int __max_leaf = __get_cpuid_max(__leaf & 0x80000000, 0);
|
|
|
|
|
|
|
|
|
|
if (__max_leaf == 0 || __max_leaf < __leaf)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
__cpuid_count(__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
using namespace lldb_private::process_linux;
|
|
|
|
|
|
|
|
|
@@ -268,12 +285,29 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Return the size of the XSTATE area supported on this cpu. It is necessary to
|
|
|
|
|
// allocate the full size of the area even if we do not use/recognise all of it
|
|
|
|
|
// because ptrace(PTRACE_SETREGSET, NT_X86_XSTATE) will refuse to write to it if
|
|
|
|
|
// we do not pass it a buffer of sufficient size. The size is always at least
|
|
|
|
|
// sizeof(FPR) so that the allocated buffer can be safely cast to FPR*.
|
|
|
|
|
static std::size_t GetXSTATESize() {
|
|
|
|
|
unsigned int eax, ebx, ecx, edx;
|
|
|
|
|
// First check whether the XSTATE are is supported at all.
|
|
|
|
|
if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx) || !(ecx & bit_XSAVE))
|
|
|
|
|
return sizeof(FPR);
|
|
|
|
|
|
|
|
|
|
// Then fetch the maximum size of the area.
|
|
|
|
|
if (!get_cpuid_count(0x0d, 0, &eax, &ebx, &ecx, &edx))
|
|
|
|
|
return sizeof(FPR);
|
|
|
|
|
return std::max<std::size_t>(ecx, sizeof(FPR));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
|
|
|
|
|
const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
|
|
|
|
|
: NativeRegisterContextLinux(native_thread,
|
|
|
|
|
CreateRegisterInfoInterface(target_arch)),
|
|
|
|
|
m_xstate_type(XStateType::Invalid), m_fpr(), m_iovec(), m_ymm_set(),
|
|
|
|
|
m_mpx_set(), m_reg_info(), m_gpr_x86_64() {
|
|
|
|
|
m_xstate_type(XStateType::Invalid), m_ymm_set(), 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:
|
|
|
|
@@ -329,14 +363,13 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize m_iovec to point to the buffer and buffer size using the
|
|
|
|
|
// conventions of Berkeley style UIO structures, as required by PTRACE
|
|
|
|
|
// extensions.
|
|
|
|
|
m_iovec.iov_base = &m_fpr;
|
|
|
|
|
m_iovec.iov_len = sizeof(m_fpr);
|
|
|
|
|
std::size_t xstate_size = GetXSTATESize();
|
|
|
|
|
m_xstate.reset(static_cast<FPR *>(std::malloc(xstate_size)));
|
|
|
|
|
m_iovec.iov_base = m_xstate.get();
|
|
|
|
|
m_iovec.iov_len = xstate_size;
|
|
|
|
|
|
|
|
|
|
// Clear out the FPR state.
|
|
|
|
|
::memset(&m_fpr, 0, sizeof(m_fpr));
|
|
|
|
|
::memset(m_xstate.get(), 0, xstate_size);
|
|
|
|
|
|
|
|
|
|
// Store byte offset of fctrl (i.e. first register of FPR)
|
|
|
|
|
const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl");
|
|
|
|
@@ -439,14 +472,17 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
|
|
|
|
|
|
|
|
|
|
if (byte_order != lldb::eByteOrderInvalid) {
|
|
|
|
|
if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
|
|
|
|
|
reg_value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes,
|
|
|
|
|
reg_info->byte_size, byte_order);
|
|
|
|
|
reg_value.SetBytes(
|
|
|
|
|
m_xstate->fxsave.stmm[reg - m_reg_info.first_st].bytes,
|
|
|
|
|
reg_info->byte_size, byte_order);
|
|
|
|
|
if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
|
|
|
|
|
reg_value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes,
|
|
|
|
|
reg_info->byte_size, byte_order);
|
|
|
|
|
reg_value.SetBytes(
|
|
|
|
|
m_xstate->fxsave.stmm[reg - m_reg_info.first_mm].bytes,
|
|
|
|
|
reg_info->byte_size, byte_order);
|
|
|
|
|
if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
|
|
|
|
|
reg_value.SetBytes(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
|
|
|
|
|
reg_info->byte_size, byte_order);
|
|
|
|
|
reg_value.SetBytes(
|
|
|
|
|
m_xstate->fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
|
|
|
|
|
reg_info->byte_size, byte_order);
|
|
|
|
|
if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
|
|
|
|
|
// Concatenate ymm using the register halves in xmm.bytes and
|
|
|
|
|
// ymmh.bytes
|
|
|
|
@@ -488,7 +524,7 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get pointer to m_fpr.fxsave variable and set the data from it.
|
|
|
|
|
// Get pointer to m_xstate->fxsave variable and set the data from it.
|
|
|
|
|
|
|
|
|
|
// Byte offsets of all registers are calculated wrt 'UserArea' structure.
|
|
|
|
|
// However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)}
|
|
|
|
@@ -499,9 +535,9 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
|
|
|
|
|
// Since, FPR structure is also one of the member of UserArea structure.
|
|
|
|
|
// byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
|
|
|
|
|
// byte_offset(fctrl wrt UserArea)
|
|
|
|
|
assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
|
|
|
|
|
uint8_t *src =
|
|
|
|
|
(uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
|
|
|
|
|
assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(FPR));
|
|
|
|
|
uint8_t *src = (uint8_t *)m_xstate.get() + reg_info->byte_offset -
|
|
|
|
|
m_fctrl_offset_in_userarea;
|
|
|
|
|
switch (reg_info->byte_size) {
|
|
|
|
|
case 1:
|
|
|
|
|
reg_value.SetUInt8(*(uint8_t *)src);
|
|
|
|
@@ -527,7 +563,7 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
|
|
|
|
|
|
|
|
|
|
void NativeRegisterContextLinux_x86_64::UpdateXSTATEforWrite(
|
|
|
|
|
uint32_t reg_index) {
|
|
|
|
|
XSAVE_HDR::XFeature &xstate_bv = m_fpr.xsave.header.xstate_bv;
|
|
|
|
|
XSAVE_HDR::XFeature &xstate_bv = m_xstate->xsave.header.xstate_bv;
|
|
|
|
|
if (IsFPR(reg_index)) {
|
|
|
|
|
// IsFPR considers both %st and %xmm registers as floating point, but these
|
|
|
|
|
// map to two features. Set both flags, just in case.
|
|
|
|
@@ -559,15 +595,15 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister(
|
|
|
|
|
if (IsFPR(reg_index) || IsAVX(reg_index) || IsMPX(reg_index)) {
|
|
|
|
|
if (reg_info->encoding == lldb::eEncodingVector) {
|
|
|
|
|
if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st)
|
|
|
|
|
::memcpy(m_fpr.fxsave.stmm[reg_index - m_reg_info.first_st].bytes,
|
|
|
|
|
::memcpy(m_xstate->fxsave.stmm[reg_index - m_reg_info.first_st].bytes,
|
|
|
|
|
reg_value.GetBytes(), reg_value.GetByteSize());
|
|
|
|
|
|
|
|
|
|
if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm)
|
|
|
|
|
::memcpy(m_fpr.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes,
|
|
|
|
|
::memcpy(m_xstate->fxsave.stmm[reg_index - m_reg_info.first_mm].bytes,
|
|
|
|
|
reg_value.GetBytes(), reg_value.GetByteSize());
|
|
|
|
|
|
|
|
|
|
if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm)
|
|
|
|
|
::memcpy(m_fpr.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes,
|
|
|
|
|
::memcpy(m_xstate->fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes,
|
|
|
|
|
reg_value.GetBytes(), reg_value.GetByteSize());
|
|
|
|
|
|
|
|
|
|
if (reg_index >= m_reg_info.first_ymm &&
|
|
|
|
@@ -596,7 +632,7 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister(
|
|
|
|
|
return Status("CopyMPXtoXSTATE() failed");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Get pointer to m_fpr.fxsave variable and set the data to it.
|
|
|
|
|
// Get pointer to m_xstate->fxsave variable and set the data to it.
|
|
|
|
|
|
|
|
|
|
// Byte offsets of all registers are calculated wrt 'UserArea' structure.
|
|
|
|
|
// However, WriteFPR() takes m_fpr (of type FPR structure) and writes
|
|
|
|
@@ -608,8 +644,8 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister(
|
|
|
|
|
// byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
|
|
|
|
|
// byte_offset(fctrl wrt UserArea)
|
|
|
|
|
assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) <
|
|
|
|
|
sizeof(m_fpr));
|
|
|
|
|
uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset -
|
|
|
|
|
sizeof(FPR));
|
|
|
|
|
uint8_t *dst = (uint8_t *)m_xstate.get() + reg_info->byte_offset -
|
|
|
|
|
m_fctrl_offset_in_userarea;
|
|
|
|
|
switch (reg_info->byte_size) {
|
|
|
|
|
case 1:
|
|
|
|
@@ -667,7 +703,7 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues(
|
|
|
|
|
::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());
|
|
|
|
|
dst += GetRegisterInfoInterface().GetGPRSize();
|
|
|
|
|
if (m_xstate_type == XStateType::FXSAVE)
|
|
|
|
|
::memcpy(dst, &m_fpr.fxsave, sizeof(m_fpr.fxsave));
|
|
|
|
|
::memcpy(dst, &m_xstate->fxsave, sizeof(m_xstate->fxsave));
|
|
|
|
|
else if (m_xstate_type == XStateType::XSAVE) {
|
|
|
|
|
lldb::ByteOrder byte_order = GetByteOrder();
|
|
|
|
|
|
|
|
|
@@ -700,7 +736,7 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Copy the extended register state including the assembled ymm registers.
|
|
|
|
|
::memcpy(dst, &m_fpr, sizeof(m_fpr));
|
|
|
|
|
::memcpy(dst, m_xstate.get(), sizeof(FPR));
|
|
|
|
|
} else {
|
|
|
|
|
assert(false && "how do we save the floating point registers?");
|
|
|
|
|
error.SetErrorString("unsure how to save the floating point registers");
|
|
|
|
@@ -758,9 +794,9 @@ Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues(
|
|
|
|
|
|
|
|
|
|
src += GetRegisterInfoInterface().GetGPRSize();
|
|
|
|
|
if (m_xstate_type == XStateType::FXSAVE)
|
|
|
|
|
::memcpy(&m_fpr.fxsave, src, sizeof(m_fpr.fxsave));
|
|
|
|
|
::memcpy(&m_xstate->fxsave, src, sizeof(m_xstate->fxsave));
|
|
|
|
|
else if (m_xstate_type == XStateType::XSAVE)
|
|
|
|
|
::memcpy(&m_fpr.xsave, src, sizeof(m_fpr.xsave));
|
|
|
|
|
::memcpy(&m_xstate->xsave, src, sizeof(m_xstate->xsave));
|
|
|
|
|
|
|
|
|
|
error = WriteFPR();
|
|
|
|
|
if (error.Fail())
|
|
|
|
@@ -814,12 +850,12 @@ bool NativeRegisterContextLinux_x86_64::IsCPUFeatureAvailable(
|
|
|
|
|
return true;
|
|
|
|
|
case RegSet::avx: // Check if CPU has AVX and if there is kernel support, by
|
|
|
|
|
// reading in the XCR0 area of XSAVE.
|
|
|
|
|
if ((m_fpr.xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX)
|
|
|
|
|
if ((m_xstate->xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX)
|
|
|
|
|
return true;
|
|
|
|
|
break;
|
|
|
|
|
case RegSet::mpx: // Check if CPU has MPX and if there is kernel support, by
|
|
|
|
|
// reading in the XCR0 area of XSAVE.
|
|
|
|
|
if ((m_fpr.xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX)
|
|
|
|
|
if ((m_xstate->xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX)
|
|
|
|
|
return true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@@ -856,10 +892,10 @@ Status NativeRegisterContextLinux_x86_64::WriteFPR() {
|
|
|
|
|
switch (m_xstate_type) {
|
|
|
|
|
case XStateType::FXSAVE:
|
|
|
|
|
return WriteRegisterSet(
|
|
|
|
|
&m_iovec, sizeof(m_fpr.fxsave),
|
|
|
|
|
&m_iovec, sizeof(m_xstate->fxsave),
|
|
|
|
|
fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture()));
|
|
|
|
|
case XStateType::XSAVE:
|
|
|
|
|
return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xsave), NT_X86_XSTATE);
|
|
|
|
|
return WriteRegisterSet(&m_iovec, sizeof(m_xstate->xsave), NT_X86_XSTATE);
|
|
|
|
|
default:
|
|
|
|
|
return Status("Unrecognized FPR type.");
|
|
|
|
|
}
|
|
|
|
@@ -879,11 +915,11 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM(
|
|
|
|
|
|
|
|
|
|
if (byte_order == lldb::eByteOrderLittle) {
|
|
|
|
|
::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
|
|
|
|
|
m_fpr.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
|
|
|
|
|
m_xstate->fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
|
|
|
|
|
sizeof(XMMReg));
|
|
|
|
|
::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes +
|
|
|
|
|
sizeof(XMMReg),
|
|
|
|
|
m_fpr.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
|
|
|
|
|
m_xstate->xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
|
|
|
|
|
sizeof(YMMHReg));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@@ -891,10 +927,10 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM(
|
|
|
|
|
if (byte_order == lldb::eByteOrderBig) {
|
|
|
|
|
::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes +
|
|
|
|
|
sizeof(XMMReg),
|
|
|
|
|
m_fpr.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
|
|
|
|
|
m_xstate->fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes,
|
|
|
|
|
sizeof(XMMReg));
|
|
|
|
|
::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
|
|
|
|
|
m_fpr.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
|
|
|
|
|
m_xstate->xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes,
|
|
|
|
|
sizeof(YMMHReg));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@@ -907,19 +943,19 @@ bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (byte_order == lldb::eByteOrderLittle) {
|
|
|
|
|
::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
|
|
|
|
|
::memcpy(m_xstate->fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
|
|
|
|
|
m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg));
|
|
|
|
|
::memcpy(m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
|
|
|
|
|
::memcpy(m_xstate->xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
|
|
|
|
|
m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
|
|
|
|
|
sizeof(YMMHReg));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (byte_order == lldb::eByteOrderBig) {
|
|
|
|
|
::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
|
|
|
|
|
::memcpy(m_xstate->fxsave.xmm[reg - m_reg_info.first_ymm].bytes,
|
|
|
|
|
m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg),
|
|
|
|
|
sizeof(XMMReg));
|
|
|
|
|
::memcpy(m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
|
|
|
|
|
::memcpy(m_xstate->xsave.ymmh[reg - m_reg_info.first_ymm].bytes,
|
|
|
|
|
m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@@ -929,7 +965,7 @@ bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(
|
|
|
|
|
void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() {
|
|
|
|
|
switch (m_xstate_type) {
|
|
|
|
|
case XStateType::FXSAVE:
|
|
|
|
|
return &m_fpr.fxsave;
|
|
|
|
|
return &m_xstate->fxsave;
|
|
|
|
|
case XStateType::XSAVE:
|
|
|
|
|
return &m_iovec;
|
|
|
|
|
default:
|
|
|
|
@@ -940,7 +976,7 @@ void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() {
|
|
|
|
|
size_t NativeRegisterContextLinux_x86_64::GetFPRSize() {
|
|
|
|
|
switch (m_xstate_type) {
|
|
|
|
|
case XStateType::FXSAVE:
|
|
|
|
|
return sizeof(m_fpr.fxsave);
|
|
|
|
|
return sizeof(m_xstate->fxsave);
|
|
|
|
|
case XStateType::XSAVE:
|
|
|
|
|
return sizeof(m_iovec);
|
|
|
|
|
default:
|
|
|
|
@@ -953,14 +989,14 @@ Status NativeRegisterContextLinux_x86_64::ReadFPR() {
|
|
|
|
|
|
|
|
|
|
// Probe XSAVE and if it is not supported fall back to FXSAVE.
|
|
|
|
|
if (m_xstate_type != XStateType::FXSAVE) {
|
|
|
|
|
error = ReadRegisterSet(&m_iovec, sizeof(m_fpr.xsave), NT_X86_XSTATE);
|
|
|
|
|
error = ReadRegisterSet(&m_iovec, sizeof(m_xstate->xsave), NT_X86_XSTATE);
|
|
|
|
|
if (!error.Fail()) {
|
|
|
|
|
m_xstate_type = XStateType::XSAVE;
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
error = ReadRegisterSet(
|
|
|
|
|
&m_iovec, sizeof(m_fpr.xsave),
|
|
|
|
|
&m_iovec, sizeof(m_xstate->xsave),
|
|
|
|
|
fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture()));
|
|
|
|
|
if (!error.Fail()) {
|
|
|
|
|
m_xstate_type = XStateType::FXSAVE;
|
|
|
|
@@ -982,11 +1018,11 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) {
|
|
|
|
|
|
|
|
|
|
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.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
|
|
|
|
|
m_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.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
|
|
|
|
|
m_xstate->xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
|
|
|
|
|
sizeof(MPXCsr));
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
@@ -997,10 +1033,10 @@ bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) {
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
|
|
|
|
|
::memcpy(m_fpr.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
|
|
|
|
|
::memcpy(m_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.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
|
|
|
|
|
::memcpy(m_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;
|
|
|
|
|