<rdar://problem/13695846>
Enabling LLDB to write to variables that are stored in registers Previously, this would not work since the Value's Context loses the notion of the data being in a register We now store an "original" context that comes out of DWARF parsing, and use that context's data when attempting a write llvm-svn: 180803
This commit is contained in:
parent
0b914fe839
commit
82fabf89b4
|
@ -165,7 +165,7 @@ public:
|
|||
}
|
||||
|
||||
RegisterInfo *
|
||||
GetRegisterInfo();
|
||||
GetRegisterInfo() const;
|
||||
|
||||
Type *
|
||||
GetType();
|
||||
|
@ -173,6 +173,18 @@ public:
|
|||
Scalar &
|
||||
ResolveValue (ExecutionContext *exe_ctx, clang::ASTContext *ast_context);
|
||||
|
||||
const Scalar &
|
||||
GetScalar() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
const Vector &
|
||||
GetVector() const
|
||||
{
|
||||
return m_vector;
|
||||
}
|
||||
|
||||
Scalar &
|
||||
GetScalar()
|
||||
{
|
||||
|
|
|
@ -794,7 +794,7 @@ public:
|
|||
virtual bool
|
||||
ResolveValue (Scalar &scalar);
|
||||
|
||||
const char *
|
||||
virtual const char *
|
||||
GetLocationAsCString ();
|
||||
|
||||
const char *
|
||||
|
@ -1340,6 +1340,10 @@ protected:
|
|||
virtual lldb::clang_type_t
|
||||
GetClangTypeImpl () = 0;
|
||||
|
||||
const char *
|
||||
GetLocationAsCStringImpl (const Value& value,
|
||||
const DataExtractor& data);
|
||||
|
||||
private:
|
||||
//------------------------------------------------------------------
|
||||
// For ValueObject only
|
||||
|
|
|
@ -58,6 +58,15 @@ public:
|
|||
virtual bool
|
||||
GetDeclaration (Declaration &decl);
|
||||
|
||||
virtual const char *
|
||||
GetLocationAsCString ();
|
||||
|
||||
virtual bool
|
||||
SetValueFromCString (const char *value_str, Error& error);
|
||||
|
||||
virtual bool
|
||||
SetData (DataExtractor &data, Error &error);
|
||||
|
||||
protected:
|
||||
virtual bool
|
||||
UpdateValue ();
|
||||
|
@ -69,6 +78,7 @@ protected:
|
|||
GetClangTypeImpl ();
|
||||
|
||||
lldb::VariableSP m_variable_sp; ///< The variable that this value object is based upon
|
||||
Value m_resolved_value; ///< The value that DWARFExpression resolves this variable to before we patch it up
|
||||
|
||||
private:
|
||||
ValueObjectVariable (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp);
|
||||
|
|
|
@ -128,7 +128,7 @@ Value::GetValueAddressType () const
|
|||
}
|
||||
|
||||
RegisterInfo *
|
||||
Value::GetRegisterInfo()
|
||||
Value::GetRegisterInfo() const
|
||||
{
|
||||
if (m_context_type == eContextTypeRegisterInfo)
|
||||
return static_cast<RegisterInfo *> (m_context);
|
||||
|
|
|
@ -400,6 +400,14 @@ ValueObject::GetName() const
|
|||
|
||||
const char *
|
||||
ValueObject::GetLocationAsCString ()
|
||||
{
|
||||
return GetLocationAsCStringImpl(m_value,
|
||||
m_data);
|
||||
}
|
||||
|
||||
const char *
|
||||
ValueObject::GetLocationAsCStringImpl (const Value& value,
|
||||
const DataExtractor& data)
|
||||
{
|
||||
if (UpdateValueIfNeeded(false))
|
||||
{
|
||||
|
@ -407,31 +415,35 @@ ValueObject::GetLocationAsCString ()
|
|||
{
|
||||
StreamString sstr;
|
||||
|
||||
switch (m_value.GetValueType())
|
||||
Value::ValueType value_type = value.GetValueType();
|
||||
|
||||
switch (value_type)
|
||||
{
|
||||
case Value::eValueTypeScalar:
|
||||
case Value::eValueTypeVector:
|
||||
if (m_value.GetContextType() == Value::eContextTypeRegisterInfo)
|
||||
if (value.GetContextType() == Value::eContextTypeRegisterInfo)
|
||||
{
|
||||
RegisterInfo *reg_info = m_value.GetRegisterInfo();
|
||||
RegisterInfo *reg_info = value.GetRegisterInfo();
|
||||
if (reg_info)
|
||||
{
|
||||
if (reg_info->name)
|
||||
m_location_str = reg_info->name;
|
||||
else if (reg_info->alt_name)
|
||||
m_location_str = reg_info->alt_name;
|
||||
|
||||
m_location_str = (reg_info->encoding == lldb::eEncodingVector) ? "vector" : "scalar";
|
||||
if (m_location_str.empty())
|
||||
m_location_str = (reg_info->encoding == lldb::eEncodingVector) ? "vector" : "scalar";
|
||||
}
|
||||
}
|
||||
if (m_location_str.empty())
|
||||
m_location_str = (value_type == Value::eValueTypeVector) ? "vector" : "scalar";
|
||||
break;
|
||||
|
||||
case Value::eValueTypeLoadAddress:
|
||||
case Value::eValueTypeFileAddress:
|
||||
case Value::eValueTypeHostAddress:
|
||||
{
|
||||
uint32_t addr_nibble_size = m_data.GetAddressByteSize() * 2;
|
||||
sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size, m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));
|
||||
uint32_t addr_nibble_size = data.GetAddressByteSize() * 2;
|
||||
sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size, value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));
|
||||
m_location_str.swap(sstr.GetString());
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/RegisterValue.h"
|
||||
#include "lldb/Core/ValueObjectList.h"
|
||||
#include "lldb/Core/Value.h"
|
||||
|
||||
|
@ -138,6 +139,8 @@ ValueObjectVariable::UpdateValue ()
|
|||
m_value.SetContext(Value::eContextTypeVariable, variable);
|
||||
else
|
||||
m_error.SetErrorString ("empty constant data");
|
||||
// constant bytes can't be edited - sorry
|
||||
m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -161,6 +164,7 @@ ValueObjectVariable::UpdateValue ()
|
|||
Value old_value(m_value);
|
||||
if (expr.Evaluate (&exe_ctx, GetClangAST(), NULL, NULL, NULL, loclist_base_load_addr, NULL, m_value, &m_error))
|
||||
{
|
||||
m_resolved_value = m_value;
|
||||
m_value.SetContext(Value::eContextTypeVariable, variable);
|
||||
|
||||
Value::ValueType value_type = m_value.GetValueType();
|
||||
|
@ -249,6 +253,11 @@ ValueObjectVariable::UpdateValue ()
|
|||
|
||||
SetValueIsValid (m_error.Success());
|
||||
}
|
||||
else
|
||||
{
|
||||
// could not find location, won't allow editing
|
||||
m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL);
|
||||
}
|
||||
}
|
||||
return m_error.Success();
|
||||
}
|
||||
|
@ -313,3 +322,74 @@ ValueObjectVariable::GetDeclaration (Declaration &decl)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *
|
||||
ValueObjectVariable::GetLocationAsCString ()
|
||||
{
|
||||
return GetLocationAsCStringImpl(m_resolved_value,
|
||||
m_data);
|
||||
}
|
||||
|
||||
bool
|
||||
ValueObjectVariable::SetValueFromCString (const char *value_str, Error& error)
|
||||
{
|
||||
if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo)
|
||||
{
|
||||
RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo();
|
||||
ExecutionContext exe_ctx(GetExecutionContextRef());
|
||||
RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
|
||||
RegisterValue reg_value;
|
||||
if (!reg_info || !reg_ctx)
|
||||
{
|
||||
error.SetErrorString("unable to retrieve register info");
|
||||
return false;
|
||||
}
|
||||
error = reg_value.SetValueFromCString(reg_info, value_str);
|
||||
if (error.Fail())
|
||||
return false;
|
||||
if (reg_ctx->WriteRegister (reg_info, reg_value))
|
||||
{
|
||||
SetNeedsUpdate();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
error.SetErrorString("unable to write back to register");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return ValueObject::SetValueFromCString(value_str, error);
|
||||
}
|
||||
|
||||
bool
|
||||
ValueObjectVariable::SetData (DataExtractor &data, Error &error)
|
||||
{
|
||||
if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo)
|
||||
{
|
||||
RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo();
|
||||
ExecutionContext exe_ctx(GetExecutionContextRef());
|
||||
RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
|
||||
RegisterValue reg_value;
|
||||
if (!reg_info || !reg_ctx)
|
||||
{
|
||||
error.SetErrorString("unable to retrieve register info");
|
||||
return false;
|
||||
}
|
||||
error = reg_value.SetValueFromData(reg_info, data, 0, false);
|
||||
if (error.Fail())
|
||||
return false;
|
||||
if (reg_ctx->WriteRegister (reg_info, reg_value))
|
||||
{
|
||||
SetNeedsUpdate();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
error.SetErrorString("unable to write back to register");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return ValueObject::SetData(data, error);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue