diff options
| author | Enrico Granata <egranata@apple.com> | 2013-04-30 20:45:04 +0000 |
|---|---|---|
| committer | Enrico Granata <egranata@apple.com> | 2013-04-30 20:45:04 +0000 |
| commit | 82fabf89b493625df34b8ee5bea48a52d8b48179 (patch) | |
| tree | 4475aea2e38644ff2070f4a26f2d94e598a8c085 /lldb/source/Core | |
| parent | 0b914fe8395caa6ab1a11d829207d693e43fb957 (diff) | |
| download | bcm5719-llvm-82fabf89b493625df34b8ee5bea48a52d8b48179.tar.gz bcm5719-llvm-82fabf89b493625df34b8ee5bea48a52d8b48179.zip | |
<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
Diffstat (limited to 'lldb/source/Core')
| -rw-r--r-- | lldb/source/Core/Value.cpp | 2 | ||||
| -rw-r--r-- | lldb/source/Core/ValueObject.cpp | 28 | ||||
| -rw-r--r-- | lldb/source/Core/ValueObjectVariable.cpp | 80 |
3 files changed, 101 insertions, 9 deletions
diff --git a/lldb/source/Core/Value.cpp b/lldb/source/Core/Value.cpp index fda84e7656c..7cae530ac7d 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<RegisterInfo *> (m_context); diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 6105a8ab31e..2692ecc8bbc 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -401,37 +401,49 @@ 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 164592d10b9..8204f11e4b9 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); +} |

