[Lldb-commits] [lldb] r246955 - Bug 24457 - X87 FPU Special Purpose Registers

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Mon Sep 7 01:58:25 PDT 2015


Hi,

this new test fails when the inferior is compiled with clang, as the
produced line tables are not what you expect. I have marked it as
XFAIL to get the bots green, but it would be great if we could write
it in a way that works on clang as well.

pl


On 7 September 2015 at 08:40, Abhishek Aggarwal via lldb-commits
<lldb-commits at lists.llvm.org> wrote:
> Author: abhishek
> Date: Mon Sep  7 02:40:16 2015
> New Revision: 246955
>
> URL: http://llvm.org/viewvc/llvm-project?rev=246955&view=rev
> Log:
> Bug 24457 - X87 FPU Special Purpose Registers
>
> Summary:
>   - For 'register read --all' command on x86_64-Linux Platform:
>
>       -- Provide correct values of X87 FPU Special Purpose Registers
>       -- Both 32-bit & 64-bit inferiors give correct values on this
>          Platform
>
>   - Added a Test Vector:
>       -- To verify the expected behaviour of the command
>
> Signed-off-by: Abhishek Aggarwal <abhishek.a.aggarwal at intel.com>
>
> Reviewers: ashok.thirumurthi, granata.enrico, tfiala, clayborg
>
> Differential Revision: http://reviews.llvm.org/D12592
>
> Added:
>     lldb/trunk/test/functionalities/register/a.cpp   (with props)
> Modified:
>     lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp   (contents, props changed)
>     lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h
>     lldb/trunk/test/functionalities/register/Makefile   (contents, props changed)
>     lldb/trunk/test/functionalities/register/TestRegisters.py   (contents, props changed)
>     lldb/trunk/test/functionalities/register/main.cpp   (contents, props changed)
>
> 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=246955&r1=246954&r2=246955&view=diff
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp (original)
> +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp Mon Sep  7 02:40:16 2015
> @@ -422,6 +422,10 @@ NativeRegisterContextLinux_x86_64::Nativ
>
>      // Clear out the FPR state.
>      ::memset(&m_fpr, 0, sizeof(FPR));
> +
> +    // Store byte offset of fctrl (i.e. first register of FPR)
> +    const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl");
> +    m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;
>  }
>
>  // CONSIDER after local and llgs debugging are merged, register set support can
> @@ -559,8 +563,16 @@ NativeRegisterContextLinux_x86_64::ReadR
>      }
>
>      // Get pointer to m_fpr.xstate.fxsave variable and set the data from it.
> -    assert (reg_info->byte_offset < sizeof(m_fpr));
> -    uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
> +
> +    // Byte offsets of all registers are calculated wrt 'UserArea' structure.
> +    // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)}
> +    // and stores them in 'm_fpr' (of type FPR structure). To extract values of fpu
> +    // registers, m_fpr should be read at byte offsets calculated wrt to FPR structure.
> +
> +    // 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;
>      switch (reg_info->byte_size)
>      {
>          case 2:
> @@ -620,8 +632,16 @@ NativeRegisterContextLinux_x86_64::Write
>          else
>          {
>              // Get pointer to m_fpr.xstate.fxsave variable and set the data to it.
> -            assert (reg_info->byte_offset < sizeof(m_fpr));
> -            uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset;
> +
> +            // Byte offsets of all registers are calculated wrt 'UserArea' structure.
> +            // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only fpu
> +            // registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu registers should
> +            // be written in m_fpr at byte offsets calculated wrt FPR structure.
> +
> +            // 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 *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
>              switch (reg_info->byte_size)
>              {
>                  case 2:
>
> Propchange: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> 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=246955&r1=246954&r2=246955&view=diff
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h (original)
> +++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h Mon Sep  7 02:40:16 2015
> @@ -136,6 +136,7 @@ namespace process_linux {
>          YMM m_ymm_set;
>          RegInfo m_reg_info;
>          uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64];
> +        uint32_t m_fctrl_offset_in_userarea;
>
>          // Private member methods.
>          bool IsRegisterSetAvailable (uint32_t set_index) const;
>
> Modified: lldb/trunk/test/functionalities/register/Makefile
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/register/Makefile?rev=246955&r1=246954&r2=246955&view=diff
> ==============================================================================
> --- lldb/trunk/test/functionalities/register/Makefile (original)
> +++ lldb/trunk/test/functionalities/register/Makefile Mon Sep  7 02:40:16 2015
> @@ -1,5 +1,5 @@
>  LEVEL = ../../make
>
> -CXX_SOURCES := main.cpp
> +CXX_SOURCES := main.cpp a.cpp
>
>  include $(LEVEL)/Makefile.rules
>
> Propchange: lldb/trunk/test/functionalities/register/Makefile
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Modified: lldb/trunk/test/functionalities/register/TestRegisters.py
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/register/TestRegisters.py?rev=246955&r1=246954&r2=246955&view=diff
> ==============================================================================
> --- lldb/trunk/test/functionalities/register/TestRegisters.py (original)
> +++ lldb/trunk/test/functionalities/register/TestRegisters.py Mon Sep  7 02:40:16 2015
> @@ -35,6 +35,13 @@ class RegisterCommandsTestCase(TestBase)
>          self.buildDefault()
>          self.fp_register_write()
>
> +    def test_fp_special_purpose_register_read(self):
> +        """Test commands that read fpu special purpose registers."""
> +        if not self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
> +            self.skipTest("This test requires x86 or x86_64 as the architecture for the inferior")
> +        self.buildDefault()
> +        self.fp_special_purpose_register_read()
> +
>      def test_register_expressions(self):
>          """Test expression evaluation with commands related to registers."""
>          if not self.getArchitecture() in ['amd64', 'i386', 'x86_64']:
> @@ -152,6 +159,69 @@ class RegisterCommandsTestCase(TestBase)
>          self.expect("register read " + register,
>              substrs = [register + ' = ', new_value])
>
> +    def fp_special_purpose_register_read(self):
> +        exe = os.path.join(os.getcwd(), "a.out")
> +
> +        # Create a target by the debugger.
> +        target = self.dbg.CreateTarget(exe)
> +        self.assertTrue(target, VALID_TARGET)
> +
> +        # Find the line number to break inside a.cpp.
> +        self.line = line_number('a.cpp', '// Set break point at this line.')
> +
> +        # Set breakpoint
> +        lldbutil.run_break_set_by_file_and_line (self, "a.cpp", self.line, num_expected_locations=1, loc_exact=True)
> +
> +        # Launch the process, and do not stop at the entry point.
> +        self.runCmd ("run", RUN_SUCCEEDED)
> +
> +        process = target.GetProcess()
> +        self.assertTrue(process.GetState() == lldb.eStateStopped,
> +                        PROCESS_STOPPED)
> +
> +        thread = process.GetThreadAtIndex(0)
> +        self.assertTrue(thread.IsValid(), "current thread is valid")
> +
> +        currentFrame = thread.GetFrameAtIndex(0)
> +        self.assertTrue(currentFrame.IsValid(), "current frame is valid")
> +
> +        # Extract the value of fstat and ftag flag at the point just before
> +        # we start pushing floating point values on st% register stack
> +        value = currentFrame.FindValue("fstat", lldb.eValueTypeRegister)
> +        error = lldb.SBError()
> +        reg_value_fstat_initial = value.GetValueAsUnsigned(error, 0)
> +
> +        self.assertTrue(error.Success(), "reading a value for fstat")
> +        value = currentFrame.FindValue("ftag", lldb.eValueTypeRegister)
> +        error = lldb.SBError()
> +        reg_value_ftag_initial = value.GetValueAsUnsigned(error, 0)
> +
> +        self.assertTrue(error.Success(), "reading a value for ftag")
> +        fstat_top_pointer_initial = (reg_value_fstat_initial & 0x3800)>>11
> +
> +        # Execute 'si' aka 'thread step-inst' instruction 5 times and with
> +        # every execution verify the value of fstat and ftag registers
> +        for x in range(0,5):
> +            # step into the next instruction to push a value on 'st' register stack
> +            self.runCmd ("si", RUN_SUCCEEDED)
> +
> +            # Verify fstat and save it to be used for verification in next execution of 'si' command
> +            if not (reg_value_fstat_initial & 0x3800):
> +                self.expect("register read fstat",
> +                    substrs = ['fstat' + ' = ', str("0x%0.4x" %((reg_value_fstat_initial & ~(0x3800))| 0x3800))])
> +                reg_value_fstat_initial = ((reg_value_fstat_initial & ~(0x3800))| 0x3800)
> +                fstat_top_pointer_initial = 7
> +            else :
> +                self.expect("register read fstat",
> +                    substrs = ['fstat' + ' = ', str("0x%0.4x" % (reg_value_fstat_initial - 0x0800))])
> +                reg_value_fstat_initial = (reg_value_fstat_initial - 0x0800)
> +                fstat_top_pointer_initial -= 1
> +
> +            # Verify ftag and save it to be used for verification in next execution of 'si' command
> +            self.expect("register read ftag",
> +                substrs = ['ftag' + ' = ', str("0x%0.4x" % (reg_value_ftag_initial | (1<< fstat_top_pointer_initial)))])
> +            reg_value_ftag_initial = reg_value_ftag_initial | (1<< fstat_top_pointer_initial)
> +
>      def fp_register_write(self):
>          exe = os.path.join(os.getcwd(), "a.out")
>
>
> Propchange: lldb/trunk/test/functionalities/register/TestRegisters.py
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Added: lldb/trunk/test/functionalities/register/a.cpp
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/register/a.cpp?rev=246955&view=auto
> ==============================================================================
> --- lldb/trunk/test/functionalities/register/a.cpp (added)
> +++ lldb/trunk/test/functionalities/register/a.cpp Mon Sep  7 02:40:16 2015
> @@ -0,0 +1,40 @@
> +//===-- a.cpp ------------------------------------------------*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +#include <stdio.h>
> +
> +long double
> +return_long_double (long double value)
> +{
> +  float a=2, b=4,c=8, d=16, e=32, f=64, k=128, l=256, add=0;
> +__asm__ ( "fld %1 ;"
> +       "fld %2 ;"
> +       "fld %3 ;"
> +       "fld %4 ;"
> +       "fld %5 ;"
> +       "fld %6 ;"
> +       "fld %7 ;"
> +       "fadd ;" : "=g" (add) : "g" (a), "g" (b), "g" (c), "g" (d), "g" (e), "g" (f), "g" (k), "g" (l) );  // Set break point at this line.
> +  return value;
> +}
> +
> +long double
> +outer_return_long_double (long double value)
> +{
> +  long double val = return_long_double(value);
> +  val *= 2 ;
> +  return val;
> +}
> +
> +long double
> +outermost_return_long_double (long double value)
> +{
> +  long double val = outer_return_long_double(value);
> +  val *= 2 ;
> +  return val;
> +}
>
> Propchange: lldb/trunk/test/functionalities/register/a.cpp
> ------------------------------------------------------------------------------
>     svn:executable = *
>
> Modified: lldb/trunk/test/functionalities/register/main.cpp
> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/register/main.cpp?rev=246955&r1=246954&r2=246955&view=diff
> ==============================================================================
> --- lldb/trunk/test/functionalities/register/main.cpp (original)
> +++ lldb/trunk/test/functionalities/register/main.cpp Mon Sep  7 02:40:16 2015
> @@ -15,6 +15,8 @@
>  #include <chrono>
>  #include <thread>
>
> +long double outermost_return_long_double (long double my_long_double);
> +
>  int main (int argc, char const *argv[])
>  {
>  #if defined(__linux__)
> @@ -32,6 +34,7 @@ int main (int argc, char const *argv[])
>
>      char my_string[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 0};
>      double my_double = 1234.5678;
> +    long double my_long_double = 1234.5678;
>
>      // For simplicity assume that any cmdline argument means wait for attach.
>      if (argc > 1)
> @@ -43,5 +46,6 @@ int main (int argc, char const *argv[])
>
>      printf("my_string=%s\n", my_string);
>      printf("my_double=%g\n", my_double);
> +    outermost_return_long_double (my_long_double);
>      return 0;
>  }
>
> Propchange: lldb/trunk/test/functionalities/register/main.cpp
> ------------------------------------------------------------------------------
>     svn:executable = *
>
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


More information about the lldb-commits mailing list