From: Enrico Granata Date: Thu, 21 Feb 2013 19:57:10 +0000 (+0000) Subject: X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ea2bc0fb1f10fe7c266ae1c0524653c99f0e36c0;p=platform%2Fupstream%2Fllvm.git Adding data formatters for iterators for std::map and std::vector (both libc++ and libstdcpp) This does not include reverse iterators since they are both trickier (due to requirements the standard imposes on them) and much less useful llvm-svn: 175787 --- diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h index 6427aaa..1546899 100644 --- a/lldb/include/lldb/Core/ValueObject.h +++ b/lldb/include/lldb/Core/ValueObject.h @@ -992,7 +992,7 @@ public: bool IsCStringContainer (bool check_pointer = false); - void + size_t ReadPointedString (Stream& s, Error& error, uint32_t max_length = 0, @@ -1260,7 +1260,6 @@ protected: m_is_deref_of_parent:1, m_is_array_item_for_pointer:1, m_is_bitfield_for_scalar:1, - m_is_expression_path_child:1, m_is_child_at_offset:1, m_is_getting_summary:1, m_did_calculate_complete_objc_class_type:1; diff --git a/lldb/include/lldb/DataFormatters/CXXFormatterFunctions.h b/lldb/include/lldb/DataFormatters/CXXFormatterFunctions.h index 75867ff..a7d5dc9 100644 --- a/lldb/include/lldb/DataFormatters/CXXFormatterFunctions.h +++ b/lldb/include/lldb/DataFormatters/CXXFormatterFunctions.h @@ -557,9 +557,101 @@ namespace lldb_private { }; SyntheticChildrenFrontEnd* LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibstdcppMapIteratorSyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + lldb::addr_t m_pair_address; + ClangASTType m_pair_type; + EvaluateExpressionOptions m_options; + lldb::ValueObjectSP m_pair_sp; + }; + + SyntheticChildrenFrontEnd* LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + class LibCxxMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibCxxMapIteratorSyntheticFrontEnd (); + private: + ValueObject *m_pair_ptr; + }; + + SyntheticChildrenFrontEnd* LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp, + ConstString item_name); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~VectorIteratorSyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + ConstString m_item_name; + lldb::ValueObjectSP m_item_sp; + }; + + SyntheticChildrenFrontEnd* LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + SyntheticChildrenFrontEnd* LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - } -} + } // namespace formatters +} // namespace lldb_private -#endif +#endif // liblldb_CXXFormatterFunctions_h_ diff --git a/lldb/include/lldb/DataFormatters/TypeSynthetic.h b/lldb/include/lldb/DataFormatters/TypeSynthetic.h index 43adf42..3c6a87b 100644 --- a/lldb/include/lldb/DataFormatters/TypeSynthetic.h +++ b/lldb/include/lldb/DataFormatters/TypeSynthetic.h @@ -273,6 +273,15 @@ namespace lldb_private { m_expression_paths() { } + + TypeFilterImpl(const SyntheticChildren::Flags& flags, + const std::initializer_list items) : + SyntheticChildren(flags), + m_expression_paths() + { + for (auto path : items) + AddExpressionPath (path); + } void AddExpressionPath (const char* path) @@ -305,7 +314,7 @@ namespace lldb_private { } void - AddExpressionPath (std::string path) + AddExpressionPath (const std::string& path) { bool need_add_dot = true; if (path[0] == '.' || @@ -320,7 +329,7 @@ namespace lldb_private { } bool - SetExpressionPathAtIndex (int i, std::string path) + SetExpressionPathAtIndex (int i, const std::string& path) { if (i >= GetCount()) return false; diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 9f43278..5049857 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -551,6 +551,8 @@ 94CB257116B0A4270059775D /* TypeSummary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB256E16B0A4260059775D /* TypeSummary.cpp */; }; 94CB257216B0A4270059775D /* TypeSynthetic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB256F16B0A4270059775D /* TypeSynthetic.cpp */; }; 94CB257416B1D3880059775D /* FormatCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB257316B1D3870059775D /* FormatCache.cpp */; }; + 94D0B10C16D5535900EA9C70 /* LibCxx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D0B10A16D5535900EA9C70 /* LibCxx.cpp */; }; + 94D0B10D16D5535900EA9C70 /* LibStdcpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D0B10B16D5535900EA9C70 /* LibStdcpp.cpp */; }; 94D6A0AA16CEB55F00833B6E /* NSArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D6A0A716CEB55F00833B6E /* NSArray.cpp */; }; 94D6A0AB16CEB55F00833B6E /* NSDictionary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D6A0A816CEB55F00833B6E /* NSDictionary.cpp */; }; 94D6A0AC16CEB55F00833B6E /* NSSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D6A0A916CEB55F00833B6E /* NSSet.cpp */; }; @@ -1594,6 +1596,8 @@ 94CB256F16B0A4270059775D /* TypeSynthetic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeSynthetic.cpp; path = source/DataFormatters/TypeSynthetic.cpp; sourceTree = ""; }; 94CB257316B1D3870059775D /* FormatCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatCache.cpp; path = source/DataFormatters/FormatCache.cpp; sourceTree = ""; }; 94CB257516B1D3910059775D /* FormatCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatCache.h; path = include/lldb/DataFormatters/FormatCache.h; sourceTree = ""; }; + 94D0B10A16D5535900EA9C70 /* LibCxx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxx.cpp; path = source/DataFormatters/LibCxx.cpp; sourceTree = ""; }; + 94D0B10B16D5535900EA9C70 /* LibStdcpp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibStdcpp.cpp; path = source/DataFormatters/LibStdcpp.cpp; sourceTree = ""; }; 94D6A0A716CEB55F00833B6E /* NSArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSArray.cpp; path = source/DataFormatters/NSArray.cpp; sourceTree = ""; }; 94D6A0A816CEB55F00833B6E /* NSDictionary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSDictionary.cpp; path = source/DataFormatters/NSDictionary.cpp; sourceTree = ""; }; 94D6A0A916CEB55F00833B6E /* NSSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSSet.cpp; path = source/DataFormatters/NSSet.cpp; sourceTree = ""; }; @@ -3370,6 +3374,8 @@ 94CB256216B069800059775D /* FormatManager.h */, 94CB255A16B069770059775D /* FormatManager.cpp */, 94CB256316B069800059775D /* FormatNavigator.h */, + 94D0B10A16D5535900EA9C70 /* LibCxx.cpp */, + 94D0B10B16D5535900EA9C70 /* LibStdcpp.cpp */, 94D6A0A716CEB55F00833B6E /* NSArray.cpp */, 94D6A0A816CEB55F00833B6E /* NSDictionary.cpp */, 94D6A0A916CEB55F00833B6E /* NSSet.cpp */, @@ -3947,6 +3953,7 @@ 2689004B13353E0400698AC0 /* Section.cpp in Sources */, 2689004C13353E0400698AC0 /* SourceManager.cpp in Sources */, 2689004D13353E0400698AC0 /* State.cpp in Sources */, + 94D0B10D16D5535900EA9C70 /* LibStdcpp.cpp in Sources */, 2689004E13353E0400698AC0 /* Stream.cpp in Sources */, 2689004F13353E0400698AC0 /* StreamFile.cpp in Sources */, 2689005013353E0400698AC0 /* StreamString.cpp in Sources */, @@ -4039,6 +4046,7 @@ 268900C213353E5F00698AC0 /* DWARFDebugPubnamesSet.cpp in Sources */, 268900C313353E5F00698AC0 /* DWARFDebugRanges.cpp in Sources */, 268900C413353E5F00698AC0 /* DWARFDefines.cpp in Sources */, + 94D0B10C16D5535900EA9C70 /* LibCxx.cpp in Sources */, 268900C513353E5F00698AC0 /* DWARFDIECollection.cpp in Sources */, 268900C613353E5F00698AC0 /* DWARFFormValue.cpp in Sources */, 268900C713353E5F00698AC0 /* DWARFLocationDescription.cpp in Sources */, diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 466f41d..50ca804 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -96,7 +96,6 @@ 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_is_child_at_offset(false), m_is_getting_summary(false), m_did_calculate_complete_objc_class_type(false) @@ -141,7 +140,6 @@ 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_is_child_at_offset(false), m_is_getting_summary(false), m_did_calculate_complete_objc_class_type(false) @@ -1040,7 +1038,7 @@ strlen_or_inf (const char* str, return len; } -void +size_t ValueObject::ReadPointedString (Stream& s, Error& error, uint32_t max_length, @@ -1053,6 +1051,9 @@ ValueObject::ReadPointedString (Stream& s, if (target && max_length == 0) max_length = target->GetMaximumSizeOfStringSummary(); + size_t bytes_read = 0; + size_t total_bytes_read = 0; + clang_type_t clang_type = GetClangType(); clang_type_t elem_or_pointee_clang_type; const Flags type_flags (GetTypeInfo (&elem_or_pointee_clang_type)); @@ -1090,7 +1091,6 @@ ValueObject::ReadPointedString (Stream& s, { Address cstr_so_addr (cstr_address); DataExtractor data; - size_t bytes_read = 0; if (cstr_len > 0 && honor_array) { // I am using GetPointeeData() here to abstract the fact that some ValueObjects are actually frozen pointers in the host @@ -1099,6 +1099,7 @@ ValueObject::ReadPointedString (Stream& s, if ((bytes_read = data.GetByteSize()) > 0) { + total_bytes_read = bytes_read; s << '"'; data.Dump (&s, 0, // Start offset in "data" @@ -1127,6 +1128,7 @@ ValueObject::ReadPointedString (Stream& s, // but the pointed-to data lives in the debuggee, and GetPointeeData() automatically takes care of this while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) { + total_bytes_read += bytes_read; const char *cstr = data.PeekCStr(0); size_t len = strlen_or_inf (cstr, k_max_buf_size, k_max_buf_size+1); if (len > k_max_buf_size) @@ -1183,6 +1185,7 @@ ValueObject::ReadPointedString (Stream& s, error.SetErrorString("impossible to read a string from this object"); s << ""; } + return total_bytes_read; } const char * @@ -2107,9 +2110,9 @@ ValueObject::GetSyntheticExpressionPathChild(const char* expression, bool can_cr // Cache the value if we got one back... if (synthetic_child_sp.get()) { + // FIXME: this causes a "real" child to end up with its name changed to the contents of expression AddSyntheticChild(name_const_string, synthetic_child_sp.get()); synthetic_child_sp->SetName(ConstString(SkipLeadingExpressionPathSeparators(expression))); - synthetic_child_sp->m_is_expression_path_child = true; } } return synthetic_child_sp; @@ -2336,8 +2339,8 @@ ValueObject::GetValueForExpressionPath(const char* expression, { const char* dummy_first_unparsed; - ExpressionPathScanEndReason dummy_reason_to_stop; - ExpressionPathEndResultType dummy_final_value_type; + ExpressionPathScanEndReason dummy_reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnknown; + ExpressionPathEndResultType dummy_final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eExpressionPathAftermathNothing; ValueObjectSP ret_val = GetValueForExpressionPath_Impl(expression, diff --git a/lldb/source/DataFormatters/CXXFormatterFunctions.cpp b/lldb/source/DataFormatters/CXXFormatterFunctions.cpp index 8ea06b0..156fd7e 100644 --- a/lldb/source/DataFormatters/CXXFormatterFunctions.cpp +++ b/lldb/source/DataFormatters/CXXFormatterFunctions.cpp @@ -550,10 +550,11 @@ lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stre if (!location_sp) return false; Error error; - location_sp->ReadPointedString(stream, - error, - 0, // max length is decided by the settings - false); // do not honor array (terminates on first 0 byte even for a char[]) + if (location_sp->ReadPointedString(stream, + error, + 0, // max length is decided by the settings + false) == 0) // do not honor array (terminates on first 0 byte even for a char[]) + stream.Printf("\"\""); // if nothing was read, print an empty string return error.Success(); } @@ -1073,320 +1074,70 @@ lldb_private::formatters::ExtractIndexFromString (const char* item_name) return idx; } -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : - SyntheticChildrenFrontEnd(*valobj_sp.get()), - m_exe_ctx_ref(), - m_count(0), - m_base_data_address(0), - m_options() - { - if (valobj_sp) - Update(); - m_options.SetCoerceToId(false) - .SetUnwindOnError(true) - .SetKeepInMemory(true) - .SetUseDynamic(lldb::eDynamicCanRunTarget); - } - -size_t -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren () -{ - return m_count; -} - -lldb::ValueObjectSP -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx) +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp, + ConstString item_name) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_exe_ctx_ref(), +m_item_name(item_name), +m_item_sp() { - if (idx >= m_count) - return ValueObjectSP(); - if (m_base_data_address == 0 || m_count == 0) - return ValueObjectSP(); - size_t byte_idx = (idx >> 3); // divide by 8 to get byte index - size_t bit_index = (idx & 7); // efficient idx % 8 for bit index - lldb::addr_t byte_location = m_base_data_address + byte_idx; - ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP()); - if (!process_sp) - return ValueObjectSP(); - uint8_t byte = 0; - uint8_t mask = 0; - Error err; - size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err); - if (err.Fail() || bytes_read == 0) - return ValueObjectSP(); - switch (bit_index) - { - case 0: - mask = 1; break; - case 1: - mask = 2; break; - case 2: - mask = 4; break; - case 3: - mask = 8; break; - case 4: - mask = 16; break; - case 5: - mask = 32; break; - case 6: - mask = 64; break; - case 7: - mask = 128; break; - default: - return ValueObjectSP(); - } - bool bit_set = ((byte & mask) != 0); - Target& target(process_sp->GetTarget()); - ValueObjectSP retval_sp; - if (bit_set) - target.EvaluateExpression("(bool)true", NULL, retval_sp); - else - target.EvaluateExpression("(bool)false", NULL, retval_sp); - StreamString name; name.Printf("[%zu]",idx); - if (retval_sp) - retval_sp->SetName(ConstString(name.GetData())); - return retval_sp; + if (valobj_sp) + Update(); } -/*(std::__1::vector >) vBool = { - __begin_ = 0x00000001001000e0 - __size_ = 56 - __cap_alloc_ = { - std::__1::__libcpp_compressed_pair_imp > = { - __first_ = 1 - } - } -}*/ - bool -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update() +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update() { ValueObjectSP valobj_sp = m_backend.GetSP(); if (!valobj_sp) return false; - if (valobj_sp->IsDynamic()) - valobj_sp = valobj_sp->GetStaticValue(); + if (!valobj_sp) return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true)); - if (!size_sp) - return false; - m_count = size_sp->GetValueAsUnsigned(0); - if (!m_count) - return true; - ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true)); - if (!begin_sp) - { - m_count = 0; + + ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true)); + if (!item_ptr) return false; - } - m_base_data_address = begin_sp->GetValueAsUnsigned(0); - if (!m_base_data_address) - { - m_count = 0; + if (item_ptr->GetValueAsUnsigned(0) == 0) return false; - } - return true; -} - -bool -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - if (!m_count || !m_base_data_address) - return UINT32_MAX; - const char* item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; -} - -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd () -{} - -SyntheticChildrenFrontEnd* -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - if (!valobj_sp) - return NULL; - return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp)); -} - -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_exe_ctx_ref(), -m_count(0), -m_base_data_address(0), -m_options() -{ - if (valobj_sp) - Update(); - m_options.SetCoerceToId(false) - .SetUnwindOnError(true) - .SetKeepInMemory(true) - .SetUseDynamic(lldb::eDynamicCanRunTarget); + Error err; + m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); + m_item_sp = ValueObject::CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, ClangASTType(item_ptr->GetClangAST(),ClangASTType::GetPointeeType(item_ptr->GetClangType()))); + if (err.Fail()) + m_item_sp.reset(); + return (m_item_sp.get() != NULL); } size_t -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::CalculateNumChildren () +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren () { - return m_count; + return 1; } lldb::ValueObjectSP -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx) +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) { - if (idx >= m_count) - return ValueObjectSP(); - if (m_base_data_address == 0 || m_count == 0) - return ValueObjectSP(); - size_t byte_idx = (idx >> 3); // divide by 8 to get byte index - size_t bit_index = (idx & 7); // efficient idx % 8 for bit index - lldb::addr_t byte_location = m_base_data_address + byte_idx; - ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP()); - if (!process_sp) - return ValueObjectSP(); - uint8_t byte = 0; - uint8_t mask = 0; - Error err; - size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err); - if (err.Fail() || bytes_read == 0) - return ValueObjectSP(); - switch (bit_index) - { - case 0: - mask = 1; break; - case 1: - mask = 2; break; - case 2: - mask = 4; break; - case 3: - mask = 8; break; - case 4: - mask = 16; break; - case 5: - mask = 32; break; - case 6: - mask = 64; break; - case 7: - mask = 128; break; - default: - return ValueObjectSP(); - } - bool bit_set = ((byte & mask) != 0); - Target& target(process_sp->GetTarget()); - ValueObjectSP retval_sp; - if (bit_set) - target.EvaluateExpression("(bool)true", NULL, retval_sp); - else - target.EvaluateExpression("(bool)false", NULL, retval_sp); - StreamString name; name.Printf("[%zu]",idx); - if (retval_sp) - retval_sp->SetName(ConstString(name.GetData())); - return retval_sp; -} - -/*((std::vector >) vBool = { - (std::_Bvector_base >) std::_Bvector_base > = { - (std::_Bvector_base >::_Bvector_impl) _M_impl = { - (std::_Bit_iterator) _M_start = { - (std::_Bit_iterator_base) std::_Bit_iterator_base = { - (_Bit_type *) _M_p = 0x0016b160 - (unsigned int) _M_offset = 0 - } - } - (std::_Bit_iterator) _M_finish = { - (std::_Bit_iterator_base) std::_Bit_iterator_base = { - (_Bit_type *) _M_p = 0x0016b16c - (unsigned int) _M_offset = 16 - } - } - (_Bit_type *) _M_end_of_storage = 0x0016b170 - } - } - } -*/ - -bool -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::Update() -{ - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return false; - if (valobj_sp->IsDynamic()) - valobj_sp = valobj_sp->GetStaticValue(); - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - - ValueObjectSP m_impl_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_impl"), true)); - if (!m_impl_sp) - return false; - - ValueObjectSP m_start_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_start"), true)); - ValueObjectSP m_finish_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_finish"), true)); - - ValueObjectSP start_p_sp, finish_p_sp, finish_offset_sp; - - if (!m_start_sp || !m_finish_sp) - return false; - - start_p_sp = m_start_sp->GetChildMemberWithName(ConstString("_M_p"), true); - finish_p_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_p"), true); - finish_offset_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_offset"), true); - - if (!start_p_sp || !finish_offset_sp || !finish_p_sp) - return false; - - m_base_data_address = start_p_sp->GetValueAsUnsigned(0); - if (!m_base_data_address) - return false; - - lldb::addr_t end_data_address(finish_p_sp->GetValueAsUnsigned(0)); - if (!end_data_address) - return false; - - if (end_data_address < m_base_data_address) - return false; - else - m_count = finish_offset_sp->GetValueAsUnsigned(0) + (end_data_address-m_base_data_address)*8; - - return true; + if (idx == 0) + return m_item_sp; + return lldb::ValueObjectSP(); } bool -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::MightHaveChildren () +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren () { return true; } size_t -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) { - if (!m_count || !m_base_data_address) - return UINT32_MAX; - const char* item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; + if (name == ConstString("item")) + return 0; + return UINT32_MAX; } -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::~LibstdcppVectorBoolSyntheticFrontEnd () -{} - -SyntheticChildrenFrontEnd* -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd () { - if (!valobj_sp) - return NULL; - return (new LibstdcppVectorBoolSyntheticFrontEnd(valobj_sp)); } template bool diff --git a/lldb/source/DataFormatters/FormatManager.cpp b/lldb/source/DataFormatters/FormatManager.cpp index 7029c6a..52986cf 100644 --- a/lldb/source/DataFormatters/FormatManager.cpp +++ b/lldb/source/DataFormatters/FormatManager.cpp @@ -443,12 +443,16 @@ static void AddStringSummary(TypeCategoryImpl::SharedPointer category_sp, const char* string, ConstString type_name, - TypeSummaryImpl::Flags flags) + TypeSummaryImpl::Flags flags, + bool regex = false) { lldb::TypeSummaryImplSP summary_sp(new StringSummaryFormat(flags, string)); - category_sp->GetSummaryNavigator()->Add(type_name, - summary_sp); + + if (regex) + {} + else + category_sp->GetSummaryNavigator()->Add(type_name, summary_sp); } #ifndef LLDB_DISABLE_PYTHON @@ -456,7 +460,8 @@ static void AddScriptSummary(TypeCategoryImpl::SharedPointer category_sp, const char* funct_name, ConstString type_name, - TypeSummaryImpl::Flags flags) + TypeSummaryImpl::Flags flags, + bool regex = false) { std::string code(" "); @@ -465,8 +470,10 @@ AddScriptSummary(TypeCategoryImpl::SharedPointer category_sp, lldb::TypeSummaryImplSP summary_sp(new ScriptSummaryFormat(flags, funct_name, code.c_str())); - category_sp->GetSummaryNavigator()->Add(type_name, - summary_sp); + if (regex) + {} + else + category_sp->GetSummaryNavigator()->Add(type_name, summary_sp); } #endif @@ -476,11 +483,14 @@ AddCXXSummary (TypeCategoryImpl::SharedPointer category_sp, CXXFunctionSummaryFormat::Callback funct, const char* description, ConstString type_name, - TypeSummaryImpl::Flags flags) + TypeSummaryImpl::Flags flags, + bool regex = false) { lldb::TypeSummaryImplSP summary_sp(new CXXFunctionSummaryFormat(flags,funct,description)); - category_sp->GetSummaryNavigator()->Add(type_name, - summary_sp); + if (regex) + {} + else + category_sp->GetSummaryNavigator()->Add(type_name, summary_sp); } #endif @@ -489,10 +499,14 @@ static void AddCXXSynthetic (TypeCategoryImpl::SharedPointer category_sp, CXXSyntheticChildren::CreateFrontEndCallback generator, const char* description, ConstString type_name, - ScriptedSyntheticChildren::Flags flags) + ScriptedSyntheticChildren::Flags flags, + bool regex = false) { lldb::SyntheticChildrenSP synth_sp(new CXXSyntheticChildren(flags,description,generator)); - category_sp->GetSyntheticNavigator()->Add(type_name,synth_sp); + if (regex) + category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression(type_name.AsCString())), synth_sp); + else + category_sp->GetSyntheticNavigator()->Add(type_name,synth_sp); } #endif @@ -561,6 +575,10 @@ FormatManager::LoadLibStdcppFormatters() gnu_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")), TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); + + AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true); + + AddCXXSynthetic(gnu_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true); gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::vector >"), TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); @@ -634,9 +652,13 @@ FormatManager::LoadLibcxxFormatters() libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::deque<.+>(( )?&)?$")), TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}"))); libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::shared_ptr<.+>(( )?&)?$")), - TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "{${var.__ptr_%S}} (strong=${var.count} weak=${var.weak_count})"))); + TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "{${var.__ptr_%S}} (strong=${var.count} weak=${var.weak_count})}"))); libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::weak_ptr<.+>(( )?&)?$")), - TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "{${var.__ptr_%S}} (strong=${var.count} weak=${var.weak_count})"))); + TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "{${var.__ptr_%S}} (strong=${var.count} weak=${var.weak_count})}"))); + + AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^std::__1::__wrap_iter<.+>$"), stl_synth_flags, true); + + AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::__1::__map_iterator<.+>$"), stl_synth_flags, true); // this summary prevails on the regex std::vector<> because we do exact matches before regex ones libcxx_category_sp->GetSummaryNavigator()->Add(ConstString("std::__1::vector >"), @@ -644,7 +666,7 @@ FormatManager::LoadLibcxxFormatters() libcxx_category_sp->GetSyntheticNavigator()->Add(ConstString("std::__1::vector >"), SyntheticChildrenSP(new CXXSyntheticChildren(stl_synth_flags,"libc++ std::vector synthetic children",lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator))); - + #endif } diff --git a/lldb/source/DataFormatters/LibCxx.cpp b/lldb/source/DataFormatters/LibCxx.cpp new file mode 100644 index 0000000..41cb264 --- /dev/null +++ b/lldb/source/DataFormatters/LibCxx.cpp @@ -0,0 +1,285 @@ +//===-- LibCxx.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/DataFormatters/CXXFormatterFunctions.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_exe_ctx_ref(), +m_count(0), +m_base_data_address(0), +m_options() +{ + if (valobj_sp) + Update(); + m_options.SetCoerceToId(false) + .SetUnwindOnError(true) + .SetKeepInMemory(true) + .SetUseDynamic(lldb::eDynamicCanRunTarget); +} + +size_t +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren () +{ + return m_count; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ + if (idx >= m_count) + return ValueObjectSP(); + if (m_base_data_address == 0 || m_count == 0) + return ValueObjectSP(); + size_t byte_idx = (idx >> 3); // divide by 8 to get byte index + size_t bit_index = (idx & 7); // efficient idx % 8 for bit index + lldb::addr_t byte_location = m_base_data_address + byte_idx; + ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP()); + if (!process_sp) + return ValueObjectSP(); + uint8_t byte = 0; + uint8_t mask = 0; + Error err; + size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err); + if (err.Fail() || bytes_read == 0) + return ValueObjectSP(); + switch (bit_index) + { + case 0: + mask = 1; break; + case 1: + mask = 2; break; + case 2: + mask = 4; break; + case 3: + mask = 8; break; + case 4: + mask = 16; break; + case 5: + mask = 32; break; + case 6: + mask = 64; break; + case 7: + mask = 128; break; + default: + return ValueObjectSP(); + } + bool bit_set = ((byte & mask) != 0); + Target& target(process_sp->GetTarget()); + ValueObjectSP retval_sp; + if (bit_set) + target.EvaluateExpression("(bool)true", NULL, retval_sp); + else + target.EvaluateExpression("(bool)false", NULL, retval_sp); + StreamString name; name.Printf("[%zu]",idx); + if (retval_sp) + retval_sp->SetName(ConstString(name.GetData())); + return retval_sp; +} + +/*(std::__1::vector >) vBool = { + __begin_ = 0x00000001001000e0 + __size_ = 56 + __cap_alloc_ = { + std::__1::__libcpp_compressed_pair_imp > = { + __first_ = 1 + } + } + }*/ + +bool +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update() +{ + ValueObjectSP valobj_sp = m_backend.GetSP(); + if (!valobj_sp) + return false; + if (!valobj_sp) + return false; + m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); + ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true)); + if (!size_sp) + return false; + m_count = size_sp->GetValueAsUnsigned(0); + if (!m_count) + return true; + ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true)); + if (!begin_sp) + { + m_count = 0; + return false; + } + m_base_data_address = begin_sp->GetValueAsUnsigned(0); + if (!m_base_data_address) + { + m_count = 0; + return false; + } + return true; +} + +bool +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren () +{ + return true; +} + +size_t +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ + if (!m_count || !m_base_data_address) + return UINT32_MAX; + const char* item_name = name.GetCString(); + uint32_t idx = ExtractIndexFromString(item_name); + if (idx < UINT32_MAX && idx >= CalculateNumChildren()) + return UINT32_MAX; + return idx; +} + +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd () +{} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ + if (!valobj_sp) + return NULL; + return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp)); +} + +/* + (lldb) fr var ibeg --raw --ptr-depth 1 + (std::__1::__map_iterator, std::__1::allocator > >, std::__1::__tree_node, std::__1::allocator > >, void *> *, long> >) ibeg = { + __i_ = { + __ptr_ = 0x0000000100103870 { + std::__1::__tree_node_base = { + std::__1::__tree_end_node *> = { + __left_ = 0x0000000000000000 + } + __right_ = 0x0000000000000000 + __parent_ = 0x00000001001038b0 + __is_black_ = true + } + __value_ = { + first = 0 + second = { std::string } + */ + +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_pair_ptr() +{ + if (valobj_sp) + Update(); +} + +bool +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() +{ + ValueObjectSP valobj_sp = m_backend.GetSP(); + if (!valobj_sp) + return false; + + TargetSP target_sp(valobj_sp->GetTargetSP()); + + if (!target_sp) + return false; + + if (!valobj_sp) + return false; + + // this must be a ValueObject* because it is a child of the ValueObject we are producing children for + // it if were a ValueObjectSP, we would end up with a loop (iterator -> synthetic -> child -> parent == iterator) + // and that would in turn leak memory by never allowing the ValueObjects to die and free their memory + m_pair_ptr = valobj_sp->GetValueForExpressionPath(".__i_.__ptr_->__value_", + NULL, + NULL, + NULL, + ValueObject::GetValueForExpressionPathOptions().DontCheckDotVsArrowSyntax().DontAllowSyntheticChildren(), + NULL).get(); + + return (m_pair_ptr != NULL); +} + +size_t +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::CalculateNumChildren () +{ + return 2; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ + if (!m_pair_ptr) + return lldb::ValueObjectSP(); + return m_pair_ptr->GetChildAtIndex(idx, true); +} + +bool +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::MightHaveChildren () +{ + return true; +} + +size_t +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ + if (name == ConstString("first")) + return 0; + if (name == ConstString("second")) + return 1; + return UINT32_MAX; +} + +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::~LibCxxMapIteratorSyntheticFrontEnd () +{ + // this will be deleted when its parent dies (since it's a child object) + //delete m_pair_ptr; +} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ + if (!valobj_sp) + return NULL; + return (new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)); +} + +/* + (lldb) fr var ibeg --raw --ptr-depth 1 -T + (std::__1::__wrap_iter) ibeg = { + (std::__1::__wrap_iter::iterator_type) __i = 0x00000001001037a0 { + (int) *__i = 1 + } + } +*/ + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ + static ConstString g_item_name; + if (!g_item_name) + g_item_name.SetCString("__i"); + if (!valobj_sp) + return NULL; + return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name)); +} diff --git a/lldb/source/DataFormatters/LibStdcpp.cpp b/lldb/source/DataFormatters/LibStdcpp.cpp new file mode 100644 index 0000000..76f4eba --- /dev/null +++ b/lldb/source/DataFormatters/LibStdcpp.cpp @@ -0,0 +1,331 @@ +//===-- LibStdcpp.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/DataFormatters/CXXFormatterFunctions.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_exe_ctx_ref(), +m_count(0), +m_base_data_address(0), +m_options() +{ + if (valobj_sp) + Update(); + m_options.SetCoerceToId(false) + .SetUnwindOnError(true) + .SetKeepInMemory(true) + .SetUseDynamic(lldb::eDynamicCanRunTarget); +} + +size_t +lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::CalculateNumChildren () +{ + return m_count; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ + if (idx >= m_count) + return ValueObjectSP(); + if (m_base_data_address == 0 || m_count == 0) + return ValueObjectSP(); + size_t byte_idx = (idx >> 3); // divide by 8 to get byte index + size_t bit_index = (idx & 7); // efficient idx % 8 for bit index + lldb::addr_t byte_location = m_base_data_address + byte_idx; + ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP()); + if (!process_sp) + return ValueObjectSP(); + uint8_t byte = 0; + uint8_t mask = 0; + Error err; + size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err); + if (err.Fail() || bytes_read == 0) + return ValueObjectSP(); + switch (bit_index) + { + case 0: + mask = 1; break; + case 1: + mask = 2; break; + case 2: + mask = 4; break; + case 3: + mask = 8; break; + case 4: + mask = 16; break; + case 5: + mask = 32; break; + case 6: + mask = 64; break; + case 7: + mask = 128; break; + default: + return ValueObjectSP(); + } + bool bit_set = ((byte & mask) != 0); + Target& target(process_sp->GetTarget()); + ValueObjectSP retval_sp; + if (bit_set) + target.EvaluateExpression("(bool)true", NULL, retval_sp); + else + target.EvaluateExpression("(bool)false", NULL, retval_sp); + StreamString name; name.Printf("[%zu]",idx); + if (retval_sp) + retval_sp->SetName(ConstString(name.GetData())); + return retval_sp; +} + +/*((std::vector >) vBool = { + (std::_Bvector_base >) std::_Bvector_base > = { + (std::_Bvector_base >::_Bvector_impl) _M_impl = { + (std::_Bit_iterator) _M_start = { + (std::_Bit_iterator_base) std::_Bit_iterator_base = { + (_Bit_type *) _M_p = 0x0016b160 + (unsigned int) _M_offset = 0 + } + } + (std::_Bit_iterator) _M_finish = { + (std::_Bit_iterator_base) std::_Bit_iterator_base = { + (_Bit_type *) _M_p = 0x0016b16c + (unsigned int) _M_offset = 16 + } + } + (_Bit_type *) _M_end_of_storage = 0x0016b170 + } + } + } + */ + +bool +lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::Update() +{ + ValueObjectSP valobj_sp = m_backend.GetSP(); + if (!valobj_sp) + return false; + if (!valobj_sp) + return false; + m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); + + ValueObjectSP m_impl_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_impl"), true)); + if (!m_impl_sp) + return false; + + ValueObjectSP m_start_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_start"), true)); + ValueObjectSP m_finish_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_finish"), true)); + + ValueObjectSP start_p_sp, finish_p_sp, finish_offset_sp; + + if (!m_start_sp || !m_finish_sp) + return false; + + start_p_sp = m_start_sp->GetChildMemberWithName(ConstString("_M_p"), true); + finish_p_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_p"), true); + finish_offset_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_offset"), true); + + if (!start_p_sp || !finish_offset_sp || !finish_p_sp) + return false; + + m_base_data_address = start_p_sp->GetValueAsUnsigned(0); + if (!m_base_data_address) + return false; + + lldb::addr_t end_data_address(finish_p_sp->GetValueAsUnsigned(0)); + if (!end_data_address) + return false; + + if (end_data_address < m_base_data_address) + return false; + else + m_count = finish_offset_sp->GetValueAsUnsigned(0) + (end_data_address-m_base_data_address)*8; + + return true; +} + +bool +lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::MightHaveChildren () +{ + return true; +} + +size_t +lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ + if (!m_count || !m_base_data_address) + return UINT32_MAX; + const char* item_name = name.GetCString(); + uint32_t idx = ExtractIndexFromString(item_name); + if (idx < UINT32_MAX && idx >= CalculateNumChildren()) + return UINT32_MAX; + return idx; +} + +lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::~LibstdcppVectorBoolSyntheticFrontEnd () +{} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ + if (!valobj_sp) + return NULL; + return (new LibstdcppVectorBoolSyntheticFrontEnd(valobj_sp)); +} + +/* + (std::_Rb_tree_iterator, std::allocator > > >) ibeg = { + (_Base_ptr) _M_node = 0x0000000100103910 { + (std::_Rb_tree_color) _M_color = _S_black + (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0 + (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000 + (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000 + } + } + */ + +lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_exe_ctx_ref(), +m_pair_address(0), +m_pair_type(), +m_options(), +m_pair_sp() +{ + if (valobj_sp) + Update(); + m_options.SetCoerceToId(false) + .SetUnwindOnError(true) + .SetKeepInMemory(true) + .SetUseDynamic(lldb::eDynamicCanRunTarget); +} + +bool +lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::Update() +{ + ValueObjectSP valobj_sp = m_backend.GetSP(); + if (!valobj_sp) + return false; + + TargetSP target_sp(valobj_sp->GetTargetSP()); + + if (!target_sp) + return false; + + bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8); + + if (!valobj_sp) + return false; + m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); + + ValueObjectSP _M_node_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_node"), true)); + if (!_M_node_sp) + return false; + + m_pair_address = _M_node_sp->GetValueAsUnsigned(0); + if (m_pair_address == 0) + return false; + + m_pair_address += (is_64bit ? 32 : 16); + + ClangASTType my_type(valobj_sp->GetClangAST(),valobj_sp->GetClangType()); + if (ClangASTContext::GetNumTemplateArguments(valobj_sp->GetClangAST(),valobj_sp->GetClangType()) >= 1) + { + TemplateArgumentKind kind; + clang_type_t pair_type = ClangASTContext::GetTemplateArgument(valobj_sp->GetClangAST(),valobj_sp->GetClangType(), 0, kind); + if (kind != eTemplateArgumentKindType && kind != eTemplateArgumentKindTemplate && kind != eTemplateArgumentKindTemplateExpansion) + return false; + m_pair_type = ClangASTType(valobj_sp->GetClangAST(),pair_type); + } + else + return false; + + return true; +} + +size_t +lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren () +{ + return 2; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ + if (m_pair_address == 0) + return lldb::ValueObjectSP(); + if (m_pair_type.GetASTContext() == NULL || + m_pair_type.GetOpaqueQualType() == NULL) + return lldb::ValueObjectSP(); + if (!m_pair_sp) + m_pair_sp = ValueObject::CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type); + if (m_pair_sp) + return m_pair_sp->GetChildAtIndex(idx, true); + return lldb::ValueObjectSP(); +} + +bool +lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren () +{ + return true; +} + +size_t +lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ + if (name == ConstString("first")) + return 0; + if (name == ConstString("second")) + return 1; + return UINT32_MAX; +} + +lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::~LibstdcppMapIteratorSyntheticFrontEnd () +{} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ + if (!valobj_sp) + return NULL; + return (new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp)); +} + +/* + (lldb) fr var ibeg --ptr-depth 1 + (__gnu_cxx::__normal_iterator > >) ibeg = { + _M_current = 0x00000001001037a0 { + *_M_current = 1 + } + } + */ + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ + static ConstString g_item_name; + if (!g_item_name) + g_item_name.SetCString("_M_current"); + if (!valobj_sp) + return NULL; + return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name)); +} diff --git a/lldb/source/DataFormatters/NSArray.cpp b/lldb/source/DataFormatters/NSArray.cpp index 9aef1e98e..ece97cc 100644 --- a/lldb/source/DataFormatters/NSArray.cpp +++ b/lldb/source/DataFormatters/NSArray.cpp @@ -7,12 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/DataFormatters/CXXFormatterFunctions.h" -#include "llvm/Support/ConvertUTF.h" - #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Core/Stream.h" @@ -144,8 +140,6 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::Update() m_data_32 = NULL; delete m_data_64; m_data_64 = NULL; - if (valobj_sp->IsDynamic()) - valobj_sp = valobj_sp->GetStaticValue(); if (!valobj_sp) return false; m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); @@ -245,8 +239,6 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::Update() m_data_ptr = 0; m_children.clear(); ValueObjectSP valobj_sp = m_backend.GetSP(); - if (valobj_sp->IsDynamic()) - valobj_sp = valobj_sp->GetStaticValue(); if (!valobj_sp) return false; m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); diff --git a/lldb/source/DataFormatters/NSDictionary.cpp b/lldb/source/DataFormatters/NSDictionary.cpp index 3c8f336..18f00cc 100644 --- a/lldb/source/DataFormatters/NSDictionary.cpp +++ b/lldb/source/DataFormatters/NSDictionary.cpp @@ -7,12 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/DataFormatters/CXXFormatterFunctions.h" -#include "llvm/Support/ConvertUTF.h" - #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Core/Stream.h" @@ -245,8 +241,6 @@ lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update() ValueObjectSP valobj_sp = m_backend.GetSP(); if (!valobj_sp) return false; - if (valobj_sp->IsDynamic()) - valobj_sp = valobj_sp->GetStaticValue(); if (!valobj_sp) return false; m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); @@ -393,8 +387,6 @@ lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() m_data_64 = NULL; if (!valobj_sp) return false; - if (valobj_sp->IsDynamic()) - valobj_sp = valobj_sp->GetStaticValue(); if (!valobj_sp) return false; m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); diff --git a/lldb/source/DataFormatters/NSSet.cpp b/lldb/source/DataFormatters/NSSet.cpp index e17a78d..5f53bac 100644 --- a/lldb/source/DataFormatters/NSSet.cpp +++ b/lldb/source/DataFormatters/NSSet.cpp @@ -7,12 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-python.h" - #include "lldb/DataFormatters/CXXFormatterFunctions.h" -#include "llvm/Support/ConvertUTF.h" - #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Core/Stream.h" @@ -201,8 +197,6 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::Update() ValueObjectSP valobj_sp = m_backend.GetSP(); if (!valobj_sp) return false; - if (valobj_sp->IsDynamic()) - valobj_sp = valobj_sp->GetStaticValue(); if (!valobj_sp) return false; m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); @@ -345,8 +339,6 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::Update() m_data_64 = NULL; if (!valobj_sp) return false; - if (valobj_sp->IsDynamic()) - valobj_sp = valobj_sp->GetStaticValue(); if (!valobj_sp) return false; m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/Makefile b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/Makefile new file mode 100644 index 0000000..f2f2b3f2 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules + +CXXFLAGS += -stdlib=libc++ -O0 +LDFLAGS += -stdlib=libc++ \ No newline at end of file diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/TestDataFormatterLibccIterator.py b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/TestDataFormatterLibccIterator.py new file mode 100644 index 0000000..97d8082 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/TestDataFormatterLibccIterator.py @@ -0,0 +1,78 @@ +""" +Test lldb data formatter subsystem. +""" + +import os, time +import unittest2 +import lldb +from lldbtest import * +import lldbutil + +class LibcxxIteratorDataFormatterTestCase(TestBase): + + mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libcxx", "iterator") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @dsym_test + def test_with_dsym_and_run_command(self): + """Test data formatter commands.""" + self.buildDsym() + self.data_formatter_commands() + + @skipOnLinux # No standard locations for libc++ on Linux, so skip for now + @dwarf_test + def test_with_dwarf_and_run_command(self): + """Test data formatter commands.""" + self.buildDwarf() + self.data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def data_formatter_commands(self): + """Test that libc++ iterators format properly.""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=-1) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd("settings set target.max-children-count 256", check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.expect('image list',substrs=['libc++.1.dylib','libc++abi.dylib']) + + self.expect('frame variable ivI', substrs = ['item = 3']) + self.expect('expr ivI', substrs = ['item = 3']) + + self.expect('frame variable iimI', substrs = ['first = 0','second = 12']) + self.expect('expr iimI', substrs = ['first = 0','second = 12']) + + self.expect('frame variable simI', substrs = ['first = "world"','second = 42']) + self.expect('expr simI', substrs = ['first = "world"','second = 42']) + + self.expect('frame variable svI', substrs = ['item = "hello"']) + self.expect('expr svI', substrs = ['item = "hello"']) + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/main.cpp new file mode 100644 index 0000000..97b3785 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/iterator/main.cpp @@ -0,0 +1,42 @@ +#include +#ifdef _LIBCPP_INLINE_VISIBILITY +#undef _LIBCPP_INLINE_VISIBILITY +#endif +#define _LIBCPP_INLINE_VISIBILITY +#include +#include + +typedef std::map intint_map; +typedef std::map strint_map; + +typedef std::vector int_vector; +typedef std::vector string_vector; + +typedef intint_map::iterator iimter; +typedef strint_map::iterator simter; + +typedef int_vector::iterator ivter; +typedef string_vector::iterator svter; + +int main() +{ + intint_map iim; + iim[0] = 12; + + strint_map sim; + sim["world"] = 42; + + int_vector iv; + iv.push_back(3); + + string_vector sv; + sv.push_back("hello"); + + iimter iimI = iim.begin(); + simter simI = sim.begin(); + + ivter ivI = iv.begin(); + svter svI = sv.begin(); + + return 0; // Set break point at this line. +} \ No newline at end of file diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/Makefile b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/Makefile new file mode 100644 index 0000000..3b26f43 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules + +CXXFLAGS += -stdlib=libstdc++ -O0 +LDFLAGS += -stdlib=libstdc++ diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/TestDataFormatterStdIterator.py b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/TestDataFormatterStdIterator.py new file mode 100644 index 0000000..d7e9435 --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/TestDataFormatterStdIterator.py @@ -0,0 +1,76 @@ +""" +Test lldb data formatter subsystem. +""" + +import os, time +import unittest2 +import lldb +from lldbtest import * +import lldbutil + +class StdIteratorDataFormatterTestCase(TestBase): + + mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libstdcpp", "iterator") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @dsym_test + def test_with_dsym_and_run_command(self): + """Test data formatter commands.""" + self.buildDsym() + self.data_formatter_commands() + + @skipOnLinux #PR-15256: assertion failure in RecordLayoutBuilder::updateExternalFieldOffset + @dwarf_test + def test_with_dwarf_and_run_command(self): + """Test data formatter commands.""" + self.buildDwarf() + self.data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def data_formatter_commands(self): + """Test that libstdcpp iterators format properly.""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=-1) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synth clear', check=False) + self.runCmd("settings set target.max-children-count 256", check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.expect('frame variable ivI', substrs = ['item = 3']) + self.expect('expr ivI', substrs = ['item = 3']) + + self.expect('frame variable iimI', substrs = ['first = 0','second = 12']) + self.expect('expr iimI', substrs = ['first = 0','second = 12']) + + self.expect('frame variable simI', substrs = ['first = "world"','second = 42']) + self.expect('expr simI', substrs = ['first = "world"','second = 42']) + + self.expect('frame variable svI', substrs = ['item = "hello"']) + self.expect('expr svI', substrs = ['item = "hello"']) + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp new file mode 100644 index 0000000..d7b046c --- /dev/null +++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp @@ -0,0 +1,38 @@ +#include +#include +#include + +typedef std::map intint_map; +typedef std::map strint_map; + +typedef std::vector int_vector; +typedef std::vector string_vector; + +typedef intint_map::iterator iimter; +typedef strint_map::iterator simter; + +typedef int_vector::iterator ivter; +typedef string_vector::iterator svter; + +int main() +{ + intint_map iim; + iim[0] = 12; + + strint_map sim; + sim["world"] = 42; + + int_vector iv; + iv.push_back(3); + + string_vector sv; + sv.push_back("hello"); + + iimter iimI = iim.begin(); + simter simI = sim.begin(); + + ivter ivI = iv.begin(); + svter svI = sv.begin(); + + return 0; // Set break point at this line. +} \ No newline at end of file