[Lldb-commits] [lldb] r281507 - Use Intel CPU flags to determine target supported features.

Valentina Giusti via lldb-commits lldb-commits at lists.llvm.org
Wed Sep 14 10:27:48 PDT 2016


Author: valentinagiusti
Date: Wed Sep 14 12:27:48 2016
New Revision: 281507

URL: http://llvm.org/viewvc/llvm-project?rev=281507&view=rev
Log:
Use Intel CPU flags to determine target supported features.

Summary:
This patch uses the instruction CPUID to verify that FXSAVE, XSAVE, AVX
and MPX are supported by the target hardware. In case the HW supports XSAVE,
and at least one of the extended register sets, it further checks if the
target software has the kernel support for such features, by verifying that
their XSAVE part is correctly managed.

Differential Revision: https://reviews.llvm.org/D24559

Modified:
    lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
    lldb/trunk/source/Plugins/Process/Utility/RegisterContext_x86.h

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp?rev=281507&r1=281506&r2=281507&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp Wed Sep 14 12:27:48 2016
@@ -20,6 +20,8 @@
 #include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
 
+#include <cpuid.h>
+
 using namespace lldb_private;
 using namespace lldb_private::process_linux;
 
@@ -218,6 +220,23 @@ static const RegisterSet g_reg_sets_x86_
 #define NT_PRXFPREG 0x46e62b7f
 #endif
 
+// ----------------------------------------------------------------------------
+// Required MPX define.
+// ----------------------------------------------------------------------------
+
+// Support MPX extensions also if compiled with compiler without MPX support.
+#ifndef bit_MPX
+#define bit_MPX 0x4000
+#endif
+
+// ----------------------------------------------------------------------------
+// XCR0 extended register sets masks.
+// ----------------------------------------------------------------------------
+#define mask_XSTATE_AVX (1ULL << 2)
+#define mask_XSTATE_BNDREGS (1ULL << 3)
+#define mask_XSTATE_BNDCFG (1ULL << 4)
+#define mask_XSTATE_MPX (mask_XSTATE_BNDREGS | mask_XSTATE_BNDCFG)
+
 NativeRegisterContextLinux *
 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
     const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
@@ -249,7 +268,7 @@ NativeRegisterContextLinux_x86_64::Nativ
     uint32_t concrete_frame_idx)
     : NativeRegisterContextLinux(native_thread, concrete_frame_idx,
                                  CreateRegisterInfoInterface(target_arch)),
-      m_fpr_type(eFPRTypeNotValid), m_fpr(), m_iovec(), m_ymm_set(),
+      m_xstate_type(eXStateTypeNotValid), m_fpr(), m_iovec(), 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()) {
@@ -379,7 +398,7 @@ Error NativeRegisterContextLinux_x86_64:
     return error;
   }
 
-  if (IsFPR(reg, GetFPRType())) {
+  if (IsFPR(reg) || IsAVX(reg) || IsMPX(reg)) {
     error = ReadFPR();
     if (error.Fail())
       return error;
@@ -428,7 +447,7 @@ Error NativeRegisterContextLinux_x86_64:
             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
-        if (GetFPRType() == eFPRTypeXSAVE && CopyXSTATEtoYMM(reg, byte_order))
+        if (CopyXSTATEtoYMM(reg, byte_order))
           reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
                              reg_info->byte_size, byte_order);
         else {
@@ -437,7 +456,7 @@ Error NativeRegisterContextLinux_x86_64:
         }
       }
       if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
