[Lldb-commits] [lldb] r319161 - Fix floating point register write on new x86 linux kernels

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Tue Nov 28 02:56:54 PST 2017


Author: labath
Date: Tue Nov 28 02:56:54 2017
New Revision: 319161

URL: http://llvm.org/viewvc/llvm-project?rev=319161&view=rev
Log:
Fix floating point register write on new x86 linux kernels

Summary:
New linux kernels (on systems that support the XSAVES instruction) will
not update the inferior registers unless the corresponding flag in the
XSAVE header is set. Normally this flag will be set in our image of the
XSAVE area (since we obtained it from the kernel), but if the inferior
has never used the corresponding register set, the respective flag can
be clear.

This fixes the issue by making sure we explicitly set the flags
corresponding to the registers we modify. I don't try to precisely match
the flags to set on each write, as the rules could get quite complicated
-- I use a simpler over-approximation instead.

This was already caught by test_fp_register_write, but that was only
because the code that ran before main() did not use some of the register
sets. Since nothing in this test relies on being stopped in main(), I
modify the test to stop at the entry point instead, so we can be sure
the inferior did not have a chance to access these registers.

Reviewers: clayborg, valentinagiusti

Subscribers: lldb-commits

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

Modified:
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/register/register_command/TestRegisters.py
    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/RegisterContextPOSIX_x86.h
    lldb/trunk/source/Plugins/Process/Utility/RegisterContext_x86.h

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/register/register_command/TestRegisters.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/register/register_command/TestRegisters.py?rev=319161&r1=319160&r2=319161&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/register/register_command/TestRegisters.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/register/register_command/TestRegisters.py Tue Nov 28 02:56:54 2017
@@ -272,14 +272,18 @@ class RegisterCommandsTestCase(TestBase)
         target = self.dbg.CreateTarget(exe)
         self.assertTrue(target, VALID_TARGET)
 
-        lldbutil.run_break_set_by_symbol(
-            self, "main", num_expected_locations=-1)
+        # Launch the process, stop at the entry point.
+        error = lldb.SBError()
+        process = target.Launch(
+                lldb.SBListener(),
+                None, None, # argv, envp
+                None, None, None, # stdin/out/err
+                self.get_process_working_directory(),
+                0, # launch flags
+                True, # stop at entry
+                error)
+        self.assertTrue(error.Success(), "Launch succeeds. Error is :" + str(error))
 
-        # Launch the process, and do not stop at the entry point.
-        process = target.LaunchSimple(
-            None, None, self.get_process_working_directory())
-
-        process = target.GetProcess()
         self.assertTrue(
             process.GetState() == lldb.eStateStopped,
             PROCESS_STOPPED)

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=319161&r1=319160&r2=319161&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp Tue Nov 28 02:56:54 2017
@@ -528,6 +528,22 @@ NativeRegisterContextLinux_x86_64::ReadR
   return error;
 }
 
+void NativeRegisterContextLinux_x86_64::UpdateXSTATEforWrite(
+    uint32_t reg_index) {
+  XSAVE_HDR::XFeature &xstate_bv = m_fpr.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.
+    xstate_bv |= XSAVE_HDR::XFeature::FP | XSAVE_HDR::XFeature::SSE;
+  } else if (IsAVX(reg_index)) {
+    // Lower bytes of some %ymm registers are shared with %xmm registers.
+    xstate_bv |= XSAVE_HDR::XFeature::YMM | XSAVE_HDR::XFeature::SSE;
+  } else if (IsMPX(reg_index)) {
+    // MPX registers map to two XSAVE features.
+    xstate_bv |= XSAVE_HDR::XFeature::BNDREGS | XSAVE_HDR::XFeature::BNDCSR;
+  }
+}
+
 Status NativeRegisterContextLinux_x86_64::WriteRegister(
     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
   assert(reg_info && "reg_info is null");
@@ -538,6 +554,8 @@ Status NativeRegisterContextLinux_x86_64
                                                ? reg_info->name
                                                : "<unknown register>");
 
+  UpdateXSTATEforWrite(reg_index);
+
   if (IsGPR(reg_index))
     return WriteRegisterRaw(reg_index, reg_value);
 

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=319161&r1=319160&r2=319161&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h Tue Nov 28 02:56:54 2017
@@ -136,6 +136,8 @@ private:
   bool CopyMPXtoXSTATE(uint32_t reg);
 
   bool IsMPX(uint32_t reg_index) const;
+
+  void UpdateXSTATEforWrite(uint32_t reg_index);
 };
 
 } // namespace process_linux

Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h?rev=319161&r1=319160&r2=319161&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h Tue Nov 28 02:56:54 2017
@@ -149,9 +149,10 @@ protected:
   RegInfo m_reg_info;
   FPRType
       m_fpr_type; // determines the type of data stored by union FPR, if any.
-  FPR m_fpr;      // floating-point registers including extended register sets.
-  IOVEC m_iovec;  // wrapper for xsave.
-  YMM m_ymm_set;  // copy of ymmh and xmm register halves.
+  lldb_private::FPR m_fpr;     // floating-point registers including extended
+                               // register sets.
+  lldb_private::IOVEC m_iovec; // wrapper for xsave.
+  lldb_private::YMM m_ymm_set; // copy of ymmh and xmm register halves.
   std::unique_ptr<lldb_private::RegisterInfoInterface>
       m_register_info_ap; // Register Info Interface (FreeBSD or Linux)
 

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=319161&r1=319160&r2=319161&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContext_x86.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContext_x86.h Tue Nov 28 02:56:54 2017
@@ -13,8 +13,10 @@
 #include <cstddef>
 #include <cstdint>
 
+#include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/Support/Compiler.h"
 
+namespace lldb_private {
 //---------------------------------------------------------------------------
 // i386 ehframe, dwarf regnums
 //---------------------------------------------------------------------------
@@ -313,13 +315,28 @@ struct MPX {
 
 LLVM_PACKED_START
 struct XSAVE_HDR {
-  uint64_t xstate_bv; // OS enabled xstate mask to determine the extended states
+  enum class XFeature : uint64_t {
+    FP = 1,
+    SSE = FP << 1,
+    YMM = SSE << 1,
+    BNDREGS = YMM << 1,
+    BNDCSR = BNDREGS << 1,
+    OPMASK = BNDCSR << 1,
+    ZMM_Hi256 = OPMASK << 1,
+    Hi16_ZMM = ZMM_Hi256 << 1,
+    PT = Hi16_ZMM << 1,
+    PKRU = PT << 1,
+    LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ PKRU)
+  };
+
+  XFeature xstate_bv; // OS enabled xstate mask to determine the extended states
                       // supported by the processor
-  uint64_t xcomp_bv;  // Mask to indicate the format of the XSAVE area and of
+  XFeature xcomp_bv;  // Mask to indicate the format of the XSAVE area and of
                       // the XRSTOR instruction
   uint64_t reserved1[1];
   uint64_t reserved2[5];
 };
+static_assert(sizeof(XSAVE_HDR) == 64, "XSAVE_HDR layout incorrect");
 LLVM_PACKED_END
 
 // x86 extensions to FXSAVE (i.e. for AVX and MPX processors)
@@ -355,4 +372,8 @@ struct IOVEC {
   size_t iov_len; // sizeof(XSAVE)
 };
 
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
+} // namespace lldb_private
+
 #endif




More information about the lldb-commits mailing list