forked from OSchip/llvm-project
Set error message if ValueObjectRegister fails to write back to register
SetValueFromCString and SetData methods return false if register can't be written but they don't set a error message. It sometimes confuses callers of these methods because they try to get the error message in case of failure but Status::AsCString returns nullptr. For example, lldb-vscode crashes due to this bug if some register can't be written. It invokes SBError::GetCString in case of error and doesn't check whether the result is nullptr (see request_setVariable implementation in lldb-vscode.cpp for more info). Reviewed By: labath, clayborg Differential Revision: https://reviews.llvm.org/D120319
This commit is contained in:
parent
b496a172e4
commit
fd37d489cf
|
@ -269,26 +269,30 @@ bool ValueObjectRegister::SetValueFromCString(const char *value_str,
|
|||
// The new value will be in the m_data. Copy that into our register value.
|
||||
error =
|
||||
m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str));
|
||||
if (error.Success()) {
|
||||
if (m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
|
||||
SetNeedsUpdate();
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
} else
|
||||
if (!error.Success())
|
||||
return false;
|
||||
|
||||
if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
|
||||
error.SetErrorString("unable to write back to register");
|
||||
return false;
|
||||
}
|
||||
|
||||
SetNeedsUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValueObjectRegister::SetData(DataExtractor &data, Status &error) {
|
||||
error = m_reg_value.SetValueFromData(&m_reg_info, data, 0, false);
|
||||
if (error.Success()) {
|
||||
if (m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
|
||||
SetNeedsUpdate();
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
} else
|
||||
if (!error.Success())
|
||||
return false;
|
||||
|
||||
if (!m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) {
|
||||
error.SetErrorString("unable to write back to register");
|
||||
return false;
|
||||
}
|
||||
|
||||
SetNeedsUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValueObjectRegister::ResolveValue(Scalar &scalar) {
|
||||
|
|
|
@ -133,6 +133,29 @@ class LinuxCoreTestCase(TestBase):
|
|||
self.assertEqual(len(bytesread), 16)
|
||||
self.dbg.DeleteTarget(target)
|
||||
|
||||
@skipIfLLVMTargetMissing("X86")
|
||||
def test_write_register(self):
|
||||
"""Test that writing to register results in an error and that error
|
||||
message is set."""
|
||||
target = self.dbg.CreateTarget("linux-x86_64.out")
|
||||
process = target.LoadCore("linux-x86_64.core")
|
||||
self.assertTrue(process, PROCESS_IS_VALID)
|
||||
|
||||
thread = process.GetSelectedThread()
|
||||
self.assertTrue(thread)
|
||||
|
||||
frame = thread.GetSelectedFrame()
|
||||
self.assertTrue(frame)
|
||||
|
||||
reg_value = frame.FindRegister('eax')
|
||||
self.assertTrue(reg_value)
|
||||
|
||||
error = lldb.SBError()
|
||||
success = reg_value.SetValueFromCString('10', error)
|
||||
self.assertFalse(success)
|
||||
self.assertTrue(error.Fail())
|
||||
self.assertIsNotNone(error.GetCString())
|
||||
|
||||
@skipIfLLVMTargetMissing("X86")
|
||||
def test_FPR_SSE(self):
|
||||
# check x86_64 core file
|
||||
|
|
Loading…
Reference in New Issue