diff options
Diffstat (limited to 'source/Plugins/Language')
18 files changed, 1064 insertions, 584 deletions
diff --git a/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/source/Plugins/Language/CPlusPlus/CMakeLists.txt index 8f769c499987f..180440a244a4a 100644 --- a/source/Plugins/Language/CPlusPlus/CMakeLists.txt +++ b/source/Plugins/Language/CPlusPlus/CMakeLists.txt @@ -5,9 +5,12 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN CxxStringTypes.cpp LibCxx.cpp LibCxxAtomic.cpp + LibCxxBitset.cpp LibCxxInitializerList.cpp LibCxxList.cpp LibCxxMap.cpp + LibCxxQueue.cpp + LibCxxTuple.cpp LibCxxUnorderedMap.cpp LibCxxVector.cpp LibStdcpp.cpp diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 1ae9418e4d9c0..51ed88065c84d 100644 --- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -422,12 +422,24 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { AddCXXSynthetic( cpp_category_sp, + lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator, + "libc++ std::bitset synthetic children", + ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), stl_synth_flags, + true); + AddCXXSynthetic( + cpp_category_sp, lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_synth_flags, true); AddCXXSynthetic( cpp_category_sp, + lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator, + "libc++ std::forward_list synthetic children", + ConstString("^std::__(ndk)?1::forward_list<.+>(( )?&)?$"), + stl_synth_flags, true); + AddCXXSynthetic( + cpp_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"), stl_synth_flags, true); @@ -467,6 +479,14 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libc++ std::initializer_list synthetic children", ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator, + "libc++ std::queue synthetic children", + ConstString("^std::__(ndk)?1::queue<.+>(( )?&)?$"), + stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, LibcxxTupleFrontEndCreator, + "libc++ std::tuple synthetic children", + ConstString("^std::__(ndk)?1::tuple<.*>(( )?&)?$"), stl_synth_flags, + true); AddCXXSynthetic( cpp_category_sp, lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator, @@ -497,12 +517,22 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { stl_summary_flags.SetSkipPointers(false); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, + "libc++ std::bitset summary provider", + ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_summary_flags, true); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", + ConstString("^std::__(ndk)?1::forward_list<.+>(( )?&)?$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxContainerSummaryProvider, + "libc++ std::list summary provider", ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"), stl_summary_flags, true); AddCXXSummary(cpp_category_sp, @@ -517,6 +547,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { stl_summary_flags, true); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, + "libc++ std::queue summary provider", + ConstString("^std::__(ndk)?1::queue<.+>(( )?&)?$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__(ndk)?1::set<.+>(( )?&)?$"), stl_summary_flags, true); @@ -535,6 +570,10 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libc++ std::unordered containers summary provider", ConstString("^(std::__(ndk)?1::)unordered_(multi)?(map|set)<.+> >$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, LibcxxContainerSummaryProvider, + "libc++ std::tuple summary provider", + ConstString("^std::__(ndk)?1::tuple<.*>(( )?&)?$"), stl_summary_flags, + true); AddCXXSummary( cpp_category_sp, lldb_private::formatters::LibCxxAtomicSummaryProvider, "libc++ std::atomic summary provider", diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp index 88bdd68ff3011..aebea6ae3569b 100644 --- a/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp @@ -628,7 +628,7 @@ static const clang::LangOptions &GetLangOptions() { g_options.CPlusPlus = true; g_options.CPlusPlus11 = true; g_options.CPlusPlus14 = true; - g_options.CPlusPlus1z = true; + g_options.CPlusPlus17 = true; }); return g_options; } diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/source/Plugins/Language/CPlusPlus/LibCxx.cpp index 11245e1310b77..f6d1f18cb596b 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -153,12 +153,11 @@ bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() { .get(); if (m_pair_ptr) { auto __i_(valobj_sp->GetChildMemberWithName(g___i_, true)); - lldb::TemplateArgumentKind kind; if (!__i_) { m_pair_ptr = nullptr; return false; } - CompilerType pair_type(__i_->GetCompilerType().GetTemplateArgument(0, kind)); + CompilerType pair_type(__i_->GetCompilerType().GetTypeTemplateArgument(0)); std::string name; uint64_t bit_offset_ptr; uint32_t bitfield_bit_size_ptr; bool is_bitfield_ptr; pair_type = pair_type.GetFieldAtIndex(0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr); if (!pair_type) { diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.h b/source/Plugins/Language/CPlusPlus/LibCxx.h index 7610212b4245a..3f6e0d6e14d7f 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -93,6 +93,10 @@ private: }; SyntheticChildrenFrontEnd * +LibcxxBitsetSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + +SyntheticChildrenFrontEnd * LibcxxSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); @@ -105,6 +109,10 @@ LibcxxStdListSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); SyntheticChildrenFrontEnd * +LibcxxStdForwardListSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + +SyntheticChildrenFrontEnd * LibcxxStdMapSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); @@ -119,6 +127,12 @@ LibcxxInitializerListSyntheticFrontEndCreator(CXXSyntheticChildren *, SyntheticChildrenFrontEnd *LibcxxFunctionFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); +SyntheticChildrenFrontEnd *LibcxxQueueFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + +SyntheticChildrenFrontEnd *LibcxxTupleFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + } // namespace formatters } // namespace lldb_private diff --git a/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp new file mode 100644 index 0000000000000..0cdb0b26cf3bd --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp @@ -0,0 +1,107 @@ +//===-- LibCxxBitset.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LibCxx.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { + +class BitsetFrontEnd : public SyntheticChildrenFrontEnd { +public: + BitsetFrontEnd(ValueObject &valobj); + + size_t GetIndexOfChildWithName(const ConstString &name) override { + return formatters::ExtractIndexFromString(name.GetCString()); + } + + bool MightHaveChildren() override { return true; } + bool Update() override; + size_t CalculateNumChildren() override { return m_elements.size(); } + ValueObjectSP GetChildAtIndex(size_t idx) override; + +private: + std::vector<ValueObjectSP> m_elements; + ValueObjectSP m_first; + CompilerType m_bool_type; + ByteOrder m_byte_order = eByteOrderInvalid; + uint8_t m_byte_size = 0; +}; +} // namespace + +BitsetFrontEnd::BitsetFrontEnd(ValueObject &valobj) + : SyntheticChildrenFrontEnd(valobj) { + m_bool_type = valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeBool); + if (auto target_sp = m_backend.GetTargetSP()) { + m_byte_order = target_sp->GetArchitecture().GetByteOrder(); + m_byte_size = target_sp->GetArchitecture().GetAddressByteSize(); + Update(); + } +} + +bool BitsetFrontEnd::Update() { + m_elements.clear(); + m_first.reset(); + + TargetSP target_sp = m_backend.GetTargetSP(); + if (!target_sp) + return false; + size_t capping_size = target_sp->GetMaximumNumberOfChildrenToDisplay(); + + size_t size = 0; + if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0)) + size = arg->value.getLimitedValue(capping_size); + + m_elements.assign(size, ValueObjectSP()); + + m_first = m_backend.GetChildMemberWithName(ConstString("__first_"), true); + return false; +} + +ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) { + if (idx >= m_elements.size() || !m_first) + return ValueObjectSP(); + + if (m_elements[idx]) + return m_elements[idx]; + + ExecutionContext ctx = m_backend.GetExecutionContextRef().Lock(false); + CompilerType type; + ValueObjectSP chunk; + // For small bitsets __first_ is not an array, but a plain size_t. + if (m_first->GetCompilerType().IsArrayType(&type, nullptr, nullptr)) + chunk = m_first->GetChildAtIndex( + idx / type.GetBitSize(ctx.GetBestExecutionContextScope()), true); + else { + type = m_first->GetCompilerType(); + chunk = m_first; + } + if (!type || !chunk) + return ValueObjectSP(); + + size_t chunk_idx = idx % type.GetBitSize(ctx.GetBestExecutionContextScope()); + uint8_t value = !!(chunk->GetValueAsUnsigned(0) & (uint64_t(1) << chunk_idx)); + DataExtractor data(&value, sizeof(value), m_byte_order, m_byte_size); + + m_elements[idx] = CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(), + data, ctx, m_bool_type); + + return m_elements[idx]; +} + +SyntheticChildrenFrontEnd *formatters::LibcxxBitsetSyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new BitsetFrontEnd(*valobj_sp); + return nullptr; +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp index 4e839532afb79..5823f6f3e0382 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp @@ -94,9 +94,8 @@ bool lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: m_start = nullptr; m_num_elements = 0; - lldb::TemplateArgumentKind kind; - m_element_type = m_backend.GetCompilerType().GetTemplateArgument(0, kind); - if (kind != lldb::eTemplateArgumentKindType || !m_element_type.IsValid()) + m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0); + if (!m_element_type.IsValid()) return false; m_element_size = m_element_type.GetByteSize(nullptr); diff --git a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp index 56d8edaba72ac..6407ae129ad7d 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp @@ -114,58 +114,90 @@ private: ListEntry m_entry; }; -} // end anonymous namespace - -namespace lldb_private { -namespace formatters { -class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd { +class AbstractListFrontEnd : public SyntheticChildrenFrontEnd { public: - LibcxxStdListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + size_t GetIndexOfChildWithName(const ConstString &name) override { + return ExtractIndexFromString(name.GetCString()); + } + bool MightHaveChildren() override { return true; } + bool Update() override; - ~LibcxxStdListSyntheticFrontEnd() override = default; +protected: + AbstractListFrontEnd(ValueObject &valobj) + : SyntheticChildrenFrontEnd(valobj) {} - size_t CalculateNumChildren() override; + size_t m_count; + ValueObject *m_head; - lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; + static constexpr bool g_use_loop_detect = true; + size_t m_loop_detected; // The number of elements that have had loop detection + // run over them. + ListEntry m_slow_runner; // Used for loop detection + ListEntry m_fast_runner; // Used for loop detection + + size_t m_list_capping_size; + CompilerType m_element_type; + std::map<size_t, ListIterator> m_iterators; + + bool HasLoop(size_t count); + ValueObjectSP GetItem(size_t idx); +}; +class ForwardListFrontEnd : public AbstractListFrontEnd { +public: + ForwardListFrontEnd(ValueObject &valobj); + + size_t CalculateNumChildren() override; + ValueObjectSP GetChildAtIndex(size_t idx) override; bool Update() override; +}; - bool MightHaveChildren() override; +class ListFrontEnd : public AbstractListFrontEnd { +public: + ListFrontEnd(lldb::ValueObjectSP valobj_sp); - size_t GetIndexOfChildWithName(const ConstString &name) override; + ~ListFrontEnd() override = default; -private: - bool HasLoop(size_t count); + size_t CalculateNumChildren() override; - size_t m_list_capping_size; - static const bool g_use_loop_detect = true; + lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; - size_t m_loop_detected; // The number of elements that have had loop detection - // run over them. - ListEntry m_slow_runner; // Used for loop detection - ListEntry m_fast_runner; // Used for loop detection + bool Update() override; +private: lldb::addr_t m_node_address; - ValueObject *m_head; ValueObject *m_tail; - CompilerType m_element_type; - size_t m_count; - std::map<size_t, ListIterator> m_iterators; }; -} // namespace formatters -} // namespace lldb_private - -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: - LibcxxStdListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) - : SyntheticChildrenFrontEnd(*valobj_sp), m_list_capping_size(0), - m_loop_detected(0), m_node_address(), m_head(nullptr), m_tail(nullptr), - m_element_type(), m_count(UINT32_MAX), m_iterators() { - if (valobj_sp) - Update(); + +} // end anonymous namespace + +bool AbstractListFrontEnd::Update() { + m_loop_detected = 0; + m_count = UINT32_MAX; + m_head = nullptr; + m_list_capping_size = 0; + m_slow_runner.SetEntry(nullptr); + m_fast_runner.SetEntry(nullptr); + m_iterators.clear(); + + if (m_backend.GetTargetSP()) + m_list_capping_size = + m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); + if (m_list_capping_size == 0) + m_list_capping_size = 255; + + CompilerType list_type = m_backend.GetCompilerType(); + if (list_type.IsReferenceType()) + list_type = list_type.GetNonReferenceType(); + + if (list_type.GetNumTemplateArguments() == 0) + return false; + m_element_type = list_type.GetTypeTemplateArgument(0); + + return false; } -bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop( - size_t count) { +bool AbstractListFrontEnd::HasLoop(size_t count) { if (!g_use_loop_detect) return false; // don't bother checking for a loop if we won't actually need to jump nodes @@ -201,8 +233,105 @@ bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop( return m_slow_runner == m_fast_runner; } -size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: - CalculateNumChildren() { +ValueObjectSP AbstractListFrontEnd::GetItem(size_t idx) { + size_t advance = idx; + ListIterator current(m_head); + if (idx > 0) { + auto cached_iterator = m_iterators.find(idx - 1); + if (cached_iterator != m_iterators.end()) { + current = cached_iterator->second; + advance = 1; + } + } + ValueObjectSP value_sp = current.advance(advance); + m_iterators[idx] = current; + return value_sp; +} + +ForwardListFrontEnd::ForwardListFrontEnd(ValueObject &valobj) + : AbstractListFrontEnd(valobj) { + Update(); +} + +size_t ForwardListFrontEnd::CalculateNumChildren() { + if (m_count != UINT32_MAX) + return m_count; + + ListEntry current(m_head); + m_count = 0; + while (current && m_count < m_list_capping_size) { + ++m_count; + current = current.next(); + } + return m_count; +} + +ValueObjectSP ForwardListFrontEnd::GetChildAtIndex(size_t idx) { + if (idx >= CalculateNumChildren()) + return nullptr; + + if (!m_head) + return nullptr; + + if (HasLoop(idx + 1)) + return nullptr; + + ValueObjectSP current_sp = GetItem(idx); + if (!current_sp) + return nullptr; + + current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child + if (!current_sp) + return nullptr; + + // we need to copy current_sp into a new object otherwise we will end up with + // all items named __value_ + DataExtractor data; + Status error; + current_sp->GetData(data, error); + if (error.Fail()) + return nullptr; + + return CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(), data, + m_backend.GetExecutionContextRef(), + m_element_type); +} + +static ValueObjectSP GetValueOfCompressedPair(ValueObject &pair) { + ValueObjectSP value = pair.GetChildMemberWithName(ConstString("__value_"), true); + if (! value) { + // pre-r300140 member name + value = pair.GetChildMemberWithName(ConstString("__first_"), true); + } + return value; +} + +bool ForwardListFrontEnd::Update() { + AbstractListFrontEnd::Update(); + + Status err; + ValueObjectSP backend_addr(m_backend.AddressOf(err)); + if (err.Fail() || !backend_addr) + return false; + + ValueObjectSP impl_sp( + m_backend.GetChildMemberWithName(ConstString("__before_begin_"), true)); + if (!impl_sp) + return false; + impl_sp = GetValueOfCompressedPair(*impl_sp); + if (!impl_sp) + return false; + m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get(); + return false; +} + +ListFrontEnd::ListFrontEnd(lldb::ValueObjectSP valobj_sp) + : AbstractListFrontEnd(*valobj_sp), m_node_address(), m_tail(nullptr) { + if (valobj_sp) + Update(); +} + +size_t ListFrontEnd::CalculateNumChildren() { if (m_count != UINT32_MAX) return m_count; if (!m_head || !m_tail || m_node_address == 0) @@ -210,10 +339,9 @@ size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: ValueObjectSP size_alloc( m_backend.GetChildMemberWithName(ConstString("__size_alloc_"), true)); if (size_alloc) { - ValueObjectSP first( - size_alloc->GetChildMemberWithName(ConstString("__first_"), true)); - if (first) { - m_count = first->GetValueAsUnsigned(UINT32_MAX); + ValueObjectSP value = GetValueOfCompressedPair(*size_alloc); + if (value) { + m_count = value->GetValueAsUnsigned(UINT32_MAX); } } if (m_count != UINT32_MAX) { @@ -239,9 +367,7 @@ size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: } } -lldb::ValueObjectSP -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex( - size_t idx) { +lldb::ValueObjectSP ListFrontEnd::GetChildAtIndex(size_t idx) { static ConstString g_value("__value_"); static ConstString g_next("__next_"); @@ -254,23 +380,10 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex( if (HasLoop(idx + 1)) return lldb::ValueObjectSP(); - size_t actual_advance = idx; - - ListIterator current(m_head); - if (idx > 0) { - auto cached_iterator = m_iterators.find(idx - 1); - if (cached_iterator != m_iterators.end()) { - current = cached_iterator->second; - actual_advance = 1; - } - } - - ValueObjectSP current_sp(current.advance(actual_advance)); + ValueObjectSP current_sp = GetItem(idx); if (!current_sp) return lldb::ValueObjectSP(); - m_iterators[idx] = current; - current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child if (!current_sp) return lldb::ValueObjectSP(); @@ -303,23 +416,13 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex( m_element_type); } -bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update() { - m_iterators.clear(); - m_head = m_tail = nullptr; +bool ListFrontEnd::Update() { + AbstractListFrontEnd::Update(); + m_tail = nullptr; m_node_address = 0; - m_count = UINT32_MAX; - m_loop_detected = 0; - m_slow_runner.SetEntry(nullptr); - m_fast_runner.SetEntry(nullptr); Status err; ValueObjectSP backend_addr(m_backend.AddressOf(err)); - m_list_capping_size = 0; - if (m_backend.GetTargetSP()) - m_list_capping_size = - m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); - if (m_list_capping_size == 0) - m_list_capping_size = 255; if (err.Fail() || !backend_addr) return false; m_node_address = backend_addr->GetValueAsUnsigned(0); @@ -329,31 +432,18 @@ bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update() { m_backend.GetChildMemberWithName(ConstString("__end_"), true)); if (!impl_sp) return false; - CompilerType list_type = m_backend.GetCompilerType(); - if (list_type.IsReferenceType()) - list_type = list_type.GetNonReferenceType(); - - if (list_type.GetNumTemplateArguments() == 0) - return false; - lldb::TemplateArgumentKind kind; - m_element_type = list_type.GetTemplateArgument(0, kind); m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get(); m_tail = impl_sp->GetChildMemberWithName(ConstString("__prev_"), true).get(); return false; } -bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: - MightHaveChildren() { - return true; -} - -size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: - GetIndexOfChildWithName(const ConstString &name) { - return ExtractIndexFromString(name.GetCString()); +SyntheticChildrenFrontEnd *formatters::LibcxxStdListSyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + return (valobj_sp ? new ListFrontEnd(valobj_sp) : nullptr); } SyntheticChildrenFrontEnd * -lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator( +formatters::LibcxxStdForwardListSyntheticFrontEndCreator( CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { - return (valobj_sp ? new LibcxxStdListSyntheticFrontEnd(valobj_sp) : nullptr); + return valobj_sp ? new ForwardListFrontEnd(*valobj_sp) : nullptr; } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp index b7215dbcbb485..be96a6d95bcd5 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp @@ -268,13 +268,12 @@ bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() { m_element_type = deref->GetCompilerType(); return true; } - lldb::TemplateArgumentKind kind; deref = m_backend.GetChildAtNamePath({g_tree_, g_pair3}); if (!deref) return false; - m_element_type = - deref->GetCompilerType().GetTemplateArgument(1, kind).GetTemplateArgument( - 1, kind); + m_element_type = deref->GetCompilerType() + .GetTypeTemplateArgument(1) + .GetTypeTemplateArgument(1); if (m_element_type) { std::string name; uint64_t bit_offset_ptr; @@ -285,7 +284,7 @@ bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() { m_element_type = m_element_type.GetTypedefedType(); return m_element_type.IsValid(); } else { - m_element_type = m_backend.GetCompilerType().GetTemplateArgument(0, kind); + m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0); return m_element_type.IsValid(); } } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp b/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp new file mode 100644 index 0000000000000..c4e0b66d4272e --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp @@ -0,0 +1,61 @@ +//===-- LibCxxQueue.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LibCxx.h" +#include "lldb/DataFormatters/FormattersHelpers.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { + +class QueueFrontEnd : public SyntheticChildrenFrontEnd { +public: + QueueFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) { + Update(); + } + + size_t GetIndexOfChildWithName(const ConstString &name) override { + return m_container_sp ? m_container_sp->GetIndexOfChildWithName(name) + : UINT32_MAX; + } + + bool MightHaveChildren() override { return true; } + bool Update() override; + + size_t CalculateNumChildren() override { + return m_container_sp ? m_container_sp->GetNumChildren() : 0; + } + + ValueObjectSP GetChildAtIndex(size_t idx) override { + return m_container_sp ? m_container_sp->GetChildAtIndex(idx, true) + : nullptr; + } + +private: + ValueObjectSP m_container_sp; +}; +} // namespace + +bool QueueFrontEnd::Update() { + m_container_sp.reset(); + ValueObjectSP c_sp = m_backend.GetChildMemberWithName(ConstString("c"), true); + if (!c_sp) + return false; + m_container_sp = c_sp->GetSyntheticValue(); + return false; +} + +SyntheticChildrenFrontEnd * +formatters::LibcxxQueueFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new QueueFrontEnd(*valobj_sp); + return nullptr; +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp b/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp new file mode 100644 index 0000000000000..9b412a12f532f --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp @@ -0,0 +1,83 @@ +//===-- LibCxxTuple.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LibCxx.h" +#include "lldb/DataFormatters/FormattersHelpers.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { + +class TupleFrontEnd: public SyntheticChildrenFrontEnd { +public: + TupleFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) { + Update(); + } + + size_t GetIndexOfChildWithName(const ConstString &name) override { + return formatters::ExtractIndexFromString(name.GetCString()); + } + + bool MightHaveChildren() override { return true; } + bool Update() override; + size_t CalculateNumChildren() override { return m_elements.size(); } + ValueObjectSP GetChildAtIndex(size_t idx) override; + +private: + std::vector<ValueObjectSP> m_elements; + ValueObjectSP m_base_sp; +}; +} + +bool TupleFrontEnd::Update() { + m_elements.clear(); + m_base_sp = m_backend.GetChildMemberWithName(ConstString("__base_"), true); + if (! m_base_sp) { + // Pre r304382 name of the base element. + m_base_sp = m_backend.GetChildMemberWithName(ConstString("base_"), true); + } + if (! m_base_sp) + return false; + m_elements.assign(m_base_sp->GetCompilerType().GetNumDirectBaseClasses(), + ValueObjectSP()); + return false; +} + +ValueObjectSP TupleFrontEnd::GetChildAtIndex(size_t idx) { + if (idx >= m_elements.size()) + return ValueObjectSP(); + if (!m_base_sp) + return ValueObjectSP(); + if (m_elements[idx]) + return m_elements[idx]; + + CompilerType holder_type = + m_base_sp->GetCompilerType().GetDirectBaseClassAtIndex(idx, nullptr); + if (!holder_type) + return ValueObjectSP(); + ValueObjectSP holder_sp = m_base_sp->GetChildAtIndex(idx, true); + if (!holder_sp) + return ValueObjectSP(); + + ValueObjectSP elem_sp = holder_sp->GetChildAtIndex(0, true); + if (elem_sp) + m_elements[idx] = + elem_sp->Clone(ConstString(llvm::formatv("[{0}]", idx).str())); + + return m_elements[idx]; +} + +SyntheticChildrenFrontEnd * +formatters::LibcxxTupleFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new TupleFrontEnd(*valobj_sp); + return nullptr; +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index 190b5f64381ea..0f1c2537d651e 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -121,11 +121,10 @@ lldb::ValueObjectSP lldb_private::formatters:: if (!first_sp) return nullptr; m_element_type = first_sp->GetCompilerType(); - lldb::TemplateArgumentKind kind; - m_element_type = m_element_type.GetTemplateArgument(0, kind); + m_element_type = m_element_type.GetTypeTemplateArgument(0); m_element_type = m_element_type.GetPointeeType(); m_node_type = m_element_type; - m_element_type = m_element_type.GetTemplateArgument(0, kind); + m_element_type = m_element_type.GetTypeTemplateArgument(0); std::string name; m_element_type = m_element_type.GetFieldAtIndex(0, name, nullptr, nullptr, nullptr); diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp index 6f601c9f6ccbf..711130639cd2f 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp @@ -290,8 +290,7 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator( CompilerType type = valobj_sp->GetCompilerType(); if (!type.IsValid() || type.GetNumTemplateArguments() == 0) return nullptr; - TemplateArgumentKind kind; - CompilerType arg_type = type.GetTemplateArgument(0, kind); + CompilerType arg_type = type.GetTypeTemplateArgument(0); if (arg_type.GetTypeName() == ConstString("bool")) return new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp); return new LibcxxStdVectorSyntheticFrontEnd(valobj_sp); diff --git a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp index e3018a1884be1..3e2b7159f8944 100644 --- a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp +++ b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp @@ -117,11 +117,8 @@ bool LibstdcppMapIteratorSyntheticFrontEnd::Update() { CompilerType my_type(valobj_sp->GetCompilerType()); if (my_type.GetNumTemplateArguments() >= 1) { - TemplateArgumentKind kind; - CompilerType pair_type = my_type.GetTemplateArgument(0, kind); - if (kind != eTemplateArgumentKindType && - kind != eTemplateArgumentKindTemplate && - kind != eTemplateArgumentKindTemplateExpansion) + CompilerType pair_type = my_type.GetTypeTemplateArgument(0); + if (!pair_type) return false; m_pair_type = pair_type; } else diff --git a/source/Plugins/Language/ObjC/CMakeLists.txt b/source/Plugins/Language/ObjC/CMakeLists.txt index 7cc93c7b05580..95ace3a3633ab 100644 --- a/source/Plugins/Language/ObjC/CMakeLists.txt +++ b/source/Plugins/Language/ObjC/CMakeLists.txt @@ -1,3 +1,13 @@ +set(EXTRA_CXXFLAGS "") + +if (CXX_SUPPORTS_NO_GNU_ANONYMOUS_STRUCT) + set(EXTRA_CXXFLAGS ${EXTRA_CXXFLAGS} -Wno-gnu-anonymous-struct) +endif () + +if (CXX_SUPPORTS_NO_NESTED_ANON_TYPES) + set(EXTRA_CXXFLAGS ${EXTRA_CXXFLAGS} -Wno-nested-anon-types) +endif () + add_lldb_library(lldbPluginObjCLanguage PLUGIN ObjCLanguage.cpp CF.cpp @@ -21,4 +31,6 @@ add_lldb_library(lldbPluginObjCLanguage PLUGIN lldbTarget lldbUtility lldbPluginAppleObjCRuntime + + EXTRA_CXXFLAGS ${EXTRA_CXXFLAGS} ) diff --git a/source/Plugins/Language/ObjC/NSArray.cpp b/source/Plugins/Language/ObjC/NSArray.cpp index 27cb9558c482d..f6d1592019511 100644 --- a/source/Plugins/Language/ObjC/NSArray.cpp +++ b/source/Plugins/Language/ObjC/NSArray.cpp @@ -48,11 +48,11 @@ NSArray_Additionals::GetAdditionalSynthetics() { return g_map; } -class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { +class NSArrayMSyntheticFrontEndBase : public SyntheticChildrenFrontEnd { public: - NSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + NSArrayMSyntheticFrontEndBase(lldb::ValueObjectSP valobj_sp); - ~NSArrayMSyntheticFrontEnd() override = default; + ~NSArrayMSyntheticFrontEndBase() override = default; size_t CalculateNumChildren() override; @@ -78,11 +78,12 @@ protected: CompilerType m_id_type; }; -class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd { +template <typename D32, typename D64> +class GenericNSArrayMSyntheticFrontEnd : public NSArrayMSyntheticFrontEndBase { public: - NSArrayMSyntheticFrontEnd_109(lldb::ValueObjectSP valobj_sp); + GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); - ~NSArrayMSyntheticFrontEnd_109() override; + ~GenericNSArrayMSyntheticFrontEnd() override; bool Update() override; @@ -96,6 +97,11 @@ protected: uint64_t GetSize() override; private: + D32 *m_data_32; + D64 *m_data_64; +}; + +namespace Foundation109 { struct DataDescriptor_32 { uint32_t _used; uint32_t _priv1 : 2; @@ -105,7 +111,7 @@ private: uint32_t _priv3; uint32_t _data; }; - + struct DataDescriptor_64 { uint64_t _used; uint64_t _priv1 : 2; @@ -115,29 +121,12 @@ private: uint32_t _priv3; uint64_t _data; }; - - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; -}; - -class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd { -public: - NSArrayMSyntheticFrontEnd_1010(lldb::ValueObjectSP valobj_sp); - - ~NSArrayMSyntheticFrontEnd_1010() override; - - bool Update() override; - -protected: - lldb::addr_t GetDataAddress() override; - - uint64_t GetUsedCount() override; - - uint64_t GetOffset() override; - - uint64_t GetSize() override; - -private: + + using NSArrayMSyntheticFrontEnd = + GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; +} + +namespace Foundation1010 { struct DataDescriptor_32 { uint32_t _used; uint32_t _offset; @@ -146,7 +135,7 @@ private: uint32_t _priv2; uint32_t _data; }; - + struct DataDescriptor_64 { uint64_t _used; uint64_t _offset; @@ -155,76 +144,86 @@ private: uint32_t _priv2; uint64_t _data; }; - - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; -}; - -class NSArrayMSyntheticFrontEnd_1400 : public NSArrayMSyntheticFrontEnd { -public: - NSArrayMSyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp); - - ~NSArrayMSyntheticFrontEnd_1400() override; - - bool Update() override; - -protected: - lldb::addr_t GetDataAddress() override; - - uint64_t GetUsedCount() override; - - uint64_t GetOffset() override; - - uint64_t GetSize() override; - -private: + + using NSArrayMSyntheticFrontEnd = + GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; +} + +namespace Foundation1428 { struct DataDescriptor_32 { - uint32_t used; - uint32_t offset; - uint32_t size; - uint32_t list; + uint32_t _used; + uint32_t _offset; + uint32_t _size; + uint32_t _data; }; - + struct DataDescriptor_64 { - uint64_t used; - uint64_t offset; - uint64_t size; - uint64_t list; + uint64_t _used; + uint64_t _offset; + uint64_t _size; + uint64_t _data; }; + + using NSArrayMSyntheticFrontEnd = + GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; +} + +namespace Foundation1437 { + template <typename PtrType> + struct DataDescriptor { + PtrType _cow; + // __deque + PtrType _data; + uint32_t _offset; + uint32_t _size; + union { + PtrType _mutations; + struct { + uint32_t _muts; + uint32_t _used; + }; + }; + }; + + using NSArrayMSyntheticFrontEnd = + GenericNSArrayMSyntheticFrontEnd< + DataDescriptor<uint32_t>, DataDescriptor<uint64_t>>; + + template <typename DD> + uint64_t + __NSArrayMSize_Impl(lldb_private::Process &process, + lldb::addr_t valobj_addr, Status &error) { + const lldb::addr_t start_of_descriptor = + valobj_addr + process.GetAddressByteSize(); + DD descriptor = DD(); + process.ReadMemory(start_of_descriptor, &descriptor, + sizeof(descriptor), error); + if (error.Fail()) { + return 0; + } + return descriptor._used; + } + + uint64_t + __NSArrayMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + if (process.GetAddressByteSize() == 4) { + return __NSArrayMSize_Impl<DataDescriptor<uint32_t>>(process, valobj_addr, + error); + } else { + return __NSArrayMSize_Impl<DataDescriptor<uint64_t>>(process, valobj_addr, + error); + } + } - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; -}; - -class NSArrayISyntheticFrontEnd_1300 : public SyntheticChildrenFrontEnd { -public: - NSArrayISyntheticFrontEnd_1300(lldb::ValueObjectSP valobj_sp); - - ~NSArrayISyntheticFrontEnd_1300() override = default; - - size_t CalculateNumChildren() override; - - lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; - - bool Update() override; - - bool MightHaveChildren() override; - - size_t GetIndexOfChildWithName(const ConstString &name) override; - -private: - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - uint64_t m_items; - lldb::addr_t m_data_ptr; - CompilerType m_id_type; -}; +} -class NSArrayISyntheticFrontEnd_1400 : public SyntheticChildrenFrontEnd { +template <typename D32, typename D64, bool Inline> +class GenericNSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: - NSArrayISyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp); + GenericNSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); - ~NSArrayISyntheticFrontEnd_1400() override; + ~GenericNSArrayISyntheticFrontEnd() override; size_t CalculateNumChildren() override; @@ -239,25 +238,58 @@ public: private: ExecutionContextRef m_exe_ctx_ref; uint8_t m_ptr_size; - - struct DataDescriptor_32 { - uint32_t used; - uint32_t offset; - uint32_t size; - uint32_t list; - }; - - struct DataDescriptor_64 { - uint64_t used; - uint64_t offset; - uint64_t size; - uint64_t list; - }; - - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; + + D32 *m_data_32; + D64 *m_data_64; CompilerType m_id_type; }; + +namespace Foundation1300 { + struct IDD32 { + uint32_t used; + uint32_t list; + }; + + struct IDD64 { + uint64_t used; + uint64_t list; + }; + + using NSArrayISyntheticFrontEnd = + GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, true>; +} + +namespace Foundation1430 { + using NSArrayISyntheticFrontEnd = + Foundation1428::NSArrayMSyntheticFrontEnd; +} + +namespace Foundation1436 { + struct IDD32 { + uint32_t used; + uint32_t list; // in Inline cases, this is the first element + }; + + struct IDD64 { + uint64_t used; + uint64_t list; // in Inline cases, this is the first element + }; + + using NSArrayI_TransferSyntheticFrontEnd = + GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, false>; + + using NSArrayISyntheticFrontEnd = + GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, true>; + + using NSFrozenArrayMSyntheticFrontEnd = + Foundation1437::NSArrayMSyntheticFrontEnd; + + uint64_t + __NSFrozenArrayMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + return Foundation1437::__NSArrayMSize(process, valobj_addr, error); + } +} class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: @@ -329,6 +361,8 @@ bool lldb_private::formatters::NSArraySummaryProvider( static const ConstString g_NSArrayI("__NSArrayI"); static const ConstString g_NSArrayM("__NSArrayM"); + static const ConstString g_NSArrayI_Transfer("__NSArrayI_Transfer"); + static const ConstString g_NSFrozenArrayM("__NSFrozenArrayM"); static const ConstString g_NSArray0("__NSArray0"); static const ConstString g_NSArray1("__NSSingleObjectArrayI"); static const ConstString g_NSArrayCF("__NSCFArray"); @@ -345,11 +379,28 @@ bool lldb_private::formatters::NSArraySummaryProvider( if (error.Fail()) return false; } else if (class_name == g_NSArrayM) { + AppleObjCRuntime *apple_runtime = + llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); + Status error; + if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { + value = Foundation1437::__NSArrayMSize(*process_sp, valobj_addr, error); + } else { + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + } + if (error.Fail()) + return false; + } else if (class_name == g_NSArrayI_Transfer) { Status error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); if (error.Fail()) return false; + } else if (class_name == g_NSFrozenArrayM) { + Status error; + value = Foundation1436::__NSFrozenArrayMSize(*process_sp, valobj_addr, error); + if (error.Fail()) + return false; } else if (class_name == g_NSArrayMLegacy) { Status error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, @@ -395,7 +446,7 @@ bool lldb_private::formatters::NSArraySummaryProvider( return true; } -lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd( +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::NSArrayMSyntheticFrontEndBase( lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_id_type() { @@ -411,28 +462,20 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd( } } -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109:: - NSArrayMSyntheticFrontEnd_109(lldb::ValueObjectSP valobj_sp) - : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr), - m_data_64(nullptr) {} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010:: - NSArrayMSyntheticFrontEnd_1010(lldb::ValueObjectSP valobj_sp) - : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr), - m_data_64(nullptr) {} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400:: - NSArrayMSyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp) - : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr), +template <typename D32, typename D64> +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) + : NSArrayMSyntheticFrontEndBase(valobj_sp), m_data_32(nullptr), m_data_64(nullptr) {} size_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren() { +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::CalculateNumChildren() { return GetUsedCount(); } lldb::ValueObjectSP -lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex( +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetChildAtIndex( size_t idx) { if (idx >= CalculateNumChildren()) return lldb::ValueObjectSP(); @@ -448,69 +491,10 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex( m_exe_ctx_ref, m_id_type); } -bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::Update() { - ValueObjectSP valobj_sp = m_backend.GetSP(); - m_ptr_size = 0; - delete m_data_32; - m_data_32 = nullptr; - delete m_data_64; - m_data_64 = nullptr; - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Status error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), - error); - } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), - error); - } - if (error.Fail()) - return false; - return false; -} - -bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update() { - ValueObjectSP valobj_sp = m_backend.GetSP(); - m_ptr_size = 0; - delete m_data_32; - m_data_32 = nullptr; - delete m_data_64; - m_data_64 = nullptr; - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Status error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), - error); - } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), - error); - } - if (error.Fail()) - return false; - return false; -} - -bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::Update() { +template <typename D32, typename D64> +bool +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>::Update() { ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; delete m_data_32; @@ -528,12 +512,12 @@ bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::Update() { m_ptr_size = process_sp->GetAddressByteSize(); uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), + m_data_32 = new D32(); + process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), error); } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), + m_data_64 = new D64(); + process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), error); } if (error.Fail()) @@ -541,12 +525,13 @@ bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::Update() { return false; } -bool lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren() { +bool +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::MightHaveChildren() { return true; } size_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName( +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetIndexOfChildWithName( const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); @@ -555,187 +540,59 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName( return idx; } -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109:: - ~NSArrayMSyntheticFrontEnd_109() { +template <typename D32, typename D64> +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + ~GenericNSArrayMSyntheticFrontEnd() { delete m_data_32; m_data_32 = nullptr; delete m_data_64; m_data_64 = nullptr; } +template <typename D32, typename D64> lldb::addr_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress() { +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd::GetDataAddress() { if (!m_data_32 && !m_data_64) return LLDB_INVALID_ADDRESS; return m_data_32 ? m_data_32->_data : m_data_64->_data; } +template <typename D32, typename D64> uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetUsedCount() { +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd::GetUsedCount() { if (!m_data_32 && !m_data_64) return 0; return m_data_32 ? m_data_32->_used : m_data_64->_used; } -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetOffset() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_offset : m_data_64->_offset; -} - -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_size : m_data_64->_size; -} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010:: - ~NSArrayMSyntheticFrontEnd_1010() { - delete m_data_32; - m_data_32 = nullptr; - delete m_data_64; - m_data_64 = nullptr; -} - -lldb::addr_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetDataAddress() { - if (!m_data_32 && !m_data_64) - return LLDB_INVALID_ADDRESS; - return m_data_32 ? m_data_32->_data : m_data_64->_data; -} - +template <typename D32, typename D64> uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetUsedCount() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_used : m_data_64->_used; -} - -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetOffset() { +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd::GetOffset() { if (!m_data_32 && !m_data_64) return 0; return m_data_32 ? m_data_32->_offset : m_data_64->_offset; } -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_size : m_data_64->_size; -} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400:: - ~NSArrayMSyntheticFrontEnd_1400() { - delete m_data_32; - m_data_32 = nullptr; - delete m_data_64; - m_data_64 = nullptr; -} - -lldb::addr_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetDataAddress() { - if (!m_data_32 && !m_data_64) - return LLDB_INVALID_ADDRESS; - return m_data_32 ? m_data_32->list : m_data_64->list; -} - +template <typename D32, typename D64> uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetUsedCount() { +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd::GetSize() { if (!m_data_32 && !m_data_64) return 0; - return m_data_32 ? m_data_32->used : m_data_64->used; -} - -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetOffset() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->offset : m_data_64->offset; -} - -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetSize() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->size : m_data_64->size; -} - - -lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::NSArrayISyntheticFrontEnd_1300( - lldb::ValueObjectSP valobj_sp) - : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), - m_items(0), m_data_ptr(0) { - if (valobj_sp) { - CompilerType type = valobj_sp->GetCompilerType(); - if (type) { - ClangASTContext *ast = valobj_sp->GetExecutionContextRef() - .GetTargetSP() - ->GetScratchClangASTContext(); - if (ast) - m_id_type = CompilerType(ast->getASTContext(), - ast->getASTContext()->ObjCBuiltinIdTy); - } - } -} - -size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetIndexOfChildWithName( - const ConstString &name) { - const char *item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; -} - -size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::CalculateNumChildren() { - return m_items; -} - -bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::Update() { - m_ptr_size = 0; - m_items = 0; - m_data_ptr = 0; - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Status error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - m_items = process_sp->ReadPointerFromMemory(data_location, error); - if (error.Fail()) - return false; - m_data_ptr = data_location + m_ptr_size; - return false; -} - -bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::MightHaveChildren() { - return true; -} - -lldb::ValueObjectSP -lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetChildAtIndex( - size_t idx) { - if (idx >= CalculateNumChildren()) - return lldb::ValueObjectSP(); - lldb::addr_t object_at_idx = m_data_ptr; - object_at_idx += (idx * m_ptr_size); - ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); - if (!process_sp) - return lldb::ValueObjectSP(); - Status error; - if (error.Fail()) - return lldb::ValueObjectSP(); - StreamString idx_name; - idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - return CreateValueObjectFromAddress(idx_name.GetString(), object_at_idx, - m_exe_ctx_ref, m_id_type); + return m_data_32 ? m_data_32->_size : m_data_64->_size; } -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::NSArrayISyntheticFrontEnd_1400( +template <typename D32, typename D64, bool Inline> +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + GenericNSArrayISyntheticFrontEnd( lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_data_32(nullptr), m_data_64(nullptr) { @@ -752,16 +609,19 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::NSArrayISyntheticFront } } -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::~NSArrayISyntheticFrontEnd_1400() { +template <typename D32, typename D64, bool Inline> +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + ~GenericNSArrayISyntheticFrontEnd() { delete m_data_32; m_data_32 = nullptr; delete m_data_64; m_data_64 = nullptr; } +template <typename D32, typename D64, bool Inline> size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetIndexOfChildWithName( - const ConstString &name) { +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + GetIndexOfChildWithName(const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); if (idx < UINT32_MAX && idx >= CalculateNumChildren()) @@ -769,12 +629,17 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetIndexOfChildWithNam return idx; } +template <typename D32, typename D64, bool Inline> size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::CalculateNumChildren() { +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + CalculateNumChildren() { return m_data_32 ? m_data_32->used : m_data_64->used; } -bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::Update() { +template <typename D32, typename D64, bool Inline> +bool +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + Update() { ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; delete m_data_32; @@ -792,12 +657,12 @@ bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::Update() { m_ptr_size = process_sp->GetAddressByteSize(); uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), + m_data_32 = new D32(); + process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), error); } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), + m_data_64 = new D64(); + process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), error); } if (error.Fail()) @@ -805,17 +670,29 @@ bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::Update() { return false; } -bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::MightHaveChildren() { +template <typename D32, typename D64, bool Inline> +bool +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + MightHaveChildren() { return true; } +template <typename D32, typename D64, bool Inline> lldb::ValueObjectSP -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetChildAtIndex( - size_t idx) { +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + GetChildAtIndex(size_t idx) { if (idx >= CalculateNumChildren()) return lldb::ValueObjectSP(); - lldb::addr_t object_at_idx = m_data_32 ? m_data_32->list : m_data_64->list; + lldb::addr_t object_at_idx; + if (Inline) { + object_at_idx = m_backend.GetSP()->GetValueAsUnsigned(0) + m_ptr_size; + object_at_idx += m_ptr_size == 4 ? sizeof(D32) : sizeof(D64); // skip the data header + object_at_idx -= m_ptr_size; // we treat the last entry in the data header as the first pointer + } else { + object_at_idx = m_data_32 ? m_data_32->list : m_data_64->list; + } object_at_idx += (idx * m_ptr_size); + ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); if (!process_sp) return lldb::ValueObjectSP(); @@ -933,6 +810,8 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator( ConstString class_name(descriptor->GetClassName()); static const ConstString g_NSArrayI("__NSArrayI"); + static const ConstString g_NSArrayI_Transfer("__NSArrayI_Transfer"); + static const ConstString g_NSFrozenArrayM("__NSFrozenArrayM"); static const ConstString g_NSArrayM("__NSArrayM"); static const ConstString g_NSArray0("__NSArray0"); static const ConstString g_NSArray1("__NSSingleObjectArrayI"); @@ -943,21 +822,30 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator( return nullptr; if (class_name == g_NSArrayI) { - if (runtime->GetFoundationVersion() >= 1400) - return (new NSArrayISyntheticFrontEnd_1400(valobj_sp)); - else - return (new NSArrayISyntheticFrontEnd_1300(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1436) + return (new Foundation1436::NSArrayISyntheticFrontEnd(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1430) + return (new Foundation1430::NSArrayISyntheticFrontEnd(valobj_sp)); + else + return (new Foundation1300::NSArrayISyntheticFrontEnd(valobj_sp)); + } else if (class_name == g_NSArrayI_Transfer) { + return (new Foundation1436::NSArrayI_TransferSyntheticFrontEnd(valobj_sp)); + } else if (class_name == g_NSArray0) { + } else if (class_name == g_NSFrozenArrayM) { + return (new Foundation1436::NSFrozenArrayMSyntheticFrontEnd(valobj_sp)); } else if (class_name == g_NSArray0) { return (new NSArray0SyntheticFrontEnd(valobj_sp)); } else if (class_name == g_NSArray1) { return (new NSArray1SyntheticFrontEnd(valobj_sp)); } else if (class_name == g_NSArrayM) { - if (runtime->GetFoundationVersion() >= 1400) - return (new NSArrayMSyntheticFrontEnd_1400(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1437) + return (new Foundation1437::NSArrayMSyntheticFrontEnd(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1428) + return (new Foundation1428::NSArrayMSyntheticFrontEnd(valobj_sp)); if (runtime->GetFoundationVersion() >= 1100) - return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp)); + return (new Foundation1010::NSArrayMSyntheticFrontEnd(valobj_sp)); else - return (new NSArrayMSyntheticFrontEnd_109(valobj_sp)); + return (new Foundation109::NSArrayMSyntheticFrontEnd(valobj_sp)); } else { auto &map(NSArray_Additionals::GetAdditionalSynthetics()); auto iter = map.find(class_name), end = map.end(); diff --git a/source/Plugins/Language/ObjC/NSDictionary.cpp b/source/Plugins/Language/ObjC/NSDictionary.cpp index 50febbe397583..c564aa1a85715 100644 --- a/source/Plugins/Language/ObjC/NSDictionary.cpp +++ b/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -165,11 +165,12 @@ private: ValueObjectSP m_pair; }; -class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { +template <typename D32, typename D64> +class GenericNSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: - NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); - ~NSDictionaryMSyntheticFrontEnd() override; + ~GenericNSDictionaryMSyntheticFrontEnd() override; size_t CalculateNumChildren() override; @@ -182,20 +183,6 @@ public: size_t GetIndexOfChildWithName(const ConstString &name) override; private: - struct DataDescriptor_32 { - uint32_t used : 26; - uint32_t kvo : 1; - uint32_t size; - uint32_t buffer; - }; - - struct DataDescriptor_64 { - uint64_t used : 58; - uint32_t kvo : 1; - uint64_t size; - uint64_t buffer; - }; - struct DictionaryItemDescriptor { lldb::addr_t key_ptr; lldb::addr_t val_ptr; @@ -205,61 +192,169 @@ private: ExecutionContextRef m_exe_ctx_ref; uint8_t m_ptr_size; lldb::ByteOrder m_order; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; + D32 *m_data_32; + D64 *m_data_64; CompilerType m_pair_type; std::vector<DictionaryItemDescriptor> m_children; }; - -class NSDictionaryMLegacySyntheticFrontEnd : public SyntheticChildrenFrontEnd { -public: - NSDictionaryMLegacySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); - - ~NSDictionaryMLegacySyntheticFrontEnd() override; - - size_t CalculateNumChildren() override; - - lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; - - bool Update() override; - - bool MightHaveChildren() override; - - size_t GetIndexOfChildWithName(const ConstString &name) override; - -private: + +namespace Foundation1100 { + class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { + public: + NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + + ~NSDictionaryMSyntheticFrontEnd() override; + + size_t CalculateNumChildren() override; + + lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; + + bool Update() override; + + bool MightHaveChildren() override; + + size_t GetIndexOfChildWithName(const ConstString &name) override; + + private: + struct DataDescriptor_32 { + uint32_t _used : 26; + uint32_t _kvo : 1; + uint32_t _size; + uint32_t _mutations; + uint32_t _objs_addr; + uint32_t _keys_addr; + }; + + struct DataDescriptor_64 { + uint64_t _used : 58; + uint32_t _kvo : 1; + uint64_t _size; + uint64_t _mutations; + uint64_t _objs_addr; + uint64_t _keys_addr; + }; + + struct DictionaryItemDescriptor { + lldb::addr_t key_ptr; + lldb::addr_t val_ptr; + lldb::ValueObjectSP valobj_sp; + }; + + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + lldb::ByteOrder m_order; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + CompilerType m_pair_type; + std::vector<DictionaryItemDescriptor> m_children; + }; +} + +namespace Foundation1428 { struct DataDescriptor_32 { uint32_t _used : 26; uint32_t _kvo : 1; uint32_t _size; - uint32_t _mutations; - uint32_t _objs_addr; - uint32_t _keys_addr; + uint32_t _buffer; + uint64_t GetSize() { return _size; } }; - + struct DataDescriptor_64 { uint64_t _used : 58; uint32_t _kvo : 1; uint64_t _size; - uint64_t _mutations; - uint64_t _objs_addr; - uint64_t _keys_addr; + uint64_t _buffer; + uint64_t GetSize() { return _size; } }; - - struct DictionaryItemDescriptor { - lldb::addr_t key_ptr; - lldb::addr_t val_ptr; - lldb::ValueObjectSP valobj_sp; + + + + using NSDictionaryMSyntheticFrontEnd = + GenericNSDictionaryMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; +} + +namespace Foundation1437 { + static const uint64_t NSDictionaryCapacities[] = { + 0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723, + 2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607, + 214519, 346607, 561109, 907759, 1468927, 2376191, 3845119, + 6221311, 10066421, 16287743, 26354171, 42641881, 68996069, + 111638519, 180634607, 292272623, 472907251 + }; + + static const size_t NSDictionaryNumSizeBuckets = sizeof(NSDictionaryCapacities) / sizeof(uint64_t); + + struct DataDescriptor_32 { + uint32_t _buffer; + union { + struct { + uint32_t _mutations; + }; + struct { + uint32_t _muts; + uint32_t _used:25; + uint32_t _kvo:1; + uint32_t _szidx:6; + }; + }; + + uint64_t GetSize() { + return (_szidx) >= NSDictionaryNumSizeBuckets ? + 0 : NSDictionaryCapacities[_szidx]; + } }; + + struct DataDescriptor_64 { + uint64_t _buffer; + union { + struct { + uint64_t _mutations; + }; + struct { + uint32_t _muts; + uint32_t _used:25; + uint32_t _kvo:1; + uint32_t _szidx:6; + }; + }; + + uint64_t GetSize() { + return (_szidx) >= NSDictionaryNumSizeBuckets ? + 0 : NSDictionaryCapacities[_szidx]; + } + }; + + using NSDictionaryMSyntheticFrontEnd = + GenericNSDictionaryMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; + + template <typename DD> + uint64_t + __NSDictionaryMSize_Impl(lldb_private::Process &process, + lldb::addr_t valobj_addr, Status &error) { + const lldb::addr_t start_of_descriptor = + valobj_addr + process.GetAddressByteSize(); + DD descriptor = DD(); + process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor), + error); + if (error.Fail()) { + return 0; + } + return descriptor._used; + } + + uint64_t + __NSDictionaryMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + if (process.GetAddressByteSize() == 4) { + return __NSDictionaryMSize_Impl<DataDescriptor_32>(process, valobj_addr, + error); + } else { + return __NSDictionaryMSize_Impl<DataDescriptor_64>(process, valobj_addr, + error); + } + } - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - lldb::ByteOrder m_order; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; - CompilerType m_pair_type; - std::vector<DictionaryItemDescriptor> m_children; -}; +} } // namespace formatters } // namespace lldb_private @@ -313,12 +408,19 @@ bool lldb_private::formatters::NSDictionarySummaryProvider( return false; value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy) { + AppleObjCRuntime *apple_runtime = + llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); Status error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, - ptr_size, 0, error); + if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { + value = Foundation1437::__NSDictionaryMSize(*process_sp, valobj_addr, + error); + } else { + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); + } if (error.Fail()) return false; - value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } else if (class_name == g_Dictionary1) { value = 1; } @@ -396,13 +498,15 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( if (class_name == g_DictionaryI) { return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); } else if (class_name == g_DictionaryM) { - if (runtime->GetFoundationVersion() > 1400) { - return (new NSDictionaryMSyntheticFrontEnd(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1437) { + return (new Foundation1437::NSDictionaryMSyntheticFrontEnd(valobj_sp)); + } else if (runtime->GetFoundationVersion() >= 1428) { + return (new Foundation1428::NSDictionaryMSyntheticFrontEnd(valobj_sp)); } else { - return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp)); + return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp)); } } else if (class_name == g_DictionaryMLegacy) { - return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp)); + return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp)); } else if (class_name == g_Dictionary1) { return (new NSDictionary1SyntheticFrontEnd(valobj_sp)); } else { @@ -641,22 +745,25 @@ lldb_private::formatters::NSDictionary1SyntheticFrontEnd::GetChildAtIndex( return m_pair; } -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: - NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) +template <typename D32, typename D64> +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: + GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_order(lldb::eByteOrderInvalid), m_data_32(nullptr), m_data_64(nullptr), m_pair_type() {} -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: - ~NSDictionaryMSyntheticFrontEnd() { +template <typename D32, typename D64> +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: + ~GenericNSDictionaryMSyntheticFrontEnd() { delete m_data_32; m_data_32 = nullptr; delete m_data_64; m_data_64 = nullptr; } -size_t lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: - GetIndexOfChildWithName(const ConstString &name) { +template <typename D32, typename D64> +size_t +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: GetIndexOfChildWithName(const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); if (idx < UINT32_MAX && idx >= CalculateNumChildren()) @@ -664,14 +771,18 @@ size_t lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: return idx; } -size_t lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: - CalculateNumChildren() { +template <typename D32, typename D64> +size_t +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>::CalculateNumChildren() { if (!m_data_32 && !m_data_64) return 0; - return (m_data_32 ? m_data_32->used : m_data_64->used); + return (m_data_32 ? m_data_32->_used : m_data_64->_used); } -bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() { +template <typename D32, typename D64> +bool +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: + Update() { m_children.clear(); ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; @@ -691,12 +802,12 @@ bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() { m_order = process_sp->GetByteOrder(); uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), + m_data_32 = new D32(); + process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), error); } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), + m_data_64 = new D64(); + process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), error); } if (error.Fail()) @@ -704,24 +815,28 @@ bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() { return false; } -bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: +template <typename D32, typename D64> +bool +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: MightHaveChildren() { return true; } +template <typename D32, typename D64> lldb::ValueObjectSP -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex( +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: + GetChildAtIndex( size_t idx) { lldb::addr_t m_keys_ptr; lldb::addr_t m_values_ptr; if (m_data_32) { - uint32_t size = m_data_32->size; - m_keys_ptr = m_data_32->buffer; - m_values_ptr = m_data_32->buffer + (m_ptr_size * size); + uint32_t size = m_data_32->GetSize(); + m_keys_ptr = m_data_32->_buffer; + m_values_ptr = m_data_32->_buffer + (m_ptr_size * size); } else { - uint32_t size = m_data_64->size; - m_keys_ptr = m_data_64->buffer; - m_values_ptr = m_data_64->buffer + (m_ptr_size * size); + uint32_t size = m_data_64->GetSize(); + m_keys_ptr = m_data_64->_buffer; + m_values_ptr = m_data_64->_buffer + (m_ptr_size * size); } uint32_t num_children = CalculateNumChildren(); @@ -800,22 +915,24 @@ lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex( } -lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - NSDictionaryMLegacySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd:: + NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_order(lldb::eByteOrderInvalid), m_data_32(nullptr), m_data_64(nullptr), m_pair_type() {} -lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - ~NSDictionaryMLegacySyntheticFrontEnd() { +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd() { delete m_data_32; m_data_32 = nullptr; delete m_data_64; m_data_64 = nullptr; } -size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - GetIndexOfChildWithName(const ConstString &name) { +size_t +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName(const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); if (idx < UINT32_MAX && idx >= CalculateNumChildren()) @@ -823,14 +940,17 @@ size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: return idx; } -size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - CalculateNumChildren() { +size_t +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::CalculateNumChildren() { if (!m_data_32 && !m_data_64) return 0; return (m_data_32 ? m_data_32->_used : m_data_64->_used); } -bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::Update() { +bool +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::Update() { m_children.clear(); ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; @@ -863,14 +983,15 @@ bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::Update() { return false; } -bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - MightHaveChildren() { +bool +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::MightHaveChildren() { return true; } lldb::ValueObjectSP -lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::GetChildAtIndex( - size_t idx) { +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::GetChildAtIndex(size_t idx) { lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr); lldb::addr_t m_values_ptr = diff --git a/source/Plugins/Language/ObjC/NSSet.cpp b/source/Plugins/Language/ObjC/NSSet.cpp index 2f33987751699..fa2483ecc0947 100644 --- a/source/Plugins/Language/ObjC/NSSet.cpp +++ b/source/Plugins/Language/ObjC/NSSet.cpp @@ -135,7 +135,7 @@ namespace Foundation1300 { GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; } -namespace Foundation1400 { +namespace Foundation1428 { struct DataDescriptor_32 { uint32_t _used : 26; uint32_t _size; @@ -154,6 +154,64 @@ namespace Foundation1400 { GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; } +namespace Foundation1437 { + struct DataDescriptor_32 { + uint32_t _cow; + // __table storage + uint32_t _objs_addr; + union { + uint32_t _mutations; + struct { + uint32_t _muts; + uint32_t _used : 26; + uint32_t _szidx : 6; + }; + }; + }; + + struct DataDescriptor_64 { + uint64_t _cow; + // __Table storage + uint64_t _objs_addr; + union { + uint64_t _mutations; + struct { + uint32_t _muts; + uint32_t _used : 26; + uint32_t _szidx : 6; + }; + }; + }; + + using NSSetMSyntheticFrontEnd = + GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; + + template <typename DD> + uint64_t + __NSSetMSize_Impl(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + const lldb::addr_t start_of_descriptor = + valobj_addr + process.GetAddressByteSize(); + DD descriptor = DD(); + process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor), + error); + if (error.Fail()) { + return 0; + } + return descriptor._used; + } + + uint64_t + __NSSetMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + if (process.GetAddressByteSize() == 4) { + return __NSSetMSize_Impl<DataDescriptor_32>(process, valobj_addr, error); + } else { + return __NSSetMSize_Impl<DataDescriptor_64>(process, valobj_addr, error); + } + } +} + class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: NSSetCodeRunningSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); @@ -219,12 +277,18 @@ bool lldb_private::formatters::NSSetSummaryProvider( return false; value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } else if (!strcmp(class_name, "__NSSetM")) { + AppleObjCRuntime *apple_runtime = + llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); Status error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, - ptr_size, 0, error); + if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { + value = Foundation1437::__NSSetMSize(*process_sp, valobj_addr, error); + } else { + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); + } if (error.Fail()) return false; - value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } /*else if (!strcmp(class_name,"__NSCFSet")) { @@ -312,10 +376,16 @@ lldb_private::formatters::NSSetSyntheticFrontEndCreator( } else if (!strcmp(class_name, "__NSSetM")) { AppleObjCRuntime *apple_runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); - if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1400) - return (new Foundation1400::NSSetMSyntheticFrontEnd(valobj_sp)); - else + if (apple_runtime) { + if (apple_runtime->GetFoundationVersion() >= 1437) + return (new Foundation1437::NSSetMSyntheticFrontEnd(valobj_sp)); + else if (apple_runtime->GetFoundationVersion() >= 1428) + return (new Foundation1428::NSSetMSyntheticFrontEnd(valobj_sp)); + else + return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp)); + } else { return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp)); + } } else { auto &map(NSSet_Additionals::GetAdditionalSynthetics()); auto iter = map.find(class_name_cs), end = map.end(); |