diff --git a/lldb/include/lldb/Core/Value.h b/lldb/include/lldb/Core/Value.h index 164b3c6c9b77..128bdb742d07 100644 --- a/lldb/include/lldb/Core/Value.h +++ b/lldb/include/lldb/Core/Value.h @@ -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() { diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h index 0fabe9194f2c..5fb4c1594187 100644 --- a/lldb/include/lldb/Core/ValueObject.h +++ b/lldb/include/lldb/Core/ValueObject.h @@ -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 diff --git a/lldb/include/lldb/Core/ValueObjectVariable.h b/lldb/include/lldb/Core/ValueObjectVariable.h index 605374673441..897ce82d9591 100644 --- a/lldb/include/lldb/Core/ValueObjectVariable.h +++ b/lldb/include/lldb/Core/ValueObjectVariable.h @@ -57,7 +57,16 @@ 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); diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp index fda84e7656cf..7cae530ac7da 100644 --- a/lldb/source/Core/Value.cpp +++ b/lldb/source/Core/Value.cpp @@ -128,7 +128,7 @@ Value::GetValueAddressType () const } RegisterInfo * -Value::GetRegisterInfo() +Value::GetRegisterInfo() const { if (m_context_type == eContextTypeRegisterInfo) return static_cast (m_context); diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 6105a8ab31e4..2692ecc8bbc4 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -400,38 +400,50 @@ 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)) { if (m_location_str.empty()) { 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; diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp index 164592d10b98..8204f11e4b93 100644 --- a/lldb/source/Core/ValueObjectVariable.cpp +++ b/lldb/source/Core/ValueObjectVariable.cpp @@ -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); +}