diff options
Diffstat (limited to 'lldb/source/Core')
-rw-r--r-- | lldb/source/Core/Debugger.cpp | 12 | ||||
-rw-r--r-- | lldb/source/Core/FormatClasses.cpp | 24 | ||||
-rw-r--r-- | lldb/source/Core/ValueObject.cpp | 107 | ||||
-rw-r--r-- | lldb/source/Core/ValueObjectSyntheticFilter.cpp | 170 |
4 files changed, 301 insertions, 12 deletions
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index cce768f8684..219fbfa8985 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -733,8 +733,12 @@ ScanFormatDescriptor(const char* var_name_begin, // if this is a V, print the value using the default format if (*format_name == 'V') *val_obj_display = ValueObject::eDisplayValue; + // if this is an L, print the location of the value if (*format_name == 'L') *val_obj_display = ValueObject::eDisplayLocation; + // if this is an S, print the summary after all + if (*format_name == 'S') + *val_obj_display = ValueObject::eDisplaySummary; } // a good custom format tells us to print the value using it else @@ -1761,6 +1765,12 @@ Debugger::Formatting::GetSummaryFormat(ValueObject& vobj, { return GetFormatManager().Get(vobj, entry); } +bool +Debugger::Formatting::GetSyntheticFilter(ValueObject& vobj, + lldb::SyntheticFilterSP& entry) +{ + return GetFormatManager().Get(vobj, entry); +} bool Debugger::Formatting::Categories::Get(const ConstString &category, lldb::FormatCategorySP &entry) @@ -1791,7 +1801,7 @@ Debugger::Formatting::Categories::Clear() void Debugger::Formatting::Categories::Clear(ConstString &category) { - GetFormatManager().Category(category.GetCString())->Clear(); + GetFormatManager().Category(category.GetCString())->ClearSummaries(); } void diff --git a/lldb/source/Core/FormatClasses.cpp b/lldb/source/Core/FormatClasses.cpp index 8ff237a603a..f301a7bbc3a 100644 --- a/lldb/source/Core/FormatClasses.cpp +++ b/lldb/source/Core/FormatClasses.cpp @@ -66,14 +66,15 @@ StringSummaryFormat::FormatObject(lldb::ValueObjectSP object) if (m_show_members_oneliner) { - const uint32_t num_children = object->GetNumChildren(); + ValueObjectSP synth_vobj = object->GetSyntheticValue(lldb::eUseSyntheticFilter); + const uint32_t num_children = synth_vobj->GetNumChildren(); if (num_children) { s.PutChar('('); for (uint32_t idx=0; idx<num_children; ++idx) { - lldb::ValueObjectSP child_sp(object->GetChildAtIndex(idx, true)); + lldb::ValueObjectSP child_sp(synth_vobj->GetChildAtIndex(idx, true)); if (child_sp.get()) { if (idx) @@ -137,4 +138,21 @@ ScriptSummaryFormat::GetDescription() } - +std::string +SyntheticFilter::GetDescription() +{ + StreamString sstr; + sstr.Printf("%s%s%s {\n", + m_cascades ? "" : " (not cascading)", + m_skip_pointers ? " (skip pointers)" : "", + m_skip_references ? " (skip references)" : ""); + + for (int i = 0; i < GetCount(); i++) + { + sstr.Printf(" %s\n", + GetExpressionPathAtIndex(i).c_str()); + } + + sstr.Printf("}"); + return sstr.GetString(); +} diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 5721b40f548..acc85df556f 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -26,6 +26,7 @@ #include "lldb/Core/ValueObjectDynamicValue.h" #include "lldb/Core/ValueObjectList.h" #include "lldb/Core/ValueObjectMemory.h" +#include "lldb/Core/ValueObjectSyntheticFilter.h" #include "lldb/Host/Endian.h" @@ -70,12 +71,14 @@ ValueObject::ValueObject (ValueObject &parent) : m_children (), m_synthetic_children (), m_dynamic_value (NULL), + m_synthetic_value(NULL), m_deref_valobj(NULL), m_format (eFormatDefault), m_last_format_mgr_revision(0), m_last_summary_format(), m_forced_summary_format(), m_last_value_format(), + m_last_synthetic_filter(), m_user_id_of_forced_summary(0), m_value_is_valid (false), m_value_did_change (false), @@ -85,6 +88,7 @@ ValueObject::ValueObject (ValueObject &parent) : m_is_deref_of_parent (false), m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), + m_is_expression_path_child(false), m_dump_printable_counter(0) { m_manager->ManageObject(this); @@ -110,12 +114,14 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope) : m_children (), m_synthetic_children (), m_dynamic_value (NULL), + m_synthetic_value(NULL), m_deref_valobj(NULL), m_format (eFormatDefault), m_last_format_mgr_revision(0), m_last_summary_format(), m_forced_summary_format(), m_last_value_format(), + m_last_synthetic_filter(), m_user_id_of_forced_summary(0), m_value_is_valid (false), m_value_did_change (false), @@ -125,6 +131,7 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope) : m_is_deref_of_parent (false), m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), + m_is_expression_path_child(false), m_dump_printable_counter(0) { m_manager = new ValueObjectManager(); @@ -209,14 +216,13 @@ ValueObject::UpdateFormatsIfNeeded() if (m_last_summary_format.get()) m_last_summary_format.reset((StringSummaryFormat*)NULL); if (m_last_value_format.get()) - m_last_value_format.reset((ValueFormat*)NULL); - Debugger::Formatting::ValueFormats::Get(*this, m_last_value_format); - // to find a summary we look for a direct summary, then if there is none - // we look for a regex summary. if there is none we look for a system - // summary (direct), and if also that fails, we look for a system - // regex summary + m_last_value_format.reset(/*(ValueFormat*)NULL*/); + if (m_last_synthetic_filter.get()) + m_last_synthetic_filter.reset(/*(SyntheticFilter*)NULL*/); + Debugger::Formatting::ValueFormats::Get(*this, m_last_value_format); Debugger::Formatting::GetSummaryFormat(*this, m_last_summary_format); + Debugger::Formatting::GetSyntheticFilter(*this, m_last_synthetic_filter); m_last_format_mgr_revision = Debugger::Formatting::ValueFormats::GetCurrentRevision(); @@ -1423,6 +1429,63 @@ ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_cre return synthetic_child_sp; } +// your expression path needs to have a leading . or -> +// (unless it somehow "looks like" an array, in which case it has +// a leading [ symbol). while the [ is meaningful and should be shown +// to the user, . and -> are just parser design, but by no means +// added information for the user.. strip them off +static const char* +SkipLeadingExpressionPathSeparators(const char* expression) +{ + if (!expression || !expression[0]) + return expression; + if (expression[0] == '.') + return expression+1; + if (expression[0] == '-' && expression[1] == '>') + return expression+2; + return expression; +} + +lldb::ValueObjectSP +ValueObject::GetSyntheticExpressionPathChild(const char* expression, bool can_create) +{ + ValueObjectSP synthetic_child_sp; + ConstString name_const_string(expression); + // Check if we have already created a synthetic array member in this + // valid object. If we have we will re-use it. + synthetic_child_sp = GetSyntheticChild (name_const_string); + if (!synthetic_child_sp) + { + // We haven't made a synthetic array member for expression yet, so + // lets make one and cache it for any future reference. + synthetic_child_sp = GetValueForExpressionPath(expression); + + // Cache the value if we got one back... + if (synthetic_child_sp.get()) + { + AddSyntheticChild(name_const_string, synthetic_child_sp.get()); + synthetic_child_sp->SetName(SkipLeadingExpressionPathSeparators(expression)); + synthetic_child_sp->m_is_expression_path_child = true; + } + } + return synthetic_child_sp; +} + +void +ValueObject::CalculateSyntheticValue (lldb::SyntheticValueType use_synthetic) +{ + if (use_synthetic == lldb::eNoSyntheticFilter) + return; + + UpdateFormatsIfNeeded(); + + if (m_last_synthetic_filter.get() == NULL) + return; + + m_synthetic_value = new ValueObjectSyntheticFilter(*this, m_last_synthetic_filter); + +} + void ValueObject::CalculateDynamicValue (lldb::DynamicValueType use_dynamic) { @@ -1483,6 +1546,29 @@ ValueObject::GetDynamicValue (DynamicValueType use_dynamic) return ValueObjectSP(); } +// GetDynamicValue() returns a NULL SharedPointer if the object is not dynamic +// or we do not really want a dynamic VO. this method instead returns this object +// itself when making it synthetic has no meaning. this makes it much simpler +// to replace the SyntheticValue for the ValueObject +ValueObjectSP +ValueObject::GetSyntheticValue (SyntheticValueType use_synthetic) +{ + if (use_synthetic == lldb::eNoSyntheticFilter) + return GetSP(); + + UpdateFormatsIfNeeded(); + + if (m_last_synthetic_filter.get() == NULL) + return GetSP(); + + CalculateSyntheticValue(use_synthetic); + + if (m_synthetic_value) + return m_synthetic_value->GetSP(); + else + return GetSP(); +} + bool ValueObject::GetBaseClassPath (Stream &s) { @@ -2398,6 +2484,7 @@ ValueObject::DumpValueObject bool show_location, bool use_objc, lldb::DynamicValueType use_dynamic, + bool use_synth, bool scope_already_checked, bool flat_output, uint32_t omit_summary_depth @@ -2545,7 +2632,10 @@ ValueObject::DumpValueObject if (print_children && (!entry || entry->DoesPrintChildren() || !sum_cstr)) { - const uint32_t num_children = valobj->GetNumChildren(); + ValueObjectSP synth_vobj = valobj->GetSyntheticValue(use_synth ? + lldb::eUseSyntheticFilter : + lldb::eNoSyntheticFilter); + const uint32_t num_children = synth_vobj->GetNumChildren(); if (num_children) { if (flat_output) @@ -2562,7 +2652,7 @@ ValueObject::DumpValueObject for (uint32_t idx=0; idx<num_children; ++idx) { - ValueObjectSP child_sp(valobj->GetChildAtIndex(idx, true)); + ValueObjectSP child_sp(synth_vobj->GetChildAtIndex(idx, true)); if (child_sp.get()) { DumpValueObject (s, @@ -2575,6 +2665,7 @@ ValueObject::DumpValueObject show_location, false, use_dynamic, + use_synth, true, flat_output, omit_summary_depth > 1 ? omit_summary_depth - 1 : 0); diff --git a/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/lldb/source/Core/ValueObjectSyntheticFilter.cpp new file mode 100644 index 00000000000..4756b1cea29 --- /dev/null +++ b/lldb/source/Core/ValueObjectSyntheticFilter.cpp @@ -0,0 +1,170 @@ +//===-- ValueObjectSyntheticFilter.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/ValueObjectSyntheticFilter.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/FormatClasses.h" +#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; + +ValueObjectSyntheticFilter::ValueObjectSyntheticFilter (ValueObject &parent, lldb::SyntheticFilterSP filter) : + ValueObject(parent), + m_address (), + m_type_sp(), +m_use_synthetic (lldb::eUseSyntheticFilter), + m_synth_filter(filter) +{ + SetName (parent.GetName().AsCString()); +} + +ValueObjectSyntheticFilter::~ValueObjectSyntheticFilter() +{ + m_owning_valobj_sp.reset(); +} + +lldb::clang_type_t +ValueObjectSyntheticFilter::GetClangType () +{ + if (m_type_sp) + return m_value.GetClangType(); + else + return m_parent->GetClangType(); +} + +ConstString +ValueObjectSyntheticFilter::GetTypeName() +{ + const bool success = UpdateValueIfNeeded(); + if (success && m_type_sp) + return ClangASTType::GetConstTypeName (GetClangType()); + else + return m_parent->GetTypeName(); +} + +uint32_t +ValueObjectSyntheticFilter::CalculateNumChildren() +{ + const bool success = UpdateValueIfNeeded(); + if (!success) + return 0; + if (m_synth_filter.get()) + return m_synth_filter->GetCount(); + return 0; + if (success && m_type_sp) + return ClangASTContext::GetNumChildren (GetClangAST (), GetClangType(), true); + else + return m_parent->GetNumChildren(); +} + +clang::ASTContext * +ValueObjectSyntheticFilter::GetClangAST () +{ + const bool success = UpdateValueIfNeeded(false); + if (success && m_type_sp) + return m_type_sp->GetClangAST(); + else + return m_parent->GetClangAST (); +} + +size_t +ValueObjectSyntheticFilter::GetByteSize() +{ + const bool success = UpdateValueIfNeeded(); + if (success && m_type_sp) + return m_value.GetValueByteSize(GetClangAST(), NULL); + else + return m_parent->GetByteSize(); +} + +lldb::ValueType +ValueObjectSyntheticFilter::GetValueType() const +{ + return m_parent->GetValueType(); +} + +bool +ValueObjectSyntheticFilter::UpdateValue () +{ + SetValueIsValid (false); + m_error.Clear(); + + if (!m_parent->UpdateValueIfNeeded()) + { + // our parent could not update.. as we are meaningless without a parent, just stop + if (m_error.Success() && m_parent->GetError().Fail()) + m_error = m_parent->GetError(); + return false; + } + + SetValueIsValid(true); + return true; +} + +lldb::ValueObjectSP +ValueObjectSyntheticFilter::GetChildAtIndex (uint32_t idx, bool can_create) +{ + if (!m_synth_filter.get()) + return lldb::ValueObjectSP(); + if (idx >= m_synth_filter->GetCount()) + return lldb::ValueObjectSP(); + return m_parent->GetSyntheticExpressionPathChild(m_synth_filter->GetExpressionPathAtIndex(idx).c_str(), can_create); +} + +lldb::ValueObjectSP +ValueObjectSyntheticFilter::GetChildMemberWithName (const ConstString &name, bool can_create) +{ + if (!m_synth_filter.get()) + return lldb::ValueObjectSP(); + uint32_t idx = GetIndexOfChildWithName(name); + if (idx >= m_synth_filter->GetCount()) + return lldb::ValueObjectSP(); + return m_parent->GetSyntheticExpressionPathChild(name.GetCString(), can_create); +} + +uint32_t +ValueObjectSyntheticFilter::GetIndexOfChildWithName (const ConstString &name) +{ + const char* name_cstr = name.GetCString(); + for (int i = 0; i < m_synth_filter->GetCount(); i++) + { + const char* expr_cstr = m_synth_filter->GetExpressionPathAtIndex(i).c_str(); + if (::strcmp(name_cstr, expr_cstr)) + return i; + } + return UINT32_MAX; +} + +bool +ValueObjectSyntheticFilter::IsInScope () +{ + return m_parent->IsInScope(); +} + |