diff options
Diffstat (limited to 'lldb/source/Core')
-rw-r--r-- | lldb/source/Core/ValueObject.cpp | 332 | ||||
-rw-r--r-- | lldb/source/Core/ValueObjectChild.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Core/ValueObjectDynamicValue.cpp | 254 | ||||
-rw-r--r-- | lldb/source/Core/ValueObjectMemory.cpp | 196 |
4 files changed, 659 insertions, 125 deletions
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index eeb3ac082d9..d95806cf192 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -22,6 +22,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectChild.h" #include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectDynamicValue.h" #include "lldb/Core/ValueObjectList.h" #include "lldb/Host/Endian.h" @@ -159,15 +160,10 @@ ValueObject::UpdateValueIfNeeded () return m_error.Success(); } -const DataExtractor & -ValueObject::GetDataExtractor () const -{ - return m_data; -} - DataExtractor & ValueObject::GetDataExtractor () { + UpdateValueIfNeeded(); return m_data; } @@ -281,17 +277,20 @@ ValueObjectSP ValueObject::GetChildAtIndex (uint32_t idx, bool can_create) { ValueObjectSP child_sp; - if (idx < GetNumChildren()) + if (UpdateValueIfNeeded()) { - // Check if we have already made the child value object? - if (can_create && m_children[idx].get() == NULL) + if (idx < GetNumChildren()) { - // No we haven't created the child at this index, so lets have our - // subclass do it and cache the result for quick future access. - m_children[idx] = CreateChildAtIndex (idx, false, 0); - } + // Check if we have already made the child value object? + if (can_create && m_children[idx].get() == NULL) + { + // No we haven't created the child at this index, so lets have our + // subclass do it and cache the result for quick future access. + m_children[idx] = CreateChildAtIndex (idx, false, 0); + } - child_sp = m_children[idx]; + child_sp = m_children[idx]; + } } return child_sp; } @@ -312,34 +311,38 @@ ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create) // when getting a child by name, it could be buried inside some base // classes (which really aren't part of the expression path), so we // need a vector of indexes that can get us down to the correct child - std::vector<uint32_t> child_indexes; - clang::ASTContext *clang_ast = GetClangAST(); - void *clang_type = GetClangType(); - bool omit_empty_base_classes = true; - const size_t num_child_indexes = ClangASTContext::GetIndexOfChildMemberWithName (clang_ast, - clang_type, - name.GetCString(), - omit_empty_base_classes, - child_indexes); ValueObjectSP child_sp; - if (num_child_indexes > 0) - { - std::vector<uint32_t>::const_iterator pos = child_indexes.begin (); - std::vector<uint32_t>::const_iterator end = child_indexes.end (); - child_sp = GetChildAtIndex(*pos, can_create); - for (++pos; pos != end; ++pos) + if (UpdateValueIfNeeded()) + { + std::vector<uint32_t> child_indexes; + clang::ASTContext *clang_ast = GetClangAST(); + void *clang_type = GetClangType(); + bool omit_empty_base_classes = true; + const size_t num_child_indexes = ClangASTContext::GetIndexOfChildMemberWithName (clang_ast, + clang_type, + name.GetCString(), + omit_empty_base_classes, + child_indexes); + if (num_child_indexes > 0) { - if (child_sp) - { - ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create)); - child_sp = new_child_sp; - } - else + std::vector<uint32_t>::const_iterator pos = child_indexes.begin (); + std::vector<uint32_t>::const_iterator end = child_indexes.end (); + + child_sp = GetChildAtIndex(*pos, can_create); + for (++pos; pos != end; ++pos) { - child_sp.reset(); - } + if (child_sp) + { + ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create)); + child_sp = new_child_sp; + } + else + { + child_sp.reset(); + } + } } } return child_sp; @@ -378,55 +381,60 @@ ValueObjectSP ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index) { ValueObjectSP valobj_sp; - bool omit_empty_base_classes = true; - - std::string child_name_str; - uint32_t child_byte_size = 0; - int32_t child_byte_offset = 0; - uint32_t child_bitfield_bit_size = 0; - uint32_t child_bitfield_bit_offset = 0; - bool child_is_base_class = false; - bool child_is_deref_of_parent = false; - - const bool transparent_pointers = synthetic_array_member == false; - clang::ASTContext *clang_ast = GetClangAST(); - clang_type_t clang_type = GetClangType(); - clang_type_t child_clang_type; - child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (clang_ast, - GetName().GetCString(), - clang_type, - idx, - transparent_pointers, - omit_empty_base_classes, - child_name_str, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent); - if (child_clang_type && child_byte_size) + + if (UpdateValueIfNeeded()) { - if (synthetic_index) - child_byte_offset += child_byte_size * synthetic_index; - - ConstString child_name; - if (!child_name_str.empty()) - child_name.SetCString (child_name_str.c_str()); - - valobj_sp.reset (new ValueObjectChild (*this, - clang_ast, - child_clang_type, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent)); - if (m_pointers_point_to_load_addrs) - valobj_sp->SetPointersPointToLoadAddrs (m_pointers_point_to_load_addrs); + bool omit_empty_base_classes = true; + + std::string child_name_str; + uint32_t child_byte_size = 0; + int32_t child_byte_offset = 0; + uint32_t child_bitfield_bit_size = 0; + uint32_t child_bitfield_bit_offset = 0; + bool child_is_base_class = false; + bool child_is_deref_of_parent = false; + + const bool transparent_pointers = synthetic_array_member == false; + clang::ASTContext *clang_ast = GetClangAST(); + clang_type_t clang_type = GetClangType(); + clang_type_t child_clang_type; + child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (clang_ast, + GetName().GetCString(), + clang_type, + idx, + transparent_pointers, + omit_empty_base_classes, + child_name_str, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent); + if (child_clang_type && child_byte_size) + { + if (synthetic_index) + child_byte_offset += child_byte_size * synthetic_index; + + ConstString child_name; + if (!child_name_str.empty()) + child_name.SetCString (child_name_str.c_str()); + + valobj_sp.reset (new ValueObjectChild (*this, + clang_ast, + child_clang_type, + child_name, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent)); + if (m_pointers_point_to_load_addrs) + valobj_sp->SetPointersPointToLoadAddrs (m_pointers_point_to_load_addrs); + } } + return valobj_sp; } @@ -710,6 +718,9 @@ ValueObject::GetValueAsCString () addr_t ValueObject::GetAddressOf (AddressType &address_type, bool scalar_is_load_address) { + if (!UpdateValueIfNeeded()) + return LLDB_INVALID_ADDRESS; + switch (m_value.GetValueType()) { case Value::eValueTypeScalar: @@ -738,6 +749,10 @@ ValueObject::GetPointerValue (AddressType &address_type, bool scalar_is_load_add { lldb::addr_t address = LLDB_INVALID_ADDRESS; address_type = eAddressTypeInvalid; + + if (!UpdateValueIfNeeded()) + return address; + switch (m_value.GetValueType()) { case Value::eValueTypeScalar: @@ -957,16 +972,66 @@ ValueObject::GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create) return synthetic_child_sp; } -bool -ValueObject::SetDynamicValue () +void +ValueObject::CalculateDynamicValue () { - if (!IsPointerOrReferenceType()) - return false; + if (!m_dynamic_value_sp && !IsDynamic()) + { + Process *process = m_update_point.GetProcess(); + bool worth_having_dynamic_value = false; - // Check that the runtime class is correct for determining the most specific class. - // If it is a C++ class, see if it is dynamic: - - return true; + + // FIXME: Process should have some kind of "map over Runtimes" so we don't have to + // hard code this everywhere. + lldb::LanguageType known_type = GetObjectRuntimeLanguage(); + if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC) + { + LanguageRuntime *runtime = process->GetLanguageRuntime (known_type); + if (runtime) + worth_having_dynamic_value = runtime->CouldHaveDynamicValue(*this); + } + else + { + LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus); + if (cpp_runtime) + worth_having_dynamic_value = cpp_runtime->CouldHaveDynamicValue(*this); + + if (!worth_having_dynamic_value) + { + LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC); + if (objc_runtime) + worth_having_dynamic_value = cpp_runtime->CouldHaveDynamicValue(*this); + } + } + + if (worth_having_dynamic_value) + m_dynamic_value_sp.reset (new ValueObjectDynamicValue (*this)); + } +} + +lldb::ValueObjectSP +ValueObject::GetDynamicValue (bool can_create) +{ + if (!IsDynamic() && m_dynamic_value_sp == NULL && can_create) + { + CalculateDynamicValue(); + } + return m_dynamic_value_sp; +} + +lldb::ValueObjectSP +ValueObject::GetDynamicValue (bool can_create, lldb::ValueObjectSP &owning_valobj_sp) +{ + if (!IsDynamic() && m_dynamic_value_sp == NULL && can_create) + { + CalculateDynamicValue(); + if (m_dynamic_value_sp) + { + ValueObjectDynamicValue *as_dynamic_value = static_cast<ValueObjectDynamicValue *>(m_dynamic_value_sp.get()); + as_dynamic_value->SetOwningSP (owning_valobj_sp); + } + } + return m_dynamic_value_sp; } bool @@ -974,7 +1039,7 @@ ValueObject::GetBaseClassPath (Stream &s) { if (IsBaseClass()) { - bool parent_had_base_class = m_parent && m_parent->GetBaseClassPath (s); + bool parent_had_base_class = GetParent() && GetParent()->GetBaseClassPath (s); clang_type_t clang_type = GetClangType(); std::string cxx_class_name; bool this_had_base_class = ClangASTContext::GetCXXClassName (clang_type, cxx_class_name); @@ -993,12 +1058,12 @@ ValueObject::GetBaseClassPath (Stream &s) ValueObject * ValueObject::GetNonBaseClassParent() { - if (m_parent) + if (GetParent()) { - if (m_parent->IsBaseClass()) - return m_parent->GetNonBaseClassParent(); + if (GetParent()->IsBaseClass()) + return GetParent()->GetNonBaseClassParent(); else - return m_parent; + return GetParent(); } return NULL; } @@ -1011,8 +1076,8 @@ ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes) if (is_deref_of_parent) s.PutCString("*("); - if (m_parent) - m_parent->GetExpressionPath (s, qualify_cxx_base_classes); + if (GetParent()) + GetParent()->GetExpressionPath (s, qualify_cxx_base_classes); if (!IsBaseClass()) { @@ -1067,12 +1132,20 @@ ValueObject::DumpValueObject bool show_types, bool show_location, bool use_objc, + bool use_dynamic, bool scope_already_checked, bool flat_output ) { if (valobj && valobj->UpdateValueIfNeeded ()) { + if (use_dynamic) + { + ValueObject *dynamic_value = valobj->GetDynamicValue(true).get(); + if (dynamic_value) + valobj = dynamic_value; + } + clang_type_t clang_type = valobj->GetClangType(); const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type, NULL, NULL)); @@ -1216,6 +1289,7 @@ ValueObject::DumpValueObject show_types, show_location, false, + use_dynamic, true, flat_output); } @@ -1296,7 +1370,9 @@ ValueObject::CreateConstantValue (const ConstString &name) lldb::ValueObjectSP ValueObject::Dereference (Error &error) { - lldb::ValueObjectSP valobj_sp; + if (m_deref_valobj_sp) + return m_deref_valobj_sp; + const bool is_pointer_type = IsPointerType(); if (is_pointer_type) { @@ -1332,20 +1408,20 @@ ValueObject::Dereference (Error &error) if (!child_name_str.empty()) child_name.SetCString (child_name_str.c_str()); - valobj_sp.reset (new ValueObjectChild (*this, - clang_ast, - child_clang_type, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent)); + m_deref_valobj_sp.reset (new ValueObjectChild (*this, + clang_ast, + child_clang_type, + child_name, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent)); } } - if (valobj_sp) + if (m_deref_valobj_sp) { error.Clear(); } @@ -1360,13 +1436,15 @@ ValueObject::Dereference (Error &error) error.SetErrorStringWithFormat("not a pointer type: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str()); } - return valobj_sp; + return m_deref_valobj_sp; } - lldb::ValueObjectSP +lldb::ValueObjectSP ValueObject::AddressOf (Error &error) { - lldb::ValueObjectSP valobj_sp; + if (m_addr_of_valobj_sp) + return m_addr_of_valobj_sp; + AddressType address_type = eAddressTypeInvalid; const bool scalar_is_load_address = false; lldb::addr_t addr = GetAddressOf (address_type, scalar_is_load_address); @@ -1394,19 +1472,19 @@ ValueObject::AddressOf (Error &error) { std::string name (1, '&'); name.append (m_name.AsCString("")); - valobj_sp.reset (new ValueObjectConstResult (GetExecutionContextScope(), - ast, - ClangASTContext::CreatePointerType (ast, clang_type), - ConstString (name.c_str()), - addr, - eAddressTypeInvalid, - m_data.GetAddressByteSize())); + m_addr_of_valobj_sp.reset (new ValueObjectConstResult (GetExecutionContextScope(), + ast, + ClangASTContext::CreatePointerType (ast, clang_type), + ConstString (name.c_str()), + addr, + eAddressTypeInvalid, + m_data.GetAddressByteSize())); } } break; } } - return valobj_sp; + return m_addr_of_valobj_sp; } ValueObject::EvaluationPoint::EvaluationPoint () : @@ -1523,10 +1601,16 @@ ValueObject::EvaluationPoint::SyncWithProcessState() return false; // If our stop id is the current stop ID, nothing has changed: - if (m_stop_id == m_process_sp->GetStopID()) + uint32_t cur_stop_id = m_process_sp->GetStopID(); + if (m_stop_id == cur_stop_id) return false; - m_stop_id = m_process_sp->GetStopID(); + // If the current stop id is 0, either we haven't run yet, or the process state has been cleared. + // In either case, we aren't going to be able to sync with the process state. + if (cur_stop_id == 0) + return false; + + m_stop_id = cur_stop_id; m_needs_update = true; m_exe_scope = m_process_sp.get(); diff --git a/lldb/source/Core/ValueObjectChild.cpp b/lldb/source/Core/ValueObjectChild.cpp index fc5f6c850f5..509852f4b3a 100644 --- a/lldb/source/Core/ValueObjectChild.cpp +++ b/lldb/source/Core/ValueObjectChild.cpp @@ -97,7 +97,7 @@ ValueObjectChild::UpdateValue () ValueObject* parent = m_parent; if (parent) { - if (parent->UpdateValue()) + if (parent->UpdateValueIfNeeded()) { m_value.SetContext(Value::eContextTypeClangType, m_clang_type); diff --git a/lldb/source/Core/ValueObjectDynamicValue.cpp b/lldb/source/Core/ValueObjectDynamicValue.cpp new file mode 100644 index 00000000000..2b80ae513e3 --- /dev/null +++ b/lldb/source/Core/ValueObjectDynamicValue.cpp @@ -0,0 +1,254 @@ +//===-- ValueObjectDynamicValue.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#include "lldb/Core/ValueObjectDynamicValue.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Module.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObject.h" + +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/Variable.h" + +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/LanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" + + +using namespace lldb_private; + +ValueObjectDynamicValue::ValueObjectDynamicValue (ValueObject &parent) : + ValueObject(parent), + m_address (), + m_type_sp() +{ + // THINK ABOUT: It looks ugly to doctor up the name like this. But if + // people find it confusing to tell the difference, we may want to do something... + +// std::string dynamic_name ("<dynamic value for \""); +// dynamic_name.append(parent.GetName().AsCString()); +// dynamic_name.append("\">"); +// +// SetName (dynamic_name.c_str()); + SetName (parent.GetName().AsCString()); +} + +ValueObjectDynamicValue::~ValueObjectDynamicValue() +{ + m_owning_valobj_sp.reset(); +} + +lldb::clang_type_t +ValueObjectDynamicValue::GetClangType () +{ + if (m_type_sp) + return m_value.GetClangType(); + else + return m_parent->GetClangType(); +} + +ConstString +ValueObjectDynamicValue::GetTypeName() +{ + // FIXME: Maybe cache the name, but have to clear it out if the type changes... + if (!UpdateValueIfNeeded()) + return ConstString("<unknown type>"); + + if (m_type_sp) + return ClangASTType::GetClangTypeName (GetClangType()); + else + return m_parent->GetTypeName(); +} + +uint32_t +ValueObjectDynamicValue::CalculateNumChildren() +{ + if (!UpdateValueIfNeeded()) + return 0; + + if (m_type_sp) + return ClangASTContext::GetNumChildren (GetClangAST (), GetClangType(), true); + else + return m_parent->GetNumChildren(); +} + +clang::ASTContext * +ValueObjectDynamicValue::GetClangAST () +{ + if (!UpdateValueIfNeeded()) + return NULL; + + if (m_type_sp) + return m_type_sp->GetClangAST(); + else + return m_parent->GetClangAST (); +} + +size_t +ValueObjectDynamicValue::GetByteSize() +{ + if (!UpdateValueIfNeeded()) + return 0; + + if (m_type_sp) + return m_value.GetValueByteSize(GetClangAST(), NULL); + else + return m_parent->GetByteSize(); +} + +lldb::ValueType +ValueObjectDynamicValue::GetValueType() const +{ + return m_parent->GetValueType(); +} + +bool +ValueObjectDynamicValue::UpdateValue () +{ + SetValueIsValid (false); + m_error.Clear(); + + if (!m_parent->UpdateValueIfNeeded()) + { + return false; + } + + ExecutionContext exe_ctx (GetExecutionContextScope()); + + if (exe_ctx.target) + { + m_data.SetByteOrder(exe_ctx.target->GetArchitecture().GetByteOrder()); + m_data.SetAddressByteSize(exe_ctx.target->GetArchitecture().GetAddressByteSize()); + } + + // First make sure our Type and/or Address haven't changed: + Process *process = m_update_point.GetProcess(); + if (!process) + return false; + + lldb::TypeSP dynamic_type_sp; + Address dynamic_address; + bool found_dynamic_type = false; + + lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage(); + if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC) + { + LanguageRuntime *runtime = process->GetLanguageRuntime (known_type); + if (runtime) + found_dynamic_type = runtime->GetDynamicValue(*m_parent, dynamic_type_sp, dynamic_address); + } + else + { + LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus); + if (cpp_runtime) + found_dynamic_type = cpp_runtime->GetDynamicValue(*m_parent, dynamic_type_sp, dynamic_address); + + if (!found_dynamic_type) + { + LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC); + if (objc_runtime) + found_dynamic_type = cpp_runtime->GetDynamicValue(*m_parent, dynamic_type_sp, dynamic_address); + } + } + + // If we don't have a dynamic type, then make ourselves just a echo of our parent. + // Or we could return false, and make ourselves an echo of our parent? + if (!found_dynamic_type) + { + if (m_type_sp) + SetValueDidChange(true); + m_value = m_parent->GetValue(); + m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0); + return m_error.Success(); + } + + Value old_value(m_value); + + if (!m_type_sp) + { + m_type_sp = dynamic_type_sp; + } + else if (dynamic_type_sp != m_type_sp) + { + // We are another type, we need to tear down our children... + m_type_sp = dynamic_type_sp; + SetValueDidChange (true); + } + + if (!m_address.IsValid() || m_address != dynamic_address) + { + if (m_address.IsValid()) + SetValueDidChange (true); + + // We've moved, so we should be fine... + m_address = dynamic_address; + lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTarget()); + m_value.GetScalar() = load_address; + } + + // The type will always be the type of the dynamic object. If our parent's type was a pointer, + // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type + // should be okay... + lldb::clang_type_t orig_type = m_type_sp->GetClangForwardType(); + lldb::clang_type_t corrected_type = orig_type; + if (m_parent->IsPointerType()) + corrected_type = ClangASTContext::CreatePointerType (m_type_sp->GetClangAST(), orig_type); + else if (m_parent->IsPointerOrReferenceType()) + corrected_type = ClangASTContext::CreateLValueReferenceType (m_type_sp->GetClangAST(), orig_type); + + m_value.SetContext (Value::eContextTypeClangType, corrected_type); + + // Our address is the location of the dynamic type stored in memory. It isn't a load address, + // because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us... + m_value.SetValueType(Value::eValueTypeScalar); + + if (m_address.IsValid() && m_type_sp) + { + // The variable value is in the Scalar value inside the m_value. + // We can point our m_data right to it. + m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0); + if (m_error.Success()) + { + if (ClangASTContext::IsAggregateType (GetClangType())) + { + // this value object represents an aggregate type whose + // children have values, but this object does not. So we + // say we are changed if our location has changed. + SetValueDidChange (m_value.GetValueType() != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); + } + + SetValueIsValid (true); + return true; + } + } + + // We get here if we've failed above... + SetValueIsValid (false); + return false; +} + + + +bool +ValueObjectDynamicValue::IsInScope () +{ + return m_parent->IsInScope(); +} + diff --git a/lldb/source/Core/ValueObjectMemory.cpp b/lldb/source/Core/ValueObjectMemory.cpp new file mode 100644 index 00000000000..d3998488eba --- /dev/null +++ b/lldb/source/Core/ValueObjectMemory.cpp @@ -0,0 +1,196 @@ +//===-- ValueObjectMemory.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#include "lldb/Core/ValueObjectMemory.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Module.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObject.h" + +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/Variable.h" + +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" + + +using namespace lldb_private; + +ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope, + const char *name, + const Address &address, + lldb::TypeSP &type_sp) : + ValueObject(exe_scope), + m_address (address), + m_type_sp(type_sp) +{ + // Do not attempt to construct one of these objects with no variable! + assert (m_type_sp.get() != NULL); + SetName (name); + m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); + lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTarget()); + if (load_address != LLDB_INVALID_ADDRESS) + { + m_value.SetValueType(Value::eValueTypeLoadAddress); + m_value.GetScalar() = load_address; + } + else + { + lldb::addr_t file_address = m_address.GetFileAddress(); + if (file_address != LLDB_INVALID_ADDRESS) + { + m_value.SetValueType(Value::eValueTypeFileAddress); + m_value.GetScalar() = file_address; + } + else + { + m_value.GetScalar() = m_address.GetOffset(); + m_value.SetValueType (Value::eValueTypeScalar); + } + } +} + +ValueObjectMemory::~ValueObjectMemory() +{ +} + +lldb::clang_type_t +ValueObjectMemory::GetClangType () +{ + return m_type_sp->GetClangForwardType(); +} + +ConstString +ValueObjectMemory::GetTypeName() +{ + return m_type_sp->GetName(); +} + +uint32_t +ValueObjectMemory::CalculateNumChildren() +{ + return m_type_sp->GetNumChildren(true); +} + +clang::ASTContext * +ValueObjectMemory::GetClangAST () +{ + return m_type_sp->GetClangAST(); +} + +size_t +ValueObjectMemory::GetByteSize() +{ + return m_type_sp->GetByteSize(); +} + +lldb::ValueType +ValueObjectMemory::GetValueType() const +{ + // RETHINK: Should this be inherited from somewhere? + return lldb::eValueTypeVariableGlobal; +} + +bool +ValueObjectMemory::UpdateValue () +{ + SetValueIsValid (false); + m_error.Clear(); + + ExecutionContext exe_ctx (GetExecutionContextScope()); + + if (exe_ctx.target) + { + m_data.SetByteOrder(exe_ctx.target->GetArchitecture().GetByteOrder()); + m_data.SetAddressByteSize(exe_ctx.target->GetArchitecture().GetAddressByteSize()); + } + + Value old_value(m_value); + if (m_address.IsValid()) + { + Value::ValueType value_type = m_value.GetValueType(); + + switch (value_type) + { + default: + assert(!"Unhandled expression result value kind..."); + break; + + case Value::eValueTypeScalar: + // The variable value is in the Scalar value inside the m_value. + // We can point our m_data right to it. + m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0); + break; + + case Value::eValueTypeFileAddress: + case Value::eValueTypeLoadAddress: + case Value::eValueTypeHostAddress: + // The DWARF expression result was an address in the inferior + // process. If this variable is an aggregate type, we just need + // the address as the main value as all child variable objects + // will rely upon this location and add an offset and then read + // their own values as needed. If this variable is a simple + // type, we read all data for it into m_data. + // Make sure this type has a value before we try and read it + + // If we have a file address, convert it to a load address if we can. + if (value_type == Value::eValueTypeFileAddress && exe_ctx.process) + { + lldb::addr_t load_addr = m_address.GetLoadAddress(exe_ctx.target); + if (load_addr != LLDB_INVALID_ADDRESS) + { + m_value.SetValueType(Value::eValueTypeLoadAddress); + m_value.GetScalar() = load_addr; + } + } + + if (ClangASTContext::IsAggregateType (GetClangType())) + { + // this value object represents an aggregate type whose + // children have values, but this object does not. So we + // say we are changed if our location has changed. + SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); + } + else + { + // Copy the Value and set the context to use our Variable + // so it can extract read its value into m_data appropriately + Value value(m_value); + value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); + m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0); + } + break; + } + + SetValueIsValid (m_error.Success()); + } + return m_error.Success(); +} + + + +bool +ValueObjectMemory::IsInScope () +{ + // FIXME: Maybe try to read the memory address, and if that works, then + // we are in scope? + return true; +} + |