diff --git a/lldb/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py b/lldb/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py index 57f373545380..96c5a33f14b0 100644 --- a/lldb/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py +++ b/lldb/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py @@ -121,8 +121,6 @@ class ObjCNewSyntaxTestCase(TestBase): '7.0.0']) @skipIf(macos_version=["<", "10.12"]) @expectedFailureAll(archs=["i[3-6]86"]) - @expectedFailureAll( - bugnumber="rdar://32777981") def test_update_dictionary(self): self.runToBreakpoint() @@ -165,8 +163,6 @@ class ObjCNewSyntaxTestCase(TestBase): '7.0.0']) @skipIf(macos_version=["<", "10.12"]) @expectedFailureAll(archs=["i[3-6]86"]) - @expectedFailureAll( - bugnumber="rdar://32777981") def test_dictionary_literal(self): self.runToBreakpoint() diff --git a/lldb/source/Plugins/Language/ObjC/NSArray.cpp b/lldb/source/Plugins/Language/ObjC/NSArray.cpp index b07b9ba5888f..27cb9558c482 100644 --- a/lldb/source/Plugins/Language/ObjC/NSArray.cpp +++ b/lldb/source/Plugins/Language/ObjC/NSArray.cpp @@ -160,11 +160,47 @@ private: DataDescriptor_64 *m_data_64; }; -class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd { +class NSArrayMSyntheticFrontEnd_1400 : public NSArrayMSyntheticFrontEnd { public: - NSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + NSArrayMSyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp); - ~NSArrayISyntheticFrontEnd() override = default; + ~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: + 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; +}; + +class NSArrayISyntheticFrontEnd_1300 : public SyntheticChildrenFrontEnd { +public: + NSArrayISyntheticFrontEnd_1300(lldb::ValueObjectSP valobj_sp); + + ~NSArrayISyntheticFrontEnd_1300() override = default; size_t CalculateNumChildren() override; @@ -184,6 +220,45 @@ private: CompilerType m_id_type; }; +class NSArrayISyntheticFrontEnd_1400 : public SyntheticChildrenFrontEnd { +public: + NSArrayISyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp); + + ~NSArrayISyntheticFrontEnd_1400() 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: + 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; + CompilerType m_id_type; +}; + class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: NSArray0SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); @@ -257,6 +332,8 @@ bool lldb_private::formatters::NSArraySummaryProvider( static const ConstString g_NSArray0("__NSArray0"); static const ConstString g_NSArray1("__NSSingleObjectArrayI"); static const ConstString g_NSArrayCF("__NSCFArray"); + static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy"); + static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable"); if (class_name.IsEmpty()) return false; @@ -273,6 +350,18 @@ bool lldb_private::formatters::NSArraySummaryProvider( ptr_size, 0, error); if (error.Fail()) return false; + } else if (class_name == g_NSArrayMLegacy) { + Status error; + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + if (error.Fail()) + return false; + } else if (class_name == g_NSArrayMImmutable) { + Status error; + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + if (error.Fail()) + return false; } else if (class_name == g_NSArray0) { value = 0; } else if (class_name == g_NSArray1) { @@ -332,6 +421,11 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010:: : 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), + m_data_64(nullptr) {} + size_t lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren() { return GetUsedCount(); @@ -416,6 +510,37 @@ bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update() { return false; } +bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::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::MightHaveChildren() { return true; } @@ -498,7 +623,42 @@ uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize() { return m_data_32 ? m_data_32->_size : m_data_64->_size; } -lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd( +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; +} + +uint64_t +lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::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_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) { @@ -516,7 +676,7 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd( } size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName( +lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetIndexOfChildWithName( const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); @@ -526,11 +686,11 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName( } size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren() { +lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::CalculateNumChildren() { return m_items; } -bool lldb_private::formatters::NSArrayISyntheticFrontEnd::Update() { +bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::Update() { m_ptr_size = 0; m_items = 0; m_data_ptr = 0; @@ -552,12 +712,12 @@ bool lldb_private::formatters::NSArrayISyntheticFrontEnd::Update() { return false; } -bool lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren() { +bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::MightHaveChildren() { return true; } lldb::ValueObjectSP -lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex( +lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetChildAtIndex( size_t idx) { if (idx >= CalculateNumChildren()) return lldb::ValueObjectSP(); @@ -575,6 +735,99 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex( m_exe_ctx_ref, m_id_type); } +lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::NSArrayISyntheticFrontEnd_1400( + lldb::ValueObjectSP valobj_sp) + : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), + m_data_32(nullptr), m_data_64(nullptr) { + 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); + } + } +} + +lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::~NSArrayISyntheticFrontEnd_1400() { + delete m_data_32; + m_data_32 = nullptr; + delete m_data_64; + m_data_64 = nullptr; +} + +size_t +lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::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_1400::CalculateNumChildren() { + return m_data_32 ? m_data_32->used : m_data_64->used; +} + +bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::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::NSArrayISyntheticFrontEnd_1400::MightHaveChildren() { + return true; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::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; + 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); +} + lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd( lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp) {} @@ -683,17 +936,24 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator( static const ConstString g_NSArrayM("__NSArrayM"); static const ConstString g_NSArray0("__NSArray0"); static const ConstString g_NSArray1("__NSSingleObjectArrayI"); + static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy"); + static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable"); if (class_name.IsEmpty()) return nullptr; if (class_name == g_NSArrayI) { - return (new NSArrayISyntheticFrontEnd(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1400) + return (new NSArrayISyntheticFrontEnd_1400(valobj_sp)); + else + return (new NSArrayISyntheticFrontEnd_1300(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() >= 1100) return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp)); else diff --git a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp index 6df83d52acca..50febbe39758 100644 --- a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp +++ b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -17,6 +17,8 @@ // Project includes #include "NSDictionary.h" +#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" + #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/DataFormatters/FormattersHelpers.h" @@ -179,6 +181,52 @@ 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; + 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 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: struct DataDescriptor_32 { uint32_t _used : 26; @@ -250,19 +298,21 @@ bool lldb_private::formatters::NSDictionarySummaryProvider( static const ConstString g_DictionaryI("__NSDictionaryI"); static const ConstString g_DictionaryM("__NSDictionaryM"); + static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy"); + static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable"); static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI"); if (class_name.IsEmpty()) return false; - if (class_name == g_DictionaryI) { + if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) { Status error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); if (error.Fail()) return false; value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); - } else if (class_name == g_DictionaryM) { + } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy) { Status error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); @@ -311,9 +361,8 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); if (!process_sp) return nullptr; - ObjCLanguageRuntime *runtime = - (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime( - lldb::eLanguageTypeObjC); + AppleObjCRuntime *runtime = + llvm::dyn_cast_or_null(process_sp->GetObjCLanguageRuntime()); if (!runtime) return nullptr; @@ -338,6 +387,8 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( static const ConstString g_DictionaryI("__NSDictionaryI"); static const ConstString g_DictionaryM("__NSDictionaryM"); static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI"); + static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable"); + static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy"); if (class_name.IsEmpty()) return nullptr; @@ -345,7 +396,13 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( if (class_name == g_DictionaryI) { return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); } else if (class_name == g_DictionaryM) { - return (new NSDictionaryMSyntheticFrontEnd(valobj_sp)); + if (runtime->GetFoundationVersion() > 1400) { + return (new NSDictionaryMSyntheticFrontEnd(valobj_sp)); + } else { + return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp)); + } + } else if (class_name == g_DictionaryMLegacy) { + return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp)); } else if (class_name == g_Dictionary1) { return (new NSDictionary1SyntheticFrontEnd(valobj_sp)); } else { @@ -611,7 +668,7 @@ size_t lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: 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() { @@ -655,6 +712,165 @@ bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: lldb::ValueObjectSP lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::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); + } 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 num_children = CalculateNumChildren(); + + if (idx >= num_children) + return lldb::ValueObjectSP(); + + if (m_children.empty()) { + // do the scan phase + lldb::addr_t key_at_idx = 0, val_at_idx = 0; + + uint32_t tries = 0; + uint32_t test_idx = 0; + + while (tries < num_children) { + key_at_idx = m_keys_ptr + (test_idx * m_ptr_size); + val_at_idx = m_values_ptr + (test_idx * m_ptr_size); + ; + ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); + if (!process_sp) + return lldb::ValueObjectSP(); + Status error; + key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); + if (error.Fail()) + return lldb::ValueObjectSP(); + val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); + if (error.Fail()) + return lldb::ValueObjectSP(); + + test_idx++; + + if (!key_at_idx || !val_at_idx) + continue; + tries++; + + DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx, + lldb::ValueObjectSP()}; + + m_children.push_back(descriptor); + } + } + + if (idx >= m_children.size()) // should never happen + return lldb::ValueObjectSP(); + + DictionaryItemDescriptor &dict_item = m_children[idx]; + if (!dict_item.valobj_sp) { + if (!m_pair_type.IsValid()) { + TargetSP target_sp(m_backend.GetTargetSP()); + if (!target_sp) + return ValueObjectSP(); + m_pair_type = GetLLDBNSPairType(target_sp); + } + if (!m_pair_type.IsValid()) + return ValueObjectSP(); + + DataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0)); + + if (m_ptr_size == 8) { + uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); + *data_ptr = dict_item.key_ptr; + *(data_ptr + 1) = dict_item.val_ptr; + } else { + uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); + *data_ptr = dict_item.key_ptr; + *(data_ptr + 1) = dict_item.val_ptr; + } + + StreamString idx_name; + idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); + DataExtractor data(buffer_sp, m_order, m_ptr_size); + dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data, + m_exe_ctx_ref, m_pair_type); + } + return dict_item.valobj_sp; +} + + +lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: + NSDictionaryMLegacySyntheticFrontEnd(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() { + 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) { + 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::NSDictionaryMLegacySyntheticFrontEnd:: + 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() { + m_children.clear(); + 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(); + 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), + 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::NSDictionaryMLegacySyntheticFrontEnd:: + MightHaveChildren() { + return true; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::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 =