diff options
-rw-r--r-- | lldb/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp | 44 | ||||
-rw-r--r-- | lldb/test/functionalities/register/TestRegisters.py | 56 |
2 files changed, 95 insertions, 5 deletions
diff --git a/lldb/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp b/lldb/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp index 36a4a9e6e91..7fc6426d3e8 100644 --- a/lldb/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp +++ b/lldb/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp @@ -688,11 +688,47 @@ RegisterContext_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info const lldb_private::RegisterValue &value) { const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - if (IsAVX(reg)) - return false; + if (IsGPR(reg)) { + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteRegisterValue(m_thread.GetID(), GetRegOffset(reg), value); + } - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteRegisterValue(m_thread.GetID(), GetRegOffset(reg), value); + if (IsFPR(reg)) { + // Note that lldb uses slightly different naming conventions from sys/user.h + switch (reg) + { + default: + return false; + case fpu_dp: + user.i387.dp = value.GetAsUInt64(); + break; + case fpu_fcw: + user.i387.fcw = value.GetAsUInt16(); + break; + case fpu_fsw: + user.i387.fsw = value.GetAsUInt16(); + break; + case fpu_ip: + user.i387.ip = value.GetAsUInt64(); + break; + case fpu_fop: + user.i387.fop = value.GetAsUInt16(); + break; + case fpu_ftw: + user.i387.ftw = value.GetAsUInt16(); + break; + case fpu_mxcsr: + user.i387.mxcsr = value.GetAsUInt32(); + break; + case fpu_mxcsrmask: + user.i387.mxcsrmask = value.GetAsUInt32(); + break; + } + if (WriteFPR()) { + return true; + } + } + return false; } bool diff --git a/lldb/test/functionalities/register/TestRegisters.py b/lldb/test/functionalities/register/TestRegisters.py index 6a4e6957f65..c34f6722439 100644 --- a/lldb/test/functionalities/register/TestRegisters.py +++ b/lldb/test/functionalities/register/TestRegisters.py @@ -20,6 +20,13 @@ class RegisterCommandsTestCase(TestBase): self.buildDefault() self.register_commands() + def test_fp_register_write(self): + """Test commands that write to registers, in particular floating-point registers.""" + if not self.getArchitecture() in ['i386', 'x86_64']: + self.skipTest("This test requires i386 or x86_64 as the architecture for the inferior") + self.buildDefault() + self.fp_register_write() + def test_register_expressions(self): """Test expression evaluation with commands related to registers.""" if not self.getArchitecture() in ['i386', 'x86_64']: @@ -68,6 +75,52 @@ class RegisterCommandsTestCase(TestBase): self.expect("register read -s 3", substrs = ['invalid register set index: 3'], error = True) + def write_and_restore(self, frame, register): + value = frame.FindValue(register, lldb.eValueTypeRegister) + self.assertTrue(value.IsValid(), "finding a value for register " + register) + + error = lldb.SBError() + register_value = value.GetValueAsUnsigned(error, 0) + self.assertTrue(error.Success(), "reading a value for " + register) + + self.runCmd("register write " + register + " 0xff0e") + self.expect("register read " + register, + substrs = [register + ' = 0x', 'ff0e']) + + self.runCmd("register write " + register + " " + str(register_value)) + self.expect("register read " + register, + substrs = [register + ' = 0x']) + + def fp_register_write(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) + + lldbutil.run_break_set_by_symbol (self, "main", num_expected_locations=-1) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple(None, None, os.getcwd()) + + 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") + + self.write_and_restore(currentFrame, "fcw") + self.write_and_restore(currentFrame, "fsw") + self.write_and_restore(currentFrame, "ftw") + self.write_and_restore(currentFrame, "ip") + self.write_and_restore(currentFrame, "dp") + self.write_and_restore(currentFrame, "mxcsr") + self.write_and_restore(currentFrame, "mxcsrmask") + @expectedFailureLinux # bugzilla 14661 - Expressions involving XMM registers fail on Linux def register_expressions(self): """Test expression evaluation with commands related to registers.""" @@ -93,7 +146,8 @@ class RegisterCommandsTestCase(TestBase): substrs = ['eax']) # Test reading of rax and eax. - self.runCmd("register read rax eax") + self.expect("register read rax eax", + substrs = ['rax = 0x', 'eax = 0x']) # Now write rax with a unique bit pattern and test that eax indeed represents the lower half of rax. self.runCmd("register write rax 0x1234567887654321") |