-        if (GetFPRType() == eFPRTypeXSAVE && CopyXSTATEtoMPX(reg))
+        if (CopyXSTATEtoMPX(reg))
           reg_value.SetBytes(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,
                              reg_info->byte_size, byte_order);
         else {
@@ -446,7 +465,7 @@ Error NativeRegisterContextLinux_x86_64:
         }
       }
       if (reg >= m_reg_info.first_mpxc && reg <= m_reg_info.last_mpxc) {
-        if (GetFPRType() == eFPRTypeXSAVE && CopyXSTATEtoMPX(reg))
+        if (CopyXSTATEtoMPX(reg))
           reg_value.SetBytes(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,
                              reg_info->byte_size, byte_order);
         else {
@@ -517,7 +536,7 @@ Error NativeRegisterContextLinux_x86_64:
   if (IsGPR(reg_index))
     return WriteRegisterRaw(reg_index, reg_value);
 
-  if (IsFPR(reg_index, GetFPRType())) {
+  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(
@@ -536,9 +555,6 @@ Error NativeRegisterContextLinux_x86_64:
 
       if (reg_index >= m_reg_info.first_ymm &&
           reg_index <= m_reg_info.last_ymm) {
-        if (GetFPRType() != eFPRTypeXSAVE)
-          return Error("target processor does not support AVX");
-
         // Store ymm register content, and split into the register halves in
         // xmm.bytes and ymmh.bytes
         ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
@@ -549,9 +565,6 @@ Error NativeRegisterContextLinux_x86_64:
 
       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))
@@ -560,9 +573,6 @@ Error NativeRegisterContextLinux_x86_64:
 
       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))
@@ -654,31 +664,37 @@ Error NativeRegisterContextLinux_x86_64:
 
   ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());
   dst += GetRegisterInfoInterface().GetGPRSize();
