summaryrefslogtreecommitdiffstats
path: root/lldb/source/Core/ValueObject.cpp
diff options
context:
space:
mode:
authorJim Ingham <jingham@apple.com>2011-04-16 00:01:13 +0000
committerJim Ingham <jingham@apple.com>2011-04-16 00:01:13 +0000
commit78a685aa2d8bbf48f25f2f93d4c0a74652eb0e9b (patch)
treebccc15a9b0e04bef29c0d2ceeb85a3c355dc9586 /lldb/source/Core/ValueObject.cpp
parentf46b33852c0294f1dba3303c6810902212fe749d (diff)
downloadbcm5719-llvm-78a685aa2d8bbf48f25f2f93d4c0a74652eb0e9b.tar.gz
bcm5719-llvm-78a685aa2d8bbf48f25f2f93d4c0a74652eb0e9b.zip
Add support for "dynamic values" for C++ classes. This currently only works for "frame var" and for the
expressions that are simple enough to get passed to the "frame var" underpinnings. The parser code will have to be changed to also query for the dynamic types & offsets as it is looking up variables. The behavior of "frame var" is controlled in two ways. You can pass "-d {true/false} to the frame var command to get the dynamic or static value of the variables you are printing. There's also a general setting: target.prefer-dynamic-value (boolean) = 'true' which is consulted if you call "frame var" without supplying a value for the -d option. llvm-svn: 129623
Diffstat (limited to 'lldb/source/Core/ValueObject.cpp')
-rw-r--r--lldb/source/Core/ValueObject.cpp332
1 files changed, 208 insertions, 124 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();
OpenPOWER on IntegriCloud