summaryrefslogtreecommitdiffstats
path: root/lldb/source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Core')
-rw-r--r--lldb/source/Core/ValueObject.cpp332
-rw-r--r--lldb/source/Core/ValueObjectChild.cpp2
-rw-r--r--lldb/source/Core/ValueObjectDynamicValue.cpp254
-rw-r--r--lldb/source/Core/ValueObjectMemory.cpp196
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;
+}
+
OpenPOWER on IntegriCloud