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:
Ilya Nozhkin 2022-02-28 14:27:32 +08:00 committed by Chuanqi Xu
parent b496a172e4
commit fd37d489cf
2 changed files with 41 additions and 14 deletions

View File

@ -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) {

View File

@ -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