diff options
Diffstat (limited to 'source/Core/ValueObject.cpp')
-rw-r--r-- | source/Core/ValueObject.cpp | 442 |
1 files changed, 130 insertions, 312 deletions
diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp index a30cc1306c6b..d39d21a2a0bf 100644 --- a/source/Core/ValueObject.cpp +++ b/source/Core/ValueObject.cpp @@ -34,6 +34,7 @@ #include "lldb/Core/ValueObjectSyntheticFilter.h" #include "lldb/DataFormatters/DataVisualization.h" +#include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Host/Endian.h" @@ -170,13 +171,12 @@ ValueObject::UpdateValueIfNeeded (bool update_format) // we have an error or not if (GetIsConstant()) { - // if you were asked to update your formatters, but did not get a chance to do it - // clear your own values (this serves the purpose of faking a stop-id for frozen - // objects (which are regarded as constant, but could have changes behind their backs - // because of the frozen-pointer depth limit) - // TODO: decouple summary from value and then remove this code and only force-clear the summary + // if you are constant, things might still have changed behind your back + // (e.g. you are a frozen object and things have changed deeper than you cared to freeze-dry yourself) + // in this case, your value has not changed, but "computed" entries might have, so you might now have + // a different summary, or a different object description. clear these so we will recompute them if (update_format && !did_change_formats) - ClearUserVisibleData(eClearUserVisibleDataItemsSummary); + ClearUserVisibleData(eClearUserVisibleDataItemsSummary | eClearUserVisibleDataItemsDescription); return m_error.Success(); } @@ -245,7 +245,7 @@ ValueObject::UpdateFormatsIfNeeded() if ( (m_last_format_mgr_revision != DataVisualization::GetCurrentRevision())) { - SetValueFormat(DataVisualization::ValueFormats::GetFormat (*this, eNoDynamicValues)); + SetValueFormat(DataVisualization::GetFormat (*this, eNoDynamicValues)); SetSummaryFormat(DataVisualization::GetSummaryFormat (*this, GetDynamicValueType())); #ifndef LLDB_DISABLE_PYTHON SetSyntheticChildren(DataVisualization::GetSyntheticChildren (*this, GetDynamicValueType())); @@ -272,6 +272,7 @@ ValueObject::SetNeedsUpdate () void ValueObject::ClearDynamicTypeInformation () { + m_children_count_valid = false; m_did_calculate_complete_objc_class_type = false; m_last_format_mgr_revision = 0; m_override_type = ClangASTType(); @@ -359,6 +360,12 @@ ValueObject::GetClangType () return MaybeCalculateCompleteType(); } +TypeImpl +ValueObject::GetTypeImpl () +{ + return TypeImpl(GetClangType()); +} + DataExtractor & ValueObject::GetDataExtractor () { @@ -595,6 +602,86 @@ ValueObject::GetChildAtIndexPath (const std::vector< std::pair<size_t, bool> > & return root; } +lldb::ValueObjectSP +ValueObject::GetChildAtNamePath (const std::initializer_list<ConstString> &names, + ConstString* name_of_error) +{ + if (names.size() == 0) + return GetSP(); + ValueObjectSP root(GetSP()); + for (ConstString name : names) + { + root = root->GetChildMemberWithName(name, true); + if (!root) + { + if (name_of_error) + *name_of_error = name; + return root; + } + } + return root; +} + +lldb::ValueObjectSP +ValueObject::GetChildAtNamePath (const std::vector<ConstString> &names, + ConstString* name_of_error) +{ + if (names.size() == 0) + return GetSP(); + ValueObjectSP root(GetSP()); + for (ConstString name : names) + { + root = root->GetChildMemberWithName(name, true); + if (!root) + { + if (name_of_error) + *name_of_error = name; + return root; + } + } + return root; +} + +lldb::ValueObjectSP +ValueObject::GetChildAtNamePath (const std::initializer_list< std::pair<ConstString, bool> > &names, + ConstString* name_of_error) +{ + if (names.size() == 0) + return GetSP(); + ValueObjectSP root(GetSP()); + for (std::pair<ConstString, bool> name : names) + { + root = root->GetChildMemberWithName(name.first, name.second); + if (!root) + { + if (name_of_error) + *name_of_error = name.first; + return root; + } + } + return root; +} + +lldb::ValueObjectSP +ValueObject::GetChildAtNamePath (const std::vector< std::pair<ConstString, bool> > &names, + ConstString* name_of_error) +{ + if (names.size() == 0) + return GetSP(); + ValueObjectSP root(GetSP()); + for (std::pair<ConstString, bool> name : names) + { + root = root->GetChildMemberWithName(name.first, name.second); + if (!root) + { + if (name_of_error) + *name_of_error = name.first; + return root; + } + } + return root; +} + size_t ValueObject::GetIndexOfChildWithName (const ConstString &name) { @@ -943,7 +1030,7 @@ ValueObject::GetPointeeData (DataExtractor& data, { heap_buf_ptr->SetByteSize(bytes); size_t bytes_read = process->ReadMemory(addr + offset, heap_buf_ptr->GetBytes(), bytes, error); - if (error.Success()) + if (error.Success() || bytes_read > 0) { data.SetData(data_sp); return bytes_read; @@ -1455,6 +1542,27 @@ ValueObject::GetValueAsUnsigned (uint64_t fail_value, bool *success) return fail_value; } +int64_t +ValueObject::GetValueAsSigned (int64_t fail_value, bool *success) +{ + // If our byte size is zero this is an aggregate type that has children + if (!GetClangType().IsAggregateType()) + { + Scalar scalar; + if (ResolveValue (scalar)) + { + if (success) + *success = true; + return scalar.SLongLong(fail_value); + } + // fallthrough, otherwise... + } + + if (success) + *success = false; + return fail_value; +} + // if any more "special cases" are added to ValueObject::DumpPrintableRepresentation() please keep // this call up to date by returning true for your new special cases. We will eventually move // to checking this call result before trying to display special cases @@ -2211,7 +2319,7 @@ ValueObject::CalculateSyntheticValue (bool use_synthetic) return; TargetSP target_sp(GetTargetSP()); - if (target_sp && (target_sp->GetEnableSyntheticValue() == false || target_sp->GetSuppressSyntheticValue() == true)) + if (target_sp && target_sp->GetEnableSyntheticValue() == false) { m_synthetic_value = NULL; return; @@ -3342,329 +3450,39 @@ ValueObject::ExpandArraySliceExpression(const char* expression_cstr, } } -static void -DumpValueObject_Impl (Stream &s, - ValueObject *valobj, - const ValueObject::DumpValueObjectOptions& options, - uint32_t ptr_depth, - uint32_t curr_depth) -{ - if (valobj) - { - bool update_success = valobj->UpdateValueIfNeeded (true); - - const char *root_valobj_name = - options.m_root_valobj_name.empty() ? - valobj->GetName().AsCString() : - options.m_root_valobj_name.c_str(); - - if (update_success && options.m_use_dynamic != eNoDynamicValues) - { - ValueObject *dynamic_value = valobj->GetDynamicValue(options.m_use_dynamic).get(); - if (dynamic_value) - valobj = dynamic_value; - } - - ClangASTType clang_type = valobj->GetClangType(); - const Flags type_flags (clang_type.GetTypeInfo ()); - const char *err_cstr = NULL; - const bool has_children = type_flags.Test (ClangASTType::eTypeHasChildren); - const bool has_value = type_flags.Test (ClangASTType::eTypeHasValue); - - const bool print_valobj = options.m_flat_output == false || has_value; - - if (print_valobj) - { - if (options.m_show_location) - { - s.Printf("%s: ", valobj->GetLocationAsCString()); - } - - s.Indent(); - - bool show_type = true; - // if we are at the root-level and been asked to hide the root's type, then hide it - if (curr_depth == 0 && options.m_hide_root_type) - show_type = false; - else - // otherwise decide according to the usual rules (asked to show types - always at the root level) - show_type = options.m_show_types || (curr_depth == 0 && !options.m_flat_output); - - if (show_type) - { - // Some ValueObjects don't have types (like registers sets). Only print - // the type if there is one to print - ConstString qualified_type_name(valobj->GetQualifiedTypeName()); - if (qualified_type_name) - s.Printf("(%s) ", qualified_type_name.GetCString()); - } - - if (options.m_flat_output) - { - // If we are showing types, also qualify the C++ base classes - const bool qualify_cxx_base_classes = options.m_show_types; - if (!options.m_hide_name) - { - valobj->GetExpressionPath(s, qualify_cxx_base_classes); - s.PutCString(" ="); - } - } - else if (!options.m_hide_name) - { - const char *name_cstr = root_valobj_name ? root_valobj_name : valobj->GetName().AsCString(""); - s.Printf ("%s =", name_cstr); - } - - if (!options.m_scope_already_checked && !valobj->IsInScope()) - { - err_cstr = "out of scope"; - } - } - - std::string summary_str; - std::string value_str; - const char *val_cstr = NULL; - const char *sum_cstr = NULL; - TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : valobj->GetSummaryFormat().get(); - - if (options.m_omit_summary_depth > 0) - entry = NULL; - - bool is_nil = valobj->IsObjCNil(); - - if (err_cstr == NULL) - { - if (options.m_format != eFormatDefault && options.m_format != valobj->GetFormat()) - { - valobj->GetValueAsCString(options.m_format, - value_str); - } - else - { - val_cstr = valobj->GetValueAsCString(); - if (val_cstr) - value_str = val_cstr; - } - err_cstr = valobj->GetError().AsCString(); - } - - if (err_cstr) - { - s.Printf (" <%s>\n", err_cstr); - } - else - { - const bool is_ref = type_flags.Test (ClangASTType::eTypeIsReference); - if (print_valobj) - { - if (is_nil) - sum_cstr = "nil"; - else if (options.m_omit_summary_depth == 0) - { - if (options.m_summary_sp) - { - valobj->GetSummaryAsCString(entry, summary_str); - sum_cstr = summary_str.c_str(); - } - else - sum_cstr = valobj->GetSummaryAsCString(); - } - - // Make sure we have a value and make sure the summary didn't - // specify that the value should not be printed - and do not print - // the value if this thing is nil - // (but show the value if the user passes a format explicitly) - if (!is_nil && !value_str.empty() && (entry == NULL || (entry->DoesPrintValue() || options.m_format != eFormatDefault) || sum_cstr == NULL) && !options.m_hide_value) - s.Printf(" %s", value_str.c_str()); - - if (sum_cstr) - s.Printf(" %s", sum_cstr); - - // let's avoid the overly verbose no description error for a nil thing - if (options.m_use_objc && !is_nil) - { - if (!options.m_hide_value || !options.m_hide_name) - s.Printf(" "); - const char *object_desc = valobj->GetObjectDescription(); - if (object_desc) - s.Printf("%s\n", object_desc); - else - s.Printf ("[no Objective-C description available]\n"); - return; - } - } - - if (curr_depth < options.m_max_depth) - { - // We will show children for all concrete types. We won't show - // pointer contents unless a pointer depth has been specified. - // We won't reference contents unless the reference is the - // root object (depth of zero). - bool print_children = true; - - // Use a new temporary pointer depth in case we override the - // current pointer depth below... - uint32_t curr_ptr_depth = ptr_depth; - - const bool is_ptr = type_flags.Test (ClangASTType::eTypeIsPointer); - if (is_ptr || is_ref) - { - // We have a pointer or reference whose value is an address. - // Make sure that address is not NULL - AddressType ptr_address_type; - if (valobj->GetPointerValue (&ptr_address_type) == 0) - print_children = false; - - else if (is_ref && curr_depth == 0) - { - // If this is the root object (depth is zero) that we are showing - // and it is a reference, and no pointer depth has been supplied - // print out what it references. Don't do this at deeper depths - // otherwise we can end up with infinite recursion... - curr_ptr_depth = 1; - } - - if (curr_ptr_depth == 0) - print_children = false; - } - - if (print_children && (!entry || entry->DoesPrintChildren() || !sum_cstr)) - { - ValueObjectSP synth_valobj_sp = valobj->GetSyntheticValue (options.m_use_synthetic); - ValueObject* synth_valobj = (synth_valobj_sp ? synth_valobj_sp.get() : valobj); - - size_t num_children = synth_valobj->GetNumChildren(); - bool print_dotdotdot = false; - if (num_children) - { - if (options.m_flat_output) - { - if (print_valobj) - s.EOL(); - } - else - { - if (print_valobj) - s.PutCString(is_ref ? ": {\n" : " {\n"); - s.IndentMore(); - } - - const size_t max_num_children = valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); - - if (num_children > max_num_children && !options.m_ignore_cap) - { - num_children = max_num_children; - print_dotdotdot = true; - } - - ValueObject::DumpValueObjectOptions child_options(options); - child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName(); - child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value) - .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0); - for (size_t idx=0; idx<num_children; ++idx) - { - ValueObjectSP child_sp(synth_valobj->GetChildAtIndex(idx, true)); - if (child_sp.get()) - { - DumpValueObject_Impl (s, - child_sp.get(), - child_options, - (is_ptr || is_ref) ? curr_ptr_depth - 1 : curr_ptr_depth, - curr_depth + 1); - } - } - - if (!options.m_flat_output) - { - if (print_dotdotdot) - { - ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); - Target *target = exe_ctx.GetTargetPtr(); - if (target) - target->GetDebugger().GetCommandInterpreter().ChildrenTruncated(); - s.Indent("...\n"); - } - s.IndentLess(); - s.Indent("}\n"); - } - } - else if (has_children) - { - // Aggregate, no children... - if (print_valobj) - s.PutCString(" {}\n"); - } - else - { - if (print_valobj) - s.EOL(); - } - - } - else - { - s.EOL(); - } - } - else - { - if (has_children && print_valobj) - { - s.PutCString("{...}\n"); - } - } - } - } -} - void -ValueObject::LogValueObject (Log *log, - ValueObject *valobj) +ValueObject::LogValueObject (Log *log) { - if (log && valobj) - return LogValueObject (log, valobj, DumpValueObjectOptions::DefaultOptions()); + if (log) + return LogValueObject (log, DumpValueObjectOptions::DefaultOptions()); } void -ValueObject::LogValueObject (Log *log, - ValueObject *valobj, - const DumpValueObjectOptions& options) +ValueObject::LogValueObject (Log *log, const DumpValueObjectOptions& options) { - if (log && valobj) + if (log) { StreamString s; - ValueObject::DumpValueObject (s, valobj, options); + Dump (s, options); if (s.GetSize()) log->PutCString(s.GetData()); } } void -ValueObject::DumpValueObject (Stream &s, - ValueObject *valobj) +ValueObject::Dump (Stream &s) { - if (!valobj) - return; - - DumpValueObject_Impl(s, - valobj, - DumpValueObjectOptions::DefaultOptions(), - 0, - 0); + ValueObjectPrinter printer(this,&s,DumpValueObjectOptions::DefaultOptions()); + printer.PrintValueObject(); } void -ValueObject::DumpValueObject (Stream &s, - ValueObject *valobj, - const DumpValueObjectOptions& options) +ValueObject::Dump (Stream &s, + const DumpValueObjectOptions& options) { - DumpValueObject_Impl(s, - valobj, - options, - options.m_max_ptr_depth, // max pointer depth allowed, we will go down from here - 0 // current object depth is 0 since we are just starting - ); + ValueObjectPrinter printer(this,&s,options); + printer.PrintValueObject(); } ValueObjectSP |