-  if (GetFPRType() == eFPRTypeFXSAVE)
+  if (GetXStateType() == eXStateTypeFXSAVE)
     ::memcpy(dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
-  else if (GetFPRType() == eFPRTypeXSAVE) {
+  else if (GetXStateType() == eXStateTypeXSAVE) {
     lldb::ByteOrder byte_order = GetByteOrder();
 
-    // Assemble the YMM register content from the register halves.
-    for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
-         ++reg) {
-      if (!CopyXSTATEtoYMM(reg, byte_order)) {
-        error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
-                                       "CopyXSTATEtoYMM() failed for reg num "
-                                       "%" PRIu32,
-                                       __FUNCTION__, reg);
-        return error;
+    if (IsCPUFeatureAvailable(avx)) {
+      // Assemble the YMM register content from the register halves.
+      for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
+           ++reg) {
+        if (!CopyXSTATEtoYMM(reg, byte_order)) {
+          error.SetErrorStringWithFormat(
+              "NativeRegisterContextLinux_x86_64::%s "
+              "CopyXSTATEtoYMM() failed for reg num "
+              "%" PRIu32,
+              __FUNCTION__, reg);
+          return error;
+        }
       }
     }
 
-    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;
+    if (IsCPUFeatureAvailable(mpx)) {
+      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.
@@ -740,38 +756,44 @@ Error NativeRegisterContextLinux_x86_64:
     return error;
 
   src += GetRegisterInfoInterface().GetGPRSize();
-  if (GetFPRType() == eFPRTypeFXSAVE)
+  if (GetXStateType() == eXStateTypeFXSAVE)
     ::memcpy(&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave));
-  else if (GetFPRType() == eFPRTypeXSAVE)
+  else if (GetXStateType() == eXStateTypeXSAVE)
     ::memcpy(&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
 
   error = WriteFPR();
   if (error.Fail())
     return error;
 
-  if (GetFPRType() == eFPRTypeXSAVE) {
+  if (GetXStateType() == eXStateTypeXSAVE) {
     lldb::ByteOrder byte_order = GetByteOrder();
 
-    // Parse the YMM register content from the register halves.
-    for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
-         ++reg) {
-      if (!CopyYMMtoXSTATE(reg, byte_order)) {
-        error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s "
-                                       "CopyYMMtoXSTATE() failed for reg num "
-                                       "%" PRIu32,
-                                       __FUNCTION__, reg);
-        return error;
+    if (IsCPUFeatureAvailable(avx)) {
+      // Parse the YMM register content from the register halves.
+      for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
+           ++reg) {
+        if (!CopyYMMtoXSTATE(reg, byte_order)) {
+          error.SetErrorStringWithFormat(
+              "NativeRegisterContextLinux_x86_64::%s "
+              "CopyYMMtoXSTATE() failed for reg num "
+              "%" PRIu32,
+              __FUNCTION__, reg);
+          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;
+    if (IsCPUFeatureAvailable(mpx)) {
+      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;
+        }
       }
     }
   }
@@ -779,16 +801,75 @@ Error NativeRegisterContextLinux_x86_64:
   return error;
 }
 
+bool NativeRegisterContextLinux_x86_64::HasFXSAVE() const {
+  unsigned int rax, rbx, rcx, rdx;
+
+  // Check if FXSAVE is enabled.
+  if (!__get_cpuid(1, &rax, &rbx, &rcx, &rdx))
+    return false;
+  if ((rdx & bit_FXSAVE) == bit_FXSAVE) {
+    m_xstate_type = eXStateTypeFXSAVE;
+    if (const_cast<NativeRegisterContextLinux_x86_64 *>(this)->ReadFPR().Fail())
+      return false;
+    return true;
+  }
+  return false;
+}
+
+bool NativeRegisterContextLinux_x86_64::HasXSAVE() const {
+  unsigned int rax, rbx, rcx, rdx;
+
+  // Check if XSAVE is enabled.
+  if (!__get_cpuid(1, &rax, &rbx, &rcx, &rdx))
+    return false;
+  if ((rcx & bit_OSXSAVE) == bit_OSXSAVE) {
+    m_xstate_type = eXStateTypeXSAVE;
+    if (const_cast<NativeRegisterContextLinux_x86_64 *>(this)->ReadFPR().Fail())
+      return false;
+    return true;
+  }
+  return false;
+}
+
+bool NativeRegisterContextLinux_x86_64::IsCPUFeatureAvailable(
+    RegSet feature_code) const {
+  unsigned int rax, rbx, rcx, rdx;
+
+  // Check if XSAVE is enabled.
+  if (!HasXSAVE())
+    return false;
+
+  __get_cpuid(1, &rax, &rbx, &rcx, &rdx);
+  switch (feature_code) {
+  case avx: // Check if CPU has AVX and if there is kernel support, by reading in the XCR0 area of XSAVE.
+    if (((rcx & bit_AVX) != 0) && ((m_fpr.xstate.xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX))
+      return true;
+  case mpx: // Check if CPU has MPX and if there is kernel support, by reading in the XCR0 area of XSAVE.
+    if (__get_cpuid_max(0, NULL) > 7) {
+      __cpuid_count(7, 0, rax, rbx, rcx, rdx);
+      if (((rbx & bit_MPX) != 0) && ((m_fpr.xstate.xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX))
+        return true;
+    }
+  default:
+    return false;
+  }
+}
+
 bool NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable(
     uint32_t set_index) const {
-  // Note: Extended register sets are assumed to be at the end of g_reg_sets.
   uint32_t num_sets = k_num_register_sets - k_num_extended_register_sets;
 
-  if (GetFPRType() == eFPRTypeXSAVE) {
-    // AVX is the first extended register set.
-    num_sets += 2;
+  switch (set_index) {
+  case gpr:
+  case fpu:
+    return (set_index < num_sets);
+  case avx:
+    return IsCPUFeatureAvailable(avx);
+  case mpx:
+    return IsCPUFeatureAvailable(mpx);
+  default:
+    return false;
   }
-  return (set_index < num_sets);
 }
 
 bool NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const {
@@ -796,32 +877,15 @@ bool NativeRegisterContextLinux_x86_64::
   return reg_index <= m_reg_info.last_gpr;
 }
 
-NativeRegisterContextLinux_x86_64::FPRType
-NativeRegisterContextLinux_x86_64::GetFPRType() const {
-  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-  if (m_fpr_type == eFPRTypeNotValid) {
-    // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx.
-
-    // Try and see if AVX register retrieval works.
-    m_fpr_type = eFPRTypeXSAVE;
-    if (const_cast<NativeRegisterContextLinux_x86_64 *>(this)
-            ->ReadFPR()
-            .Fail()) {
-      // Fall back to general floating point with no AVX support.
-      m_fpr_type = eFPRTypeFXSAVE;
-
-      // Check if FXSAVE area can be read.
-      if (const_cast<NativeRegisterContextLinux_x86_64 *>(this)
-              ->ReadFPR()
-              .Fail()) {
-        if (log)
-          log->Printf("NativeRegisterContextLinux_x86_64::%s ptrace APIs "
-                      "failed to read XSAVE/FXSAVE area",
-                      __FUNCTION__);
-      }
-    }
+NativeRegisterContextLinux_x86_64::XStateType
+NativeRegisterContextLinux_x86_64::GetXStateType() const {
+  if (m_xstate_type == eXStateTypeNotValid) {
+    if (HasXSAVE())
+      m_xstate_type = eXStateTypeXSAVE;
+    else if (HasFXSAVE())
+      m_xstate_type = eXStateTypeFXSAVE;
   }
-  return m_fpr_type;
+  return m_xstate_type;
 }
 
 bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const {
@@ -829,21 +893,12 @@ bool NativeRegisterContextLinux_x86_64::
           reg_index <= m_reg_info.last_fpr);
 }
 
-bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index,
-                                              FPRType fpr_type) const {
-  bool generic_fpr = IsFPR(reg_index);
-
-  if (fpr_type == eFPRTypeXSAVE)
-    return generic_fpr || IsAVX(reg_index) || IsMPX(reg_index);
-  return generic_fpr;
-}
-
 Error NativeRegisterContextLinux_x86_64::WriteFPR() {
-  const FPRType fpr_type = GetFPRType();
+  const XStateType fpr_type = GetXStateType();
   const lldb_private::ArchSpec &target_arch =
       GetRegisterInfoInterface().GetTargetArchitecture();
   switch (fpr_type) {
-  case FPRType::eFPRTypeFXSAVE:
+  case XStateType::eXStateTypeFXSAVE:
     // For 32-bit inferiors on x86_32/x86_64 architectures,
     // FXSAVE area can be written using PTRACE_SETREGSET ptrace api
     // For 64-bit inferiors on x86_64 architectures,
@@ -858,7 +913,7 @@ Error NativeRegisterContextLinux_x86_64:
       assert(false && "Unhandled target architecture.");
       break;
     }
-  case FPRType::eFPRTypeXSAVE:
+  case XStateType::eXStateTypeXSAVE:
     return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave),
                             NT_X86_XSTATE);
   default:
@@ -867,6 +922,8 @@ Error NativeRegisterContextLinux_x86_64:
 }
 
 bool NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const {
+  if (!IsCPUFeatureAvailable(avx))
+    return false;
   return (m_reg_info.first_ymm <= reg_index &&
           reg_index <= m_reg_info.last_ymm);
 }
@@ -926,11 +983,11 @@ bool NativeRegisterContextLinux_x86_64::
 }
 
 void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() {
-  const FPRType fpr_type = GetFPRType();
-  switch (fpr_type) {
-  case FPRType::eFPRTypeFXSAVE:
+  const XStateType xstate_type = GetXStateType();
+  switch (xstate_type) {
+  case XStateType::eXStateTypeFXSAVE:
     return &m_fpr.xstate.fxsave;
-  case FPRType::eFPRTypeXSAVE:
+  case XStateType::eXStateTypeXSAVE:
     return &m_iovec;
   default:
     return nullptr;
@@ -938,11 +995,11 @@ void *NativeRegisterContextLinux_x86_64:
 }
 
 size_t NativeRegisterContextLinux_x86_64::GetFPRSize() {
-  const FPRType fpr_type = GetFPRType();
-  switch (fpr_type) {
-  case FPRType::eFPRTypeFXSAVE:
+  const XStateType xstate_type = GetXStateType();
+  switch (xstate_type) {
+  case XStateType::eXStateTypeFXSAVE:
     return sizeof(m_fpr.xstate.fxsave);
-  case FPRType::eFPRTypeXSAVE:
+  case XStateType::eXStateTypeXSAVE:
     return sizeof(m_iovec);
   default:
     return 0;
@@ -950,11 +1007,11 @@ size_t NativeRegisterContextLinux_x86_64
 }
 
 Error NativeRegisterContextLinux_x86_64::ReadFPR() {
-  const FPRType fpr_type = GetFPRType();
+  const XStateType xstate_type = GetXStateType();
   const lldb_private::ArchSpec &target_arch =
       GetRegisterInfoInterface().GetTargetArchitecture();
-  switch (fpr_type) {
-  case FPRType::eFPRTypeFXSAVE:
+  switch (xstate_type) {
+  case XStateType::eXStateTypeFXSAVE:
     // For 32-bit inferiors on x86_32/x86_64 architectures,
     // FXSAVE area can be read using PTRACE_GETREGSET ptrace api
     // For 64-bit inferiors on x86_64 architectures,
@@ -968,7 +1025,7 @@ Error NativeRegisterContextLinux_x86_64:
       assert(false && "Unhandled target architecture.");
       break;
     }
-  case FPRType::eFPRTypeXSAVE:
+  case XStateType::eXStateTypeXSAVE:
     return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
   default:
     return Error("Unrecognized FPR type");
@@ -976,8 +1033,10 @@ Error NativeRegisterContextLinux_x86_64:
 }
 
 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);
+  if (!IsCPUFeatureAvailable(mpx))
+    return false;
+  return (m_reg_info.first_mpxr <= reg_index &&
+          reg_index <= m_reg_info.last_mpxc);
 }
 
 bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) {

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h?rev=281507&r1=281506&r2=281507&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h Wed Sep 14 12:27:48 2016
@@ -77,7 +77,8 @@ protected:
 
 private:
   // Private member types.
-  enum FPRType { eFPRTypeNotValid = 0, eFPRTypeFXSAVE, eFPRTypeXSAVE };
+  enum XStateType { eXStateTypeNotValid = 0, eXStateTypeFXSAVE, eXStateTypeXSAVE };
+  enum RegSet { gpr, fpu, avx, mpx };
 
   // Info about register ranges.
   struct RegInfo {
@@ -106,8 +107,8 @@ private:
   };
 
   // Private member variables.
-  mutable FPRType m_fpr_type;
-  FPR m_fpr;
+  mutable XStateType m_xstate_type;
+  FPR m_fpr; // Extended States Area, named FPR for historical reasons.
   IOVEC m_iovec;
   YMM m_ymm_set;
   MPX m_mpx_set;
@@ -116,16 +117,20 @@ private:
   uint32_t m_fctrl_offset_in_userarea;
 
   // Private member methods.
+  bool HasFXSAVE() const;
+
+  bool HasXSAVE() const;
+
+  bool IsCPUFeatureAvailable(RegSet feature_code) const;
+
   bool IsRegisterSetAvailable(uint32_t set_index) const;
 
   bool IsGPR(uint32_t reg_index) const;
 
-  FPRType GetFPRType() const;
+  XStateType GetXStateType() const;
 
   bool IsFPR(uint32_t reg_index) const;
 
-  bool IsFPR(uint32_t reg_index, FPRType fpr_type) const;
-
   bool CopyXSTATEtoYMM(uint32_t reg_index, lldb::ByteOrder byte_order);
 
   bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order);

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContext_x86.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContext_x86.h?rev=281507&r1=281506&r2=281507&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContext_x86.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContext_x86.h Wed Sep 14 12:27:48 2016
@@ -277,7 +277,9 @@ struct FXSAVE {
   uint32_t mxcsrmask; // MXCSR Mask
   MMSReg stmm[8];     // 8*16 bytes for each FP-reg = 128 bytes
   XMMReg xmm[16];     // 16*16 bytes for each XMM-reg = 256 bytes
-  uint32_t padding[24];
+  uint8_t padding1[48];
+  uint64_t xcr0;
+  uint8_t padding2[40];
 };
 
 //---------------------------------------------------------------------------




More information about the lldb-commits mailing list