15ffd83dbSDimitry Andric //===-- NSDictionary.cpp --------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include <mutex> 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 120b57cec5SDimitry Andric 135ffd83dbSDimitry Andric #include "CFBasicHash.h" 140b57cec5SDimitry Andric #include "NSDictionary.h" 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" 175ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h" 200b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResult.h" 210b57cec5SDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h" 220b57cec5SDimitry Andric #include "lldb/Target/Language.h" 230b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h" 240b57cec5SDimitry Andric #include "lldb/Target/Target.h" 250b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h" 260b57cec5SDimitry Andric #include "lldb/Utility/Endian.h" 270b57cec5SDimitry Andric #include "lldb/Utility/Status.h" 280b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric using namespace lldb; 310b57cec5SDimitry Andric using namespace lldb_private; 320b57cec5SDimitry Andric using namespace lldb_private::formatters; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric NSDictionary_Additionals::AdditionalFormatterMatching::Prefix::Prefix( 350b57cec5SDimitry Andric ConstString p) 360b57cec5SDimitry Andric : m_prefix(p) {} 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric bool NSDictionary_Additionals::AdditionalFormatterMatching::Prefix::Match( 390b57cec5SDimitry Andric ConstString class_name) { 405f757f3fSDimitry Andric return class_name.GetStringRef().starts_with(m_prefix.GetStringRef()); 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric NSDictionary_Additionals::AdditionalFormatterMatching::Full::Full(ConstString n) 440b57cec5SDimitry Andric : m_name(n) {} 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric bool NSDictionary_Additionals::AdditionalFormatterMatching::Full::Match( 470b57cec5SDimitry Andric ConstString class_name) { 480b57cec5SDimitry Andric return (class_name == m_name); 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric NSDictionary_Additionals::AdditionalFormatters< 520b57cec5SDimitry Andric CXXFunctionSummaryFormat::Callback> & 530b57cec5SDimitry Andric NSDictionary_Additionals::GetAdditionalSummaries() { 540b57cec5SDimitry Andric static AdditionalFormatters<CXXFunctionSummaryFormat::Callback> g_map; 550b57cec5SDimitry Andric return g_map; 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric NSDictionary_Additionals::AdditionalFormatters< 590b57cec5SDimitry Andric CXXSyntheticChildren::CreateFrontEndCallback> & 600b57cec5SDimitry Andric NSDictionary_Additionals::GetAdditionalSynthetics() { 610b57cec5SDimitry Andric static AdditionalFormatters<CXXSyntheticChildren::CreateFrontEndCallback> 620b57cec5SDimitry Andric g_map; 630b57cec5SDimitry Andric return g_map; 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric static CompilerType GetLLDBNSPairType(TargetSP target_sp) { 670b57cec5SDimitry Andric CompilerType compiler_type; 68bdd1243dSDimitry Andric TypeSystemClangSP scratch_ts_sp = 69e8d8bef9SDimitry Andric ScratchTypeSystemClang::GetForTarget(*target_sp); 700b57cec5SDimitry Andric 7106c3fb27SDimitry Andric if (!scratch_ts_sp) 7206c3fb27SDimitry Andric return compiler_type; 730b57cec5SDimitry Andric 7406c3fb27SDimitry Andric static constexpr llvm::StringLiteral g_lldb_autogen_nspair("__lldb_autogen_nspair"); 7506c3fb27SDimitry Andric 7606c3fb27SDimitry Andric compiler_type = scratch_ts_sp->GetTypeForIdentifier<clang::CXXRecordDecl>(g_lldb_autogen_nspair); 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric if (!compiler_type) { 79bdd1243dSDimitry Andric compiler_type = scratch_ts_sp->CreateRecordType( 805ffd83dbSDimitry Andric nullptr, OptionalClangModuleID(), lldb::eAccessPublic, 815f757f3fSDimitry Andric g_lldb_autogen_nspair, llvm::to_underlying(clang::TagTypeKind::Struct), 825f757f3fSDimitry Andric lldb::eLanguageTypeC); 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric if (compiler_type) { 855ffd83dbSDimitry Andric TypeSystemClang::StartTagDeclarationDefinition(compiler_type); 860b57cec5SDimitry Andric CompilerType id_compiler_type = 87bdd1243dSDimitry Andric scratch_ts_sp->GetBasicType(eBasicTypeObjCID); 885ffd83dbSDimitry Andric TypeSystemClang::AddFieldToRecordType( 890b57cec5SDimitry Andric compiler_type, "key", id_compiler_type, lldb::eAccessPublic, 0); 905ffd83dbSDimitry Andric TypeSystemClang::AddFieldToRecordType( 910b57cec5SDimitry Andric compiler_type, "value", id_compiler_type, lldb::eAccessPublic, 0); 925ffd83dbSDimitry Andric TypeSystemClang::CompleteTagDeclarationDefinition(compiler_type); 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric return compiler_type; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric namespace lldb_private { 990b57cec5SDimitry Andric namespace formatters { 1000b57cec5SDimitry Andric class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd { 1010b57cec5SDimitry Andric public: 1020b57cec5SDimitry Andric NSDictionaryISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric ~NSDictionaryISyntheticFrontEnd() override; 1050b57cec5SDimitry Andric 106*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 1070b57cec5SDimitry Andric 108*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 1090b57cec5SDimitry Andric 110*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric bool MightHaveChildren() override; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric private: 1170b57cec5SDimitry Andric struct DataDescriptor_32 { 1180b57cec5SDimitry Andric uint32_t _used : 26; 1190b57cec5SDimitry Andric uint32_t _szidx : 6; 1200b57cec5SDimitry Andric }; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric struct DataDescriptor_64 { 1230b57cec5SDimitry Andric uint64_t _used : 58; 1240b57cec5SDimitry Andric uint32_t _szidx : 6; 1250b57cec5SDimitry Andric }; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric struct DictionaryItemDescriptor { 1280b57cec5SDimitry Andric lldb::addr_t key_ptr; 1290b57cec5SDimitry Andric lldb::addr_t val_ptr; 1300b57cec5SDimitry Andric lldb::ValueObjectSP valobj_sp; 1310b57cec5SDimitry Andric }; 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric ExecutionContextRef m_exe_ctx_ref; 13481ad6265SDimitry Andric uint8_t m_ptr_size = 8; 13581ad6265SDimitry Andric lldb::ByteOrder m_order = lldb::eByteOrderInvalid; 13681ad6265SDimitry Andric DataDescriptor_32 *m_data_32 = nullptr; 13781ad6265SDimitry Andric DataDescriptor_64 *m_data_64 = nullptr; 138fcaf7f86SDimitry Andric lldb::addr_t m_data_ptr = LLDB_INVALID_ADDRESS; 1390b57cec5SDimitry Andric CompilerType m_pair_type; 1400b57cec5SDimitry Andric std::vector<DictionaryItemDescriptor> m_children; 1410b57cec5SDimitry Andric }; 1420b57cec5SDimitry Andric 143349cc55cSDimitry Andric class NSConstantDictionarySyntheticFrontEnd : public SyntheticChildrenFrontEnd { 144349cc55cSDimitry Andric public: 145349cc55cSDimitry Andric NSConstantDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 146349cc55cSDimitry Andric 147*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 148349cc55cSDimitry Andric 149*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 150349cc55cSDimitry Andric 151*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 152349cc55cSDimitry Andric 153349cc55cSDimitry Andric bool MightHaveChildren() override; 154349cc55cSDimitry Andric 155349cc55cSDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 156349cc55cSDimitry Andric 157349cc55cSDimitry Andric private: 158349cc55cSDimitry Andric ExecutionContextRef m_exe_ctx_ref; 159349cc55cSDimitry Andric CompilerType m_pair_type; 160349cc55cSDimitry Andric uint8_t m_ptr_size = 8; 161349cc55cSDimitry Andric lldb::ByteOrder m_order = lldb::eByteOrderInvalid; 162349cc55cSDimitry Andric unsigned int m_size = 0; 163349cc55cSDimitry Andric lldb::addr_t m_keys_ptr = LLDB_INVALID_ADDRESS; 164349cc55cSDimitry Andric lldb::addr_t m_objects_ptr = LLDB_INVALID_ADDRESS; 165349cc55cSDimitry Andric 166349cc55cSDimitry Andric struct DictionaryItemDescriptor { 167349cc55cSDimitry Andric lldb::addr_t key_ptr; 168349cc55cSDimitry Andric lldb::addr_t val_ptr; 169349cc55cSDimitry Andric lldb::ValueObjectSP valobj_sp; 170349cc55cSDimitry Andric }; 171349cc55cSDimitry Andric 172349cc55cSDimitry Andric std::vector<DictionaryItemDescriptor> m_children; 173349cc55cSDimitry Andric }; 174349cc55cSDimitry Andric 1755ffd83dbSDimitry Andric class NSCFDictionarySyntheticFrontEnd : public SyntheticChildrenFrontEnd { 1765ffd83dbSDimitry Andric public: 1775ffd83dbSDimitry Andric NSCFDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 1785ffd83dbSDimitry Andric 179*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 1805ffd83dbSDimitry Andric 181*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 1825ffd83dbSDimitry Andric 183*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 1845ffd83dbSDimitry Andric 1855ffd83dbSDimitry Andric bool MightHaveChildren() override; 1865ffd83dbSDimitry Andric 1875ffd83dbSDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 1885ffd83dbSDimitry Andric 1895ffd83dbSDimitry Andric private: 1905ffd83dbSDimitry Andric struct DictionaryItemDescriptor { 1915ffd83dbSDimitry Andric lldb::addr_t key_ptr; 1925ffd83dbSDimitry Andric lldb::addr_t val_ptr; 1935ffd83dbSDimitry Andric lldb::ValueObjectSP valobj_sp; 1945ffd83dbSDimitry Andric }; 1955ffd83dbSDimitry Andric 1965ffd83dbSDimitry Andric ExecutionContextRef m_exe_ctx_ref; 19781ad6265SDimitry Andric uint8_t m_ptr_size = 8; 19881ad6265SDimitry Andric lldb::ByteOrder m_order = lldb::eByteOrderInvalid; 1995ffd83dbSDimitry Andric 2005ffd83dbSDimitry Andric CFBasicHash m_hashtable; 2015ffd83dbSDimitry Andric 2025ffd83dbSDimitry Andric CompilerType m_pair_type; 2035ffd83dbSDimitry Andric std::vector<DictionaryItemDescriptor> m_children; 2045ffd83dbSDimitry Andric }; 2055ffd83dbSDimitry Andric 2060b57cec5SDimitry Andric class NSDictionary1SyntheticFrontEnd : public SyntheticChildrenFrontEnd { 2070b57cec5SDimitry Andric public: 2080b57cec5SDimitry Andric NSDictionary1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric ~NSDictionary1SyntheticFrontEnd() override = default; 2110b57cec5SDimitry Andric 212*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 2130b57cec5SDimitry Andric 214*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 2150b57cec5SDimitry Andric 216*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric bool MightHaveChildren() override; 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric private: 2230b57cec5SDimitry Andric ValueObjectSP m_pair; 2240b57cec5SDimitry Andric }; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric template <typename D32, typename D64> 2270b57cec5SDimitry Andric class GenericNSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 2280b57cec5SDimitry Andric public: 2290b57cec5SDimitry Andric GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric ~GenericNSDictionaryMSyntheticFrontEnd() override; 2320b57cec5SDimitry Andric 233*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 2340b57cec5SDimitry Andric 235*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 2360b57cec5SDimitry Andric 237*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric bool MightHaveChildren() override; 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric private: 2440b57cec5SDimitry Andric struct DictionaryItemDescriptor { 2450b57cec5SDimitry Andric lldb::addr_t key_ptr; 2460b57cec5SDimitry Andric lldb::addr_t val_ptr; 2470b57cec5SDimitry Andric lldb::ValueObjectSP valobj_sp; 2480b57cec5SDimitry Andric }; 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric ExecutionContextRef m_exe_ctx_ref; 25181ad6265SDimitry Andric uint8_t m_ptr_size = 8; 25281ad6265SDimitry Andric lldb::ByteOrder m_order = lldb::eByteOrderInvalid; 2530b57cec5SDimitry Andric D32 *m_data_32; 2540b57cec5SDimitry Andric D64 *m_data_64; 2550b57cec5SDimitry Andric CompilerType m_pair_type; 2560b57cec5SDimitry Andric std::vector<DictionaryItemDescriptor> m_children; 2570b57cec5SDimitry Andric }; 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric namespace Foundation1100 { 2600b57cec5SDimitry Andric class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 2610b57cec5SDimitry Andric public: 2620b57cec5SDimitry Andric NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric ~NSDictionaryMSyntheticFrontEnd() override; 2650b57cec5SDimitry Andric 266*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 2670b57cec5SDimitry Andric 268*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 2690b57cec5SDimitry Andric 270*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric bool MightHaveChildren() override; 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric private: 2770b57cec5SDimitry Andric struct DataDescriptor_32 { 2780b57cec5SDimitry Andric uint32_t _used : 26; 2790b57cec5SDimitry Andric uint32_t _kvo : 1; 2800b57cec5SDimitry Andric uint32_t _size; 2810b57cec5SDimitry Andric uint32_t _mutations; 2820b57cec5SDimitry Andric uint32_t _objs_addr; 2830b57cec5SDimitry Andric uint32_t _keys_addr; 2840b57cec5SDimitry Andric }; 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric struct DataDescriptor_64 { 2870b57cec5SDimitry Andric uint64_t _used : 58; 2880b57cec5SDimitry Andric uint32_t _kvo : 1; 2890b57cec5SDimitry Andric uint64_t _size; 2900b57cec5SDimitry Andric uint64_t _mutations; 2910b57cec5SDimitry Andric uint64_t _objs_addr; 2920b57cec5SDimitry Andric uint64_t _keys_addr; 2930b57cec5SDimitry Andric }; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric struct DictionaryItemDescriptor { 2960b57cec5SDimitry Andric lldb::addr_t key_ptr; 2970b57cec5SDimitry Andric lldb::addr_t val_ptr; 2980b57cec5SDimitry Andric lldb::ValueObjectSP valobj_sp; 2990b57cec5SDimitry Andric }; 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric ExecutionContextRef m_exe_ctx_ref; 30281ad6265SDimitry Andric uint8_t m_ptr_size = 8; 30381ad6265SDimitry Andric lldb::ByteOrder m_order = lldb::eByteOrderInvalid; 30481ad6265SDimitry Andric DataDescriptor_32 *m_data_32 = nullptr; 30581ad6265SDimitry Andric DataDescriptor_64 *m_data_64 = nullptr; 3060b57cec5SDimitry Andric CompilerType m_pair_type; 3070b57cec5SDimitry Andric std::vector<DictionaryItemDescriptor> m_children; 3080b57cec5SDimitry Andric }; 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric namespace Foundation1428 { 3125ffd83dbSDimitry Andric namespace { 3130b57cec5SDimitry Andric struct DataDescriptor_32 { 3140b57cec5SDimitry Andric uint32_t _used : 26; 3150b57cec5SDimitry Andric uint32_t _kvo : 1; 3160b57cec5SDimitry Andric uint32_t _size; 3170b57cec5SDimitry Andric uint32_t _buffer; 3180b57cec5SDimitry Andric uint64_t GetSize() { return _size; } 3190b57cec5SDimitry Andric }; 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric struct DataDescriptor_64 { 3220b57cec5SDimitry Andric uint64_t _used : 58; 3230b57cec5SDimitry Andric uint32_t _kvo : 1; 3240b57cec5SDimitry Andric uint64_t _size; 3250b57cec5SDimitry Andric uint64_t _buffer; 3260b57cec5SDimitry Andric uint64_t GetSize() { return _size; } 3270b57cec5SDimitry Andric }; 3285ffd83dbSDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric using NSDictionaryMSyntheticFrontEnd = 3310b57cec5SDimitry Andric GenericNSDictionaryMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric namespace Foundation1437 { 3350b57cec5SDimitry Andric static const uint64_t NSDictionaryCapacities[] = { 3360b57cec5SDimitry Andric 0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723, 3370b57cec5SDimitry Andric 2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607, 3380b57cec5SDimitry Andric 214519, 346607, 561109, 907759, 1468927, 2376191, 3845119, 3390b57cec5SDimitry Andric 6221311, 10066421, 16287743, 26354171, 42641881, 68996069, 3400b57cec5SDimitry Andric 111638519, 180634607, 292272623, 472907251 3410b57cec5SDimitry Andric }; 3420b57cec5SDimitry Andric 3435ffd83dbSDimitry Andric static const size_t NSDictionaryNumSizeBuckets = 3445ffd83dbSDimitry Andric sizeof(NSDictionaryCapacities) / sizeof(uint64_t); 3450b57cec5SDimitry Andric 346349cc55cSDimitry Andric namespace { 3470b57cec5SDimitry Andric struct DataDescriptor_32 { 3480b57cec5SDimitry Andric uint32_t _buffer; 3490b57cec5SDimitry Andric uint32_t _muts; 3500b57cec5SDimitry Andric uint32_t _used : 25; 3510b57cec5SDimitry Andric uint32_t _kvo : 1; 3520b57cec5SDimitry Andric uint32_t _szidx : 6; 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric uint64_t GetSize() { 3550b57cec5SDimitry Andric return (_szidx) >= NSDictionaryNumSizeBuckets ? 3560b57cec5SDimitry Andric 0 : NSDictionaryCapacities[_szidx]; 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric }; 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric struct DataDescriptor_64 { 3610b57cec5SDimitry Andric uint64_t _buffer; 3620b57cec5SDimitry Andric uint32_t _muts; 3630b57cec5SDimitry Andric uint32_t _used : 25; 3640b57cec5SDimitry Andric uint32_t _kvo : 1; 3650b57cec5SDimitry Andric uint32_t _szidx : 6; 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric uint64_t GetSize() { 3680b57cec5SDimitry Andric return (_szidx) >= NSDictionaryNumSizeBuckets ? 3690b57cec5SDimitry Andric 0 : NSDictionaryCapacities[_szidx]; 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric }; 372349cc55cSDimitry Andric } // namespace 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric using NSDictionaryMSyntheticFrontEnd = 3750b57cec5SDimitry Andric GenericNSDictionaryMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric template <typename DD> 3780b57cec5SDimitry Andric uint64_t 3790b57cec5SDimitry Andric __NSDictionaryMSize_Impl(lldb_private::Process &process, 3800b57cec5SDimitry Andric lldb::addr_t valobj_addr, Status &error) { 3810b57cec5SDimitry Andric const lldb::addr_t start_of_descriptor = 3820b57cec5SDimitry Andric valobj_addr + process.GetAddressByteSize(); 3830b57cec5SDimitry Andric DD descriptor = DD(); 3840b57cec5SDimitry Andric process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor), 3850b57cec5SDimitry Andric error); 3860b57cec5SDimitry Andric if (error.Fail()) { 3870b57cec5SDimitry Andric return 0; 3880b57cec5SDimitry Andric } 3890b57cec5SDimitry Andric return descriptor._used; 3900b57cec5SDimitry Andric } 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric uint64_t 3930b57cec5SDimitry Andric __NSDictionaryMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, 3940b57cec5SDimitry Andric Status &error) { 3950b57cec5SDimitry Andric if (process.GetAddressByteSize() == 4) { 3960b57cec5SDimitry Andric return __NSDictionaryMSize_Impl<DataDescriptor_32>(process, valobj_addr, 3970b57cec5SDimitry Andric error); 3980b57cec5SDimitry Andric } else { 3990b57cec5SDimitry Andric return __NSDictionaryMSize_Impl<DataDescriptor_64>(process, valobj_addr, 4000b57cec5SDimitry Andric error); 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric } // namespace formatters 4060b57cec5SDimitry Andric } // namespace lldb_private 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric template <bool name_entries> 4090b57cec5SDimitry Andric bool lldb_private::formatters::NSDictionarySummaryProvider( 4100b57cec5SDimitry Andric ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { 41106c3fb27SDimitry Andric static constexpr llvm::StringLiteral g_TypeHint("NSDictionary"); 4120b57cec5SDimitry Andric ProcessSP process_sp = valobj.GetProcessSP(); 4130b57cec5SDimitry Andric if (!process_sp) 4140b57cec5SDimitry Andric return false; 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp); 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric if (!runtime) 4190b57cec5SDimitry Andric return false; 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP descriptor( 422e8d8bef9SDimitry Andric runtime->GetNonKVOClassDescriptor(valobj)); 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric if (!descriptor || !descriptor->IsValid()) 4250b57cec5SDimitry Andric return false; 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric uint32_t ptr_size = process_sp->GetAddressByteSize(); 4280b57cec5SDimitry Andric bool is_64bit = (ptr_size == 8); 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric if (!valobj_addr) 4330b57cec5SDimitry Andric return false; 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric uint64_t value = 0; 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric ConstString class_name(descriptor->GetClassName()); 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric static const ConstString g_DictionaryI("__NSDictionaryI"); 4400b57cec5SDimitry Andric static const ConstString g_DictionaryM("__NSDictionaryM"); 4410b57cec5SDimitry Andric static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy"); 4420b57cec5SDimitry Andric static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable"); 443fe6060f1SDimitry Andric static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM"); 4440b57cec5SDimitry Andric static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI"); 4450b57cec5SDimitry Andric static const ConstString g_Dictionary0("__NSDictionary0"); 4465ffd83dbSDimitry Andric static const ConstString g_DictionaryCF("__CFDictionary"); 4475ffd83dbSDimitry Andric static const ConstString g_DictionaryNSCF("__NSCFDictionary"); 4485ffd83dbSDimitry Andric static const ConstString g_DictionaryCFRef("CFDictionaryRef"); 449349cc55cSDimitry Andric static const ConstString g_ConstantDictionary("NSConstantDictionary"); 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric if (class_name.IsEmpty()) 4520b57cec5SDimitry Andric return false; 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) { 4550b57cec5SDimitry Andric Status error; 4560b57cec5SDimitry Andric value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 4570b57cec5SDimitry Andric ptr_size, 0, error); 4580b57cec5SDimitry Andric if (error.Fail()) 4590b57cec5SDimitry Andric return false; 4605ffd83dbSDimitry Andric 4610b57cec5SDimitry Andric value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 462349cc55cSDimitry Andric } else if (class_name == g_ConstantDictionary) { 463349cc55cSDimitry Andric Status error; 464349cc55cSDimitry Andric value = process_sp->ReadUnsignedIntegerFromMemory( 465349cc55cSDimitry Andric valobj_addr + 2 * ptr_size, ptr_size, 0, error); 466349cc55cSDimitry Andric if (error.Fail()) 467349cc55cSDimitry Andric return false; 468349cc55cSDimitry Andric } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy || 469349cc55cSDimitry Andric class_name == g_DictionaryMFrozen) { 4700b57cec5SDimitry Andric AppleObjCRuntime *apple_runtime = 4710b57cec5SDimitry Andric llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); 4720b57cec5SDimitry Andric Status error; 4730b57cec5SDimitry Andric if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { 4740b57cec5SDimitry Andric value = Foundation1437::__NSDictionaryMSize(*process_sp, valobj_addr, 4750b57cec5SDimitry Andric error); 4760b57cec5SDimitry Andric } else { 4770b57cec5SDimitry Andric value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 4780b57cec5SDimitry Andric ptr_size, 0, error); 4790b57cec5SDimitry Andric value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric if (error.Fail()) 4820b57cec5SDimitry Andric return false; 4830b57cec5SDimitry Andric } else if (class_name == g_Dictionary1) { 4840b57cec5SDimitry Andric value = 1; 4850b57cec5SDimitry Andric } else if (class_name == g_Dictionary0) { 4860b57cec5SDimitry Andric value = 0; 487349cc55cSDimitry Andric } else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF || 4885ffd83dbSDimitry Andric class_name == g_DictionaryCFRef) { 4895ffd83dbSDimitry Andric ExecutionContext exe_ctx(process_sp); 4905ffd83dbSDimitry Andric CFBasicHash cfbh; 4915ffd83dbSDimitry Andric if (!cfbh.Update(valobj_addr, exe_ctx)) 4925ffd83dbSDimitry Andric return false; 4935ffd83dbSDimitry Andric value = cfbh.GetCount(); 4945ffd83dbSDimitry Andric } else { 4950b57cec5SDimitry Andric auto &map(NSDictionary_Additionals::GetAdditionalSummaries()); 4960b57cec5SDimitry Andric for (auto &candidate : map) { 4970b57cec5SDimitry Andric if (candidate.first && candidate.first->Match(class_name)) 4980b57cec5SDimitry Andric return candidate.second(valobj, stream, options); 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric return false; 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 50306c3fb27SDimitry Andric llvm::StringRef prefix, suffix; 50406c3fb27SDimitry Andric if (Language *language = Language::FindPlugin(options.GetLanguage())) 50506c3fb27SDimitry Andric std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint); 5060b57cec5SDimitry Andric 50706c3fb27SDimitry Andric stream << prefix; 50806c3fb27SDimitry Andric stream.Printf("%" PRIu64 " %s%s", value, "key/value pair", 50906c3fb27SDimitry Andric value == 1 ? "" : "s"); 51006c3fb27SDimitry Andric stream << suffix; 5110b57cec5SDimitry Andric return true; 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andric SyntheticChildrenFrontEnd * 5150b57cec5SDimitry Andric lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( 5160b57cec5SDimitry Andric CXXSyntheticChildren *synth, lldb::ValueObjectSP valobj_sp) { 5170b57cec5SDimitry Andric lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 5180b57cec5SDimitry Andric if (!process_sp) 5190b57cec5SDimitry Andric return nullptr; 5200b57cec5SDimitry Andric AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>( 5210b57cec5SDimitry Andric ObjCLanguageRuntime::Get(*process_sp)); 5220b57cec5SDimitry Andric if (!runtime) 5230b57cec5SDimitry Andric return nullptr; 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric CompilerType valobj_type(valobj_sp->GetCompilerType()); 5260b57cec5SDimitry Andric Flags flags(valobj_type.GetTypeInfo()); 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric if (flags.IsClear(eTypeIsPointer)) { 5290b57cec5SDimitry Andric Status error; 5300b57cec5SDimitry Andric valobj_sp = valobj_sp->AddressOf(error); 5310b57cec5SDimitry Andric if (error.Fail() || !valobj_sp) 5320b57cec5SDimitry Andric return nullptr; 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP descriptor( 5360b57cec5SDimitry Andric runtime->GetClassDescriptor(*valobj_sp)); 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric if (!descriptor || !descriptor->IsValid()) 5390b57cec5SDimitry Andric return nullptr; 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric ConstString class_name(descriptor->GetClassName()); 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric static const ConstString g_DictionaryI("__NSDictionaryI"); 5440b57cec5SDimitry Andric static const ConstString g_DictionaryM("__NSDictionaryM"); 5450b57cec5SDimitry Andric static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI"); 5460b57cec5SDimitry Andric static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable"); 547fe6060f1SDimitry Andric static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM"); 5480b57cec5SDimitry Andric static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy"); 5490b57cec5SDimitry Andric static const ConstString g_Dictionary0("__NSDictionary0"); 5505ffd83dbSDimitry Andric static const ConstString g_DictionaryCF("__CFDictionary"); 5515ffd83dbSDimitry Andric static const ConstString g_DictionaryNSCF("__NSCFDictionary"); 5525ffd83dbSDimitry Andric static const ConstString g_DictionaryCFRef("CFDictionaryRef"); 553349cc55cSDimitry Andric static const ConstString g_ConstantDictionary("NSConstantDictionary"); 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric if (class_name.IsEmpty()) 5560b57cec5SDimitry Andric return nullptr; 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric if (class_name == g_DictionaryI) { 5590b57cec5SDimitry Andric return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); 560349cc55cSDimitry Andric } else if (class_name == g_ConstantDictionary) { 561349cc55cSDimitry Andric return (new NSConstantDictionarySyntheticFrontEnd(valobj_sp)); 562fe6060f1SDimitry Andric } else if (class_name == g_DictionaryM || class_name == g_DictionaryMFrozen) { 5630b57cec5SDimitry Andric if (runtime->GetFoundationVersion() >= 1437) { 5640b57cec5SDimitry Andric return (new Foundation1437::NSDictionaryMSyntheticFrontEnd(valobj_sp)); 5650b57cec5SDimitry Andric } else if (runtime->GetFoundationVersion() >= 1428) { 5660b57cec5SDimitry Andric return (new Foundation1428::NSDictionaryMSyntheticFrontEnd(valobj_sp)); 5670b57cec5SDimitry Andric } else { 5680b57cec5SDimitry Andric return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp)); 5690b57cec5SDimitry Andric } 5700b57cec5SDimitry Andric } else if (class_name == g_DictionaryMLegacy) { 5710b57cec5SDimitry Andric return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp)); 5720b57cec5SDimitry Andric } else if (class_name == g_Dictionary1) { 5730b57cec5SDimitry Andric return (new NSDictionary1SyntheticFrontEnd(valobj_sp)); 574349cc55cSDimitry Andric } else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF || 5755ffd83dbSDimitry Andric class_name == g_DictionaryCFRef) { 5765ffd83dbSDimitry Andric return (new NSCFDictionarySyntheticFrontEnd(valobj_sp)); 5770b57cec5SDimitry Andric } else { 5780b57cec5SDimitry Andric auto &map(NSDictionary_Additionals::GetAdditionalSynthetics()); 5790b57cec5SDimitry Andric for (auto &candidate : map) { 5800b57cec5SDimitry Andric if (candidate.first && candidate.first->Match((class_name))) 5810b57cec5SDimitry Andric return candidate.second(synth, valobj_sp); 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric } 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric return nullptr; 5860b57cec5SDimitry Andric } 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric lldb_private::formatters::NSDictionaryISyntheticFrontEnd:: 5890b57cec5SDimitry Andric NSDictionaryISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 59081ad6265SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_type() {} 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric lldb_private::formatters::NSDictionaryISyntheticFrontEnd:: 5930b57cec5SDimitry Andric ~NSDictionaryISyntheticFrontEnd() { 5940b57cec5SDimitry Andric delete m_data_32; 5950b57cec5SDimitry Andric m_data_32 = nullptr; 5960b57cec5SDimitry Andric delete m_data_64; 5970b57cec5SDimitry Andric m_data_64 = nullptr; 5980b57cec5SDimitry Andric } 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric size_t lldb_private::formatters::NSDictionaryISyntheticFrontEnd:: 6010b57cec5SDimitry Andric GetIndexOfChildWithName(ConstString name) { 6020b57cec5SDimitry Andric const char *item_name = name.GetCString(); 6030b57cec5SDimitry Andric uint32_t idx = ExtractIndexFromString(item_name); 604*0fca6ea1SDimitry Andric if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors()) 6050b57cec5SDimitry Andric return UINT32_MAX; 6060b57cec5SDimitry Andric return idx; 6070b57cec5SDimitry Andric } 6080b57cec5SDimitry Andric 609*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> lldb_private::formatters:: 610*0fca6ea1SDimitry Andric NSDictionaryISyntheticFrontEnd::CalculateNumChildren() { 6110b57cec5SDimitry Andric if (!m_data_32 && !m_data_64) 6120b57cec5SDimitry Andric return 0; 6130b57cec5SDimitry Andric return (m_data_32 ? m_data_32->_used : m_data_64->_used); 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric 616*0fca6ea1SDimitry Andric lldb::ChildCacheState 617*0fca6ea1SDimitry Andric lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update() { 6180b57cec5SDimitry Andric m_children.clear(); 6190b57cec5SDimitry Andric delete m_data_32; 6200b57cec5SDimitry Andric m_data_32 = nullptr; 6210b57cec5SDimitry Andric delete m_data_64; 6220b57cec5SDimitry Andric m_data_64 = nullptr; 6230b57cec5SDimitry Andric m_ptr_size = 0; 6240b57cec5SDimitry Andric ValueObjectSP valobj_sp = m_backend.GetSP(); 6250b57cec5SDimitry Andric if (!valobj_sp) 626*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 6270b57cec5SDimitry Andric m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 6280b57cec5SDimitry Andric Status error; 6290b57cec5SDimitry Andric error.Clear(); 6300b57cec5SDimitry Andric lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 6310b57cec5SDimitry Andric if (!process_sp) 632*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 6330b57cec5SDimitry Andric m_ptr_size = process_sp->GetAddressByteSize(); 6340b57cec5SDimitry Andric m_order = process_sp->GetByteOrder(); 6350b57cec5SDimitry Andric uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 6360b57cec5SDimitry Andric if (m_ptr_size == 4) { 6370b57cec5SDimitry Andric m_data_32 = new DataDescriptor_32(); 6380b57cec5SDimitry Andric process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), 6390b57cec5SDimitry Andric error); 6400b57cec5SDimitry Andric } else { 6410b57cec5SDimitry Andric m_data_64 = new DataDescriptor_64(); 6420b57cec5SDimitry Andric process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), 6430b57cec5SDimitry Andric error); 6440b57cec5SDimitry Andric } 6450b57cec5SDimitry Andric if (error.Fail()) 646*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 6470b57cec5SDimitry Andric m_data_ptr = data_location + m_ptr_size; 648*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 6490b57cec5SDimitry Andric } 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric bool lldb_private::formatters::NSDictionaryISyntheticFrontEnd:: 6520b57cec5SDimitry Andric MightHaveChildren() { 6530b57cec5SDimitry Andric return true; 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric lldb::ValueObjectSP 6570b57cec5SDimitry Andric lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex( 658*0fca6ea1SDimitry Andric uint32_t idx) { 659*0fca6ea1SDimitry Andric uint32_t num_children = CalculateNumChildrenIgnoringErrors(); 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric if (idx >= num_children) 6620b57cec5SDimitry Andric return lldb::ValueObjectSP(); 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric if (m_children.empty()) { 6650b57cec5SDimitry Andric // do the scan phase 6660b57cec5SDimitry Andric lldb::addr_t key_at_idx = 0, val_at_idx = 0; 6670b57cec5SDimitry Andric 6680b57cec5SDimitry Andric uint32_t tries = 0; 6690b57cec5SDimitry Andric uint32_t test_idx = 0; 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric while (tries < num_children) { 6720b57cec5SDimitry Andric key_at_idx = m_data_ptr + (2 * test_idx * m_ptr_size); 6730b57cec5SDimitry Andric val_at_idx = key_at_idx + m_ptr_size; 6740b57cec5SDimitry Andric ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 6750b57cec5SDimitry Andric if (!process_sp) 6760b57cec5SDimitry Andric return lldb::ValueObjectSP(); 6770b57cec5SDimitry Andric Status error; 6780b57cec5SDimitry Andric key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); 6790b57cec5SDimitry Andric if (error.Fail()) 6800b57cec5SDimitry Andric return lldb::ValueObjectSP(); 6810b57cec5SDimitry Andric val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); 6820b57cec5SDimitry Andric if (error.Fail()) 6830b57cec5SDimitry Andric return lldb::ValueObjectSP(); 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric test_idx++; 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andric if (!key_at_idx || !val_at_idx) 6880b57cec5SDimitry Andric continue; 6890b57cec5SDimitry Andric tries++; 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx, 6920b57cec5SDimitry Andric lldb::ValueObjectSP()}; 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric m_children.push_back(descriptor); 6950b57cec5SDimitry Andric } 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric 6980b57cec5SDimitry Andric if (idx >= m_children.size()) // should never happen 6990b57cec5SDimitry Andric return lldb::ValueObjectSP(); 7000b57cec5SDimitry Andric 7010b57cec5SDimitry Andric DictionaryItemDescriptor &dict_item = m_children[idx]; 7020b57cec5SDimitry Andric if (!dict_item.valobj_sp) { 7030b57cec5SDimitry Andric if (!m_pair_type.IsValid()) { 7040b57cec5SDimitry Andric TargetSP target_sp(m_backend.GetTargetSP()); 7050b57cec5SDimitry Andric if (!target_sp) 7060b57cec5SDimitry Andric return ValueObjectSP(); 7070b57cec5SDimitry Andric m_pair_type = GetLLDBNSPairType(target_sp); 7080b57cec5SDimitry Andric } 7090b57cec5SDimitry Andric if (!m_pair_type.IsValid()) 7100b57cec5SDimitry Andric return ValueObjectSP(); 7110b57cec5SDimitry Andric 71281ad6265SDimitry Andric WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0)); 7130b57cec5SDimitry Andric 7140b57cec5SDimitry Andric if (m_ptr_size == 8) { 7150b57cec5SDimitry Andric uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); 7160b57cec5SDimitry Andric *data_ptr = dict_item.key_ptr; 7170b57cec5SDimitry Andric *(data_ptr + 1) = dict_item.val_ptr; 7180b57cec5SDimitry Andric } else { 7190b57cec5SDimitry Andric uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); 7200b57cec5SDimitry Andric *data_ptr = dict_item.key_ptr; 7210b57cec5SDimitry Andric *(data_ptr + 1) = dict_item.val_ptr; 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric StreamString idx_name; 7250b57cec5SDimitry Andric idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 7260b57cec5SDimitry Andric DataExtractor data(buffer_sp, m_order, m_ptr_size); 7270b57cec5SDimitry Andric dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data, 7280b57cec5SDimitry Andric m_exe_ctx_ref, m_pair_type); 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric return dict_item.valobj_sp; 7310b57cec5SDimitry Andric } 7320b57cec5SDimitry Andric 7335ffd83dbSDimitry Andric lldb_private::formatters::NSCFDictionarySyntheticFrontEnd:: 7345ffd83dbSDimitry Andric NSCFDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 73581ad6265SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_hashtable(), 73681ad6265SDimitry Andric m_pair_type() {} 7375ffd83dbSDimitry Andric 7385ffd83dbSDimitry Andric size_t lldb_private::formatters::NSCFDictionarySyntheticFrontEnd:: 7395ffd83dbSDimitry Andric GetIndexOfChildWithName(ConstString name) { 7405ffd83dbSDimitry Andric const char *item_name = name.GetCString(); 7415ffd83dbSDimitry Andric const uint32_t idx = ExtractIndexFromString(item_name); 742*0fca6ea1SDimitry Andric if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors()) 7435ffd83dbSDimitry Andric return UINT32_MAX; 7445ffd83dbSDimitry Andric return idx; 7455ffd83dbSDimitry Andric } 7465ffd83dbSDimitry Andric 747*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> lldb_private::formatters:: 748*0fca6ea1SDimitry Andric NSCFDictionarySyntheticFrontEnd::CalculateNumChildren() { 7495ffd83dbSDimitry Andric if (!m_hashtable.IsValid()) 7505ffd83dbSDimitry Andric return 0; 7515ffd83dbSDimitry Andric return m_hashtable.GetCount(); 7525ffd83dbSDimitry Andric } 7535ffd83dbSDimitry Andric 754*0fca6ea1SDimitry Andric lldb::ChildCacheState 755*0fca6ea1SDimitry Andric lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::Update() { 7565ffd83dbSDimitry Andric m_children.clear(); 7575ffd83dbSDimitry Andric ValueObjectSP valobj_sp = m_backend.GetSP(); 7585ffd83dbSDimitry Andric m_ptr_size = 0; 7595ffd83dbSDimitry Andric if (!valobj_sp) 760*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 7615ffd83dbSDimitry Andric m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 7625ffd83dbSDimitry Andric 7635ffd83dbSDimitry Andric lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 7645ffd83dbSDimitry Andric if (!process_sp) 765*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 7665ffd83dbSDimitry Andric m_ptr_size = process_sp->GetAddressByteSize(); 7675ffd83dbSDimitry Andric m_order = process_sp->GetByteOrder(); 768*0fca6ea1SDimitry Andric return m_hashtable.Update(valobj_sp->GetValueAsUnsigned(0), m_exe_ctx_ref) 769*0fca6ea1SDimitry Andric ? lldb::ChildCacheState::eReuse 770*0fca6ea1SDimitry Andric : lldb::ChildCacheState::eRefetch; 7715ffd83dbSDimitry Andric } 7725ffd83dbSDimitry Andric 7735ffd83dbSDimitry Andric bool lldb_private::formatters::NSCFDictionarySyntheticFrontEnd:: 7745ffd83dbSDimitry Andric MightHaveChildren() { 7755ffd83dbSDimitry Andric return true; 7765ffd83dbSDimitry Andric } 7775ffd83dbSDimitry Andric 7785ffd83dbSDimitry Andric lldb::ValueObjectSP 7795ffd83dbSDimitry Andric lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::GetChildAtIndex( 780*0fca6ea1SDimitry Andric uint32_t idx) { 7815ffd83dbSDimitry Andric lldb::addr_t m_keys_ptr = m_hashtable.GetKeyPointer(); 7825ffd83dbSDimitry Andric lldb::addr_t m_values_ptr = m_hashtable.GetValuePointer(); 7835ffd83dbSDimitry Andric 784*0fca6ea1SDimitry Andric const uint32_t num_children = CalculateNumChildrenIgnoringErrors(); 7855ffd83dbSDimitry Andric 7865ffd83dbSDimitry Andric if (idx >= num_children) 7875ffd83dbSDimitry Andric return lldb::ValueObjectSP(); 7885ffd83dbSDimitry Andric 7895ffd83dbSDimitry Andric if (m_children.empty()) { 7905ffd83dbSDimitry Andric ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 7915ffd83dbSDimitry Andric if (!process_sp) 7925ffd83dbSDimitry Andric return lldb::ValueObjectSP(); 7935ffd83dbSDimitry Andric 7945ffd83dbSDimitry Andric Status error; 7955ffd83dbSDimitry Andric lldb::addr_t key_at_idx = 0, val_at_idx = 0; 7965ffd83dbSDimitry Andric 7975ffd83dbSDimitry Andric uint32_t tries = 0; 7985ffd83dbSDimitry Andric uint32_t test_idx = 0; 7995ffd83dbSDimitry Andric 8005ffd83dbSDimitry Andric // Iterate over inferior memory, reading key/value pointers by shifting each 8015ffd83dbSDimitry Andric // cursor by test_index * m_ptr_size. Returns an empty ValueObject if a read 8025ffd83dbSDimitry Andric // fails, otherwise, continue until the number of tries matches the number 8035ffd83dbSDimitry Andric // of childen. 8045ffd83dbSDimitry Andric while (tries < num_children) { 8055ffd83dbSDimitry Andric key_at_idx = m_keys_ptr + (test_idx * m_ptr_size); 8065ffd83dbSDimitry Andric val_at_idx = m_values_ptr + (test_idx * m_ptr_size); 8075ffd83dbSDimitry Andric 8085ffd83dbSDimitry Andric key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); 8095ffd83dbSDimitry Andric if (error.Fail()) 8105ffd83dbSDimitry Andric return lldb::ValueObjectSP(); 8115ffd83dbSDimitry Andric val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); 8125ffd83dbSDimitry Andric if (error.Fail()) 8135ffd83dbSDimitry Andric return lldb::ValueObjectSP(); 8145ffd83dbSDimitry Andric 8155ffd83dbSDimitry Andric test_idx++; 8165ffd83dbSDimitry Andric 8175ffd83dbSDimitry Andric if (!key_at_idx || !val_at_idx) 8185ffd83dbSDimitry Andric continue; 8195ffd83dbSDimitry Andric tries++; 8205ffd83dbSDimitry Andric 8215ffd83dbSDimitry Andric DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx, 8225ffd83dbSDimitry Andric lldb::ValueObjectSP()}; 8235ffd83dbSDimitry Andric 8245ffd83dbSDimitry Andric m_children.push_back(descriptor); 8255ffd83dbSDimitry Andric } 8265ffd83dbSDimitry Andric } 8275ffd83dbSDimitry Andric 8285ffd83dbSDimitry Andric if (idx >= m_children.size()) // should never happen 8295ffd83dbSDimitry Andric return lldb::ValueObjectSP(); 8305ffd83dbSDimitry Andric 8315ffd83dbSDimitry Andric DictionaryItemDescriptor &dict_item = m_children[idx]; 8325ffd83dbSDimitry Andric if (!dict_item.valobj_sp) { 8335ffd83dbSDimitry Andric if (!m_pair_type.IsValid()) { 8345ffd83dbSDimitry Andric TargetSP target_sp(m_backend.GetTargetSP()); 8355ffd83dbSDimitry Andric if (!target_sp) 8365ffd83dbSDimitry Andric return ValueObjectSP(); 8375ffd83dbSDimitry Andric m_pair_type = GetLLDBNSPairType(target_sp); 8385ffd83dbSDimitry Andric } 8395ffd83dbSDimitry Andric if (!m_pair_type.IsValid()) 8405ffd83dbSDimitry Andric return ValueObjectSP(); 8415ffd83dbSDimitry Andric 84281ad6265SDimitry Andric WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0)); 8435ffd83dbSDimitry Andric 8445ffd83dbSDimitry Andric switch (m_ptr_size) { 8455ffd83dbSDimitry Andric case 0: // architecture has no clue - fail 8465ffd83dbSDimitry Andric return lldb::ValueObjectSP(); 8475ffd83dbSDimitry Andric case 4: { 8485ffd83dbSDimitry Andric uint32_t *data_ptr = reinterpret_cast<uint32_t *>(buffer_sp->GetBytes()); 8495ffd83dbSDimitry Andric *data_ptr = dict_item.key_ptr; 8505ffd83dbSDimitry Andric *(data_ptr + 1) = dict_item.val_ptr; 8515ffd83dbSDimitry Andric } break; 8525ffd83dbSDimitry Andric case 8: { 8535ffd83dbSDimitry Andric uint64_t *data_ptr = reinterpret_cast<uint64_t *>(buffer_sp->GetBytes()); 8545ffd83dbSDimitry Andric *data_ptr = dict_item.key_ptr; 8555ffd83dbSDimitry Andric *(data_ptr + 1) = dict_item.val_ptr; 8565ffd83dbSDimitry Andric } break; 8575ffd83dbSDimitry Andric default: 8585ffd83dbSDimitry Andric lldbassert(false && "pointer size is not 4 nor 8"); 8595ffd83dbSDimitry Andric } 8605ffd83dbSDimitry Andric 8615ffd83dbSDimitry Andric StreamString idx_name; 8625ffd83dbSDimitry Andric idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 8635ffd83dbSDimitry Andric DataExtractor data(buffer_sp, m_order, m_ptr_size); 8645ffd83dbSDimitry Andric dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data, 8655ffd83dbSDimitry Andric m_exe_ctx_ref, m_pair_type); 8665ffd83dbSDimitry Andric } 8675ffd83dbSDimitry Andric return dict_item.valobj_sp; 8685ffd83dbSDimitry Andric } 8695ffd83dbSDimitry Andric 870349cc55cSDimitry Andric lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd:: 871349cc55cSDimitry Andric NSConstantDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 872349cc55cSDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp) {} 873349cc55cSDimitry Andric 874349cc55cSDimitry Andric size_t lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd:: 875349cc55cSDimitry Andric GetIndexOfChildWithName(ConstString name) { 876349cc55cSDimitry Andric const char *item_name = name.GetCString(); 877349cc55cSDimitry Andric uint32_t idx = ExtractIndexFromString(item_name); 878*0fca6ea1SDimitry Andric if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors()) 879349cc55cSDimitry Andric return UINT32_MAX; 880349cc55cSDimitry Andric return idx; 881349cc55cSDimitry Andric } 882349cc55cSDimitry Andric 883*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> lldb_private::formatters:: 884*0fca6ea1SDimitry Andric NSConstantDictionarySyntheticFrontEnd::CalculateNumChildren() { 885349cc55cSDimitry Andric return m_size; 886349cc55cSDimitry Andric } 887349cc55cSDimitry Andric 888*0fca6ea1SDimitry Andric lldb::ChildCacheState 889*0fca6ea1SDimitry Andric lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd::Update() { 890349cc55cSDimitry Andric ValueObjectSP valobj_sp = m_backend.GetSP(); 891349cc55cSDimitry Andric if (!valobj_sp) 892*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 893349cc55cSDimitry Andric m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 894349cc55cSDimitry Andric Status error; 895349cc55cSDimitry Andric error.Clear(); 896349cc55cSDimitry Andric lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 897349cc55cSDimitry Andric if (!process_sp) 898*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 899349cc55cSDimitry Andric m_ptr_size = process_sp->GetAddressByteSize(); 900349cc55cSDimitry Andric m_order = process_sp->GetByteOrder(); 901349cc55cSDimitry Andric uint64_t valobj_addr = valobj_sp->GetValueAsUnsigned(0); 902349cc55cSDimitry Andric m_size = process_sp->ReadUnsignedIntegerFromMemory( 903349cc55cSDimitry Andric valobj_addr + 2 * m_ptr_size, m_ptr_size, 0, error); 904349cc55cSDimitry Andric if (error.Fail()) 905*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 906349cc55cSDimitry Andric m_keys_ptr = 907349cc55cSDimitry Andric process_sp->ReadPointerFromMemory(valobj_addr + 3 * m_ptr_size, error); 908349cc55cSDimitry Andric if (error.Fail()) 909*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 910349cc55cSDimitry Andric m_objects_ptr = 911349cc55cSDimitry Andric process_sp->ReadPointerFromMemory(valobj_addr + 4 * m_ptr_size, error); 912*0fca6ea1SDimitry Andric 913*0fca6ea1SDimitry Andric return error.Success() ? lldb::ChildCacheState::eReuse 914*0fca6ea1SDimitry Andric : lldb::ChildCacheState::eRefetch; 915349cc55cSDimitry Andric } 916349cc55cSDimitry Andric 917349cc55cSDimitry Andric bool lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd:: 918349cc55cSDimitry Andric MightHaveChildren() { 919349cc55cSDimitry Andric return true; 920349cc55cSDimitry Andric } 921349cc55cSDimitry Andric 922349cc55cSDimitry Andric lldb::ValueObjectSP lldb_private::formatters:: 923*0fca6ea1SDimitry Andric NSConstantDictionarySyntheticFrontEnd::GetChildAtIndex(uint32_t idx) { 924*0fca6ea1SDimitry Andric uint32_t num_children = CalculateNumChildrenIgnoringErrors(); 925349cc55cSDimitry Andric 926349cc55cSDimitry Andric if (idx >= num_children) 927349cc55cSDimitry Andric return lldb::ValueObjectSP(); 928349cc55cSDimitry Andric 929349cc55cSDimitry Andric if (m_children.empty()) { 930349cc55cSDimitry Andric // do the scan phase 931349cc55cSDimitry Andric lldb::addr_t key_at_idx = 0, val_at_idx = 0; 932349cc55cSDimitry Andric ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 933349cc55cSDimitry Andric if (!process_sp) 934349cc55cSDimitry Andric return lldb::ValueObjectSP(); 935349cc55cSDimitry Andric 936349cc55cSDimitry Andric for (unsigned int child = 0; child < num_children; ++child) { 937349cc55cSDimitry Andric Status error; 938349cc55cSDimitry Andric key_at_idx = process_sp->ReadPointerFromMemory( 939349cc55cSDimitry Andric m_keys_ptr + child * m_ptr_size, error); 940349cc55cSDimitry Andric if (error.Fail()) 941349cc55cSDimitry Andric return lldb::ValueObjectSP(); 942349cc55cSDimitry Andric val_at_idx = process_sp->ReadPointerFromMemory( 943349cc55cSDimitry Andric m_objects_ptr + child * m_ptr_size, error); 944349cc55cSDimitry Andric if (error.Fail()) 945349cc55cSDimitry Andric return lldb::ValueObjectSP(); 946349cc55cSDimitry Andric DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx, 947349cc55cSDimitry Andric lldb::ValueObjectSP()}; 948349cc55cSDimitry Andric m_children.push_back(descriptor); 949349cc55cSDimitry Andric } 950349cc55cSDimitry Andric } 951349cc55cSDimitry Andric 952349cc55cSDimitry Andric if (idx >= m_children.size()) // should never happen 953349cc55cSDimitry Andric return lldb::ValueObjectSP(); 954349cc55cSDimitry Andric 955349cc55cSDimitry Andric DictionaryItemDescriptor &dict_item = m_children[idx]; 956349cc55cSDimitry Andric if (!dict_item.valobj_sp) { 957349cc55cSDimitry Andric if (!m_pair_type.IsValid()) { 958349cc55cSDimitry Andric TargetSP target_sp(m_backend.GetTargetSP()); 959349cc55cSDimitry Andric if (!target_sp) 960349cc55cSDimitry Andric return ValueObjectSP(); 961349cc55cSDimitry Andric m_pair_type = GetLLDBNSPairType(target_sp); 962349cc55cSDimitry Andric } 963349cc55cSDimitry Andric if (!m_pair_type.IsValid()) 964349cc55cSDimitry Andric return ValueObjectSP(); 965349cc55cSDimitry Andric 96681ad6265SDimitry Andric WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0)); 967349cc55cSDimitry Andric 968349cc55cSDimitry Andric if (m_ptr_size == 8) { 969349cc55cSDimitry Andric uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); 970349cc55cSDimitry Andric *data_ptr = dict_item.key_ptr; 971349cc55cSDimitry Andric *(data_ptr + 1) = dict_item.val_ptr; 972349cc55cSDimitry Andric } else { 973349cc55cSDimitry Andric uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); 974349cc55cSDimitry Andric *data_ptr = dict_item.key_ptr; 975349cc55cSDimitry Andric *(data_ptr + 1) = dict_item.val_ptr; 976349cc55cSDimitry Andric } 977349cc55cSDimitry Andric 978349cc55cSDimitry Andric StreamString idx_name; 979349cc55cSDimitry Andric idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 980349cc55cSDimitry Andric DataExtractor data(buffer_sp, m_order, m_ptr_size); 981349cc55cSDimitry Andric dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data, 982349cc55cSDimitry Andric m_exe_ctx_ref, m_pair_type); 983349cc55cSDimitry Andric } 984349cc55cSDimitry Andric return dict_item.valobj_sp; 985349cc55cSDimitry Andric } 986349cc55cSDimitry Andric 9870b57cec5SDimitry Andric lldb_private::formatters::NSDictionary1SyntheticFrontEnd:: 9880b57cec5SDimitry Andric NSDictionary1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 9890b57cec5SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp.get()), m_pair(nullptr) {} 9900b57cec5SDimitry Andric 9910b57cec5SDimitry Andric size_t lldb_private::formatters::NSDictionary1SyntheticFrontEnd:: 9920b57cec5SDimitry Andric GetIndexOfChildWithName(ConstString name) { 9930b57cec5SDimitry Andric static const ConstString g_zero("[0]"); 9940b57cec5SDimitry Andric return name == g_zero ? 0 : UINT32_MAX; 9950b57cec5SDimitry Andric } 9960b57cec5SDimitry Andric 997*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> lldb_private::formatters:: 998*0fca6ea1SDimitry Andric NSDictionary1SyntheticFrontEnd::CalculateNumChildren() { 9990b57cec5SDimitry Andric return 1; 10000b57cec5SDimitry Andric } 10010b57cec5SDimitry Andric 1002*0fca6ea1SDimitry Andric lldb::ChildCacheState 1003*0fca6ea1SDimitry Andric lldb_private::formatters::NSDictionary1SyntheticFrontEnd::Update() { 10040b57cec5SDimitry Andric m_pair.reset(); 1005*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 10060b57cec5SDimitry Andric } 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andric bool lldb_private::formatters::NSDictionary1SyntheticFrontEnd:: 10090b57cec5SDimitry Andric MightHaveChildren() { 10100b57cec5SDimitry Andric return true; 10110b57cec5SDimitry Andric } 10120b57cec5SDimitry Andric 10130b57cec5SDimitry Andric lldb::ValueObjectSP 10140b57cec5SDimitry Andric lldb_private::formatters::NSDictionary1SyntheticFrontEnd::GetChildAtIndex( 1015*0fca6ea1SDimitry Andric uint32_t idx) { 10160b57cec5SDimitry Andric if (idx != 0) 10170b57cec5SDimitry Andric return lldb::ValueObjectSP(); 10180b57cec5SDimitry Andric 10190b57cec5SDimitry Andric if (m_pair.get()) 10200b57cec5SDimitry Andric return m_pair; 10210b57cec5SDimitry Andric 10220b57cec5SDimitry Andric auto process_sp(m_backend.GetProcessSP()); 10230b57cec5SDimitry Andric if (!process_sp) 10240b57cec5SDimitry Andric return nullptr; 10250b57cec5SDimitry Andric 10260b57cec5SDimitry Andric auto ptr_size = process_sp->GetAddressByteSize(); 10270b57cec5SDimitry Andric 10280b57cec5SDimitry Andric lldb::addr_t key_ptr = 10290b57cec5SDimitry Andric m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS) + ptr_size; 10300b57cec5SDimitry Andric lldb::addr_t value_ptr = key_ptr + ptr_size; 10310b57cec5SDimitry Andric 10320b57cec5SDimitry Andric Status error; 10330b57cec5SDimitry Andric 10340b57cec5SDimitry Andric lldb::addr_t value_at_idx = process_sp->ReadPointerFromMemory(key_ptr, error); 10350b57cec5SDimitry Andric if (error.Fail()) 10360b57cec5SDimitry Andric return nullptr; 10370b57cec5SDimitry Andric lldb::addr_t key_at_idx = process_sp->ReadPointerFromMemory(value_ptr, error); 10380b57cec5SDimitry Andric if (error.Fail()) 10390b57cec5SDimitry Andric return nullptr; 10400b57cec5SDimitry Andric 10410b57cec5SDimitry Andric auto pair_type = 10420b57cec5SDimitry Andric GetLLDBNSPairType(process_sp->GetTarget().shared_from_this()); 10430b57cec5SDimitry Andric 104481ad6265SDimitry Andric WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * ptr_size, 0)); 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric if (ptr_size == 8) { 10470b57cec5SDimitry Andric uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); 10480b57cec5SDimitry Andric *data_ptr = key_at_idx; 10490b57cec5SDimitry Andric *(data_ptr + 1) = value_at_idx; 10500b57cec5SDimitry Andric } else { 10510b57cec5SDimitry Andric uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); 10520b57cec5SDimitry Andric *data_ptr = key_at_idx; 10530b57cec5SDimitry Andric *(data_ptr + 1) = value_at_idx; 10540b57cec5SDimitry Andric } 10550b57cec5SDimitry Andric 10560b57cec5SDimitry Andric DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size); 10570b57cec5SDimitry Andric m_pair = CreateValueObjectFromData( 10580b57cec5SDimitry Andric "[0]", data, m_backend.GetExecutionContextRef(), pair_type); 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric return m_pair; 10610b57cec5SDimitry Andric } 10620b57cec5SDimitry Andric 10630b57cec5SDimitry Andric template <typename D32, typename D64> 10640b57cec5SDimitry Andric lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32, D64>:: 10650b57cec5SDimitry Andric GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 106681ad6265SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), 106781ad6265SDimitry Andric m_data_32(nullptr), m_data_64(nullptr), m_pair_type() {} 10680b57cec5SDimitry Andric 10690b57cec5SDimitry Andric template <typename D32, typename D64> 1070*0fca6ea1SDimitry Andric lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd< 1071*0fca6ea1SDimitry Andric D32, D64>::GenericNSDictionaryMSyntheticFrontEnd:: 1072*0fca6ea1SDimitry Andric ~GenericNSDictionaryMSyntheticFrontEnd() { 10730b57cec5SDimitry Andric delete m_data_32; 10740b57cec5SDimitry Andric m_data_32 = nullptr; 10750b57cec5SDimitry Andric delete m_data_64; 10760b57cec5SDimitry Andric m_data_64 = nullptr; 10770b57cec5SDimitry Andric } 10780b57cec5SDimitry Andric 10790b57cec5SDimitry Andric template <typename D32, typename D64> 10805ffd83dbSDimitry Andric size_t lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd< 10815ffd83dbSDimitry Andric D32, D64>::GetIndexOfChildWithName(ConstString name) { 10820b57cec5SDimitry Andric const char *item_name = name.GetCString(); 10830b57cec5SDimitry Andric uint32_t idx = ExtractIndexFromString(item_name); 1084*0fca6ea1SDimitry Andric if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors()) 10850b57cec5SDimitry Andric return UINT32_MAX; 10860b57cec5SDimitry Andric return idx; 10870b57cec5SDimitry Andric } 10880b57cec5SDimitry Andric 10890b57cec5SDimitry Andric template <typename D32, typename D64> 1090*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> 1091*0fca6ea1SDimitry Andric lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd< 1092*0fca6ea1SDimitry Andric D32, D64>::CalculateNumChildren() { 10930b57cec5SDimitry Andric if (!m_data_32 && !m_data_64) 10940b57cec5SDimitry Andric return 0; 1095*0fca6ea1SDimitry Andric return (m_data_32 ? (uint32_t)m_data_32->_used : (uint32_t)m_data_64->_used); 10960b57cec5SDimitry Andric } 10970b57cec5SDimitry Andric 10980b57cec5SDimitry Andric template <typename D32, typename D64> 1099*0fca6ea1SDimitry Andric lldb::ChildCacheState 1100*0fca6ea1SDimitry Andric lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32, 1101*0fca6ea1SDimitry Andric D64>::Update() { 11020b57cec5SDimitry Andric m_children.clear(); 11030b57cec5SDimitry Andric ValueObjectSP valobj_sp = m_backend.GetSP(); 11040b57cec5SDimitry Andric m_ptr_size = 0; 11050b57cec5SDimitry Andric delete m_data_32; 11060b57cec5SDimitry Andric m_data_32 = nullptr; 11070b57cec5SDimitry Andric delete m_data_64; 11080b57cec5SDimitry Andric m_data_64 = nullptr; 11090b57cec5SDimitry Andric if (!valobj_sp) 1110*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 11110b57cec5SDimitry Andric m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 11120b57cec5SDimitry Andric Status error; 11130b57cec5SDimitry Andric error.Clear(); 11140b57cec5SDimitry Andric lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 11150b57cec5SDimitry Andric if (!process_sp) 1116*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 11170b57cec5SDimitry Andric m_ptr_size = process_sp->GetAddressByteSize(); 11180b57cec5SDimitry Andric m_order = process_sp->GetByteOrder(); 11190b57cec5SDimitry Andric uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 11200b57cec5SDimitry Andric if (m_ptr_size == 4) { 11210b57cec5SDimitry Andric m_data_32 = new D32(); 11220b57cec5SDimitry Andric process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), 11230b57cec5SDimitry Andric error); 11240b57cec5SDimitry Andric } else { 11250b57cec5SDimitry Andric m_data_64 = new D64(); 11260b57cec5SDimitry Andric process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), 11270b57cec5SDimitry Andric error); 11280b57cec5SDimitry Andric } 1129bdd1243dSDimitry Andric 1130*0fca6ea1SDimitry Andric return error.Success() ? lldb::ChildCacheState::eReuse 1131*0fca6ea1SDimitry Andric : lldb::ChildCacheState::eRefetch; 11320b57cec5SDimitry Andric } 11330b57cec5SDimitry Andric 11340b57cec5SDimitry Andric template <typename D32, typename D64> 11350b57cec5SDimitry Andric bool 11360b57cec5SDimitry Andric lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: 11370b57cec5SDimitry Andric MightHaveChildren() { 11380b57cec5SDimitry Andric return true; 11390b57cec5SDimitry Andric } 11400b57cec5SDimitry Andric 11410b57cec5SDimitry Andric template <typename D32, typename D64> 11420b57cec5SDimitry Andric lldb::ValueObjectSP 11435ffd83dbSDimitry Andric lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd< 1144*0fca6ea1SDimitry Andric D32, D64>::GetChildAtIndex(uint32_t idx) { 11450b57cec5SDimitry Andric lldb::addr_t m_keys_ptr; 11460b57cec5SDimitry Andric lldb::addr_t m_values_ptr; 11470b57cec5SDimitry Andric if (m_data_32) { 11480b57cec5SDimitry Andric uint32_t size = m_data_32->GetSize(); 11490b57cec5SDimitry Andric m_keys_ptr = m_data_32->_buffer; 11500b57cec5SDimitry Andric m_values_ptr = m_data_32->_buffer + (m_ptr_size * size); 11510b57cec5SDimitry Andric } else { 11520b57cec5SDimitry Andric uint32_t size = m_data_64->GetSize(); 11530b57cec5SDimitry Andric m_keys_ptr = m_data_64->_buffer; 11540b57cec5SDimitry Andric m_values_ptr = m_data_64->_buffer + (m_ptr_size * size); 11550b57cec5SDimitry Andric } 11560b57cec5SDimitry Andric 1157*0fca6ea1SDimitry Andric uint32_t num_children = CalculateNumChildrenIgnoringErrors(); 11580b57cec5SDimitry Andric 11590b57cec5SDimitry Andric if (idx >= num_children) 11600b57cec5SDimitry Andric return lldb::ValueObjectSP(); 11610b57cec5SDimitry Andric 11620b57cec5SDimitry Andric if (m_children.empty()) { 11630b57cec5SDimitry Andric // do the scan phase 11640b57cec5SDimitry Andric lldb::addr_t key_at_idx = 0, val_at_idx = 0; 11650b57cec5SDimitry Andric 11660b57cec5SDimitry Andric uint32_t tries = 0; 11670b57cec5SDimitry Andric uint32_t test_idx = 0; 11680b57cec5SDimitry Andric 11690b57cec5SDimitry Andric while (tries < num_children) { 11700b57cec5SDimitry Andric key_at_idx = m_keys_ptr + (test_idx * m_ptr_size); 11710b57cec5SDimitry Andric val_at_idx = m_values_ptr + (test_idx * m_ptr_size); 11720b57cec5SDimitry Andric ; 11730b57cec5SDimitry Andric ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 11740b57cec5SDimitry Andric if (!process_sp) 11750b57cec5SDimitry Andric return lldb::ValueObjectSP(); 11760b57cec5SDimitry Andric Status error; 11770b57cec5SDimitry Andric key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); 11780b57cec5SDimitry Andric if (error.Fail()) 11790b57cec5SDimitry Andric return lldb::ValueObjectSP(); 11800b57cec5SDimitry Andric val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); 11810b57cec5SDimitry Andric if (error.Fail()) 11820b57cec5SDimitry Andric return lldb::ValueObjectSP(); 11830b57cec5SDimitry Andric 11840b57cec5SDimitry Andric test_idx++; 11850b57cec5SDimitry Andric 11860b57cec5SDimitry Andric if (!key_at_idx || !val_at_idx) 11870b57cec5SDimitry Andric continue; 11880b57cec5SDimitry Andric tries++; 11890b57cec5SDimitry Andric 11900b57cec5SDimitry Andric DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx, 11910b57cec5SDimitry Andric lldb::ValueObjectSP()}; 11920b57cec5SDimitry Andric 11930b57cec5SDimitry Andric m_children.push_back(descriptor); 11940b57cec5SDimitry Andric } 11950b57cec5SDimitry Andric } 11960b57cec5SDimitry Andric 11970b57cec5SDimitry Andric if (idx >= m_children.size()) // should never happen 11980b57cec5SDimitry Andric return lldb::ValueObjectSP(); 11990b57cec5SDimitry Andric 12000b57cec5SDimitry Andric DictionaryItemDescriptor &dict_item = m_children[idx]; 12010b57cec5SDimitry Andric if (!dict_item.valobj_sp) { 12020b57cec5SDimitry Andric if (!m_pair_type.IsValid()) { 12030b57cec5SDimitry Andric TargetSP target_sp(m_backend.GetTargetSP()); 12040b57cec5SDimitry Andric if (!target_sp) 12050b57cec5SDimitry Andric return ValueObjectSP(); 12060b57cec5SDimitry Andric m_pair_type = GetLLDBNSPairType(target_sp); 12070b57cec5SDimitry Andric } 12080b57cec5SDimitry Andric if (!m_pair_type.IsValid()) 12090b57cec5SDimitry Andric return ValueObjectSP(); 12100b57cec5SDimitry Andric 121181ad6265SDimitry Andric WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0)); 12120b57cec5SDimitry Andric 12130b57cec5SDimitry Andric if (m_ptr_size == 8) { 12140b57cec5SDimitry Andric uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); 12150b57cec5SDimitry Andric *data_ptr = dict_item.key_ptr; 12160b57cec5SDimitry Andric *(data_ptr + 1) = dict_item.val_ptr; 12170b57cec5SDimitry Andric } else { 12180b57cec5SDimitry Andric uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); 12190b57cec5SDimitry Andric *data_ptr = dict_item.key_ptr; 12200b57cec5SDimitry Andric *(data_ptr + 1) = dict_item.val_ptr; 12210b57cec5SDimitry Andric } 12220b57cec5SDimitry Andric 12230b57cec5SDimitry Andric StreamString idx_name; 12240b57cec5SDimitry Andric idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 12250b57cec5SDimitry Andric DataExtractor data(buffer_sp, m_order, m_ptr_size); 12260b57cec5SDimitry Andric dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data, 12270b57cec5SDimitry Andric m_exe_ctx_ref, m_pair_type); 12280b57cec5SDimitry Andric } 12290b57cec5SDimitry Andric return dict_item.valobj_sp; 12300b57cec5SDimitry Andric } 12310b57cec5SDimitry Andric 123281ad6265SDimitry Andric lldb_private::formatters::Foundation1100::NSDictionaryMSyntheticFrontEnd:: 12330b57cec5SDimitry Andric NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 123481ad6265SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_type() {} 12350b57cec5SDimitry Andric 12360b57cec5SDimitry Andric lldb_private::formatters::Foundation1100:: 12370b57cec5SDimitry Andric NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd() { 12380b57cec5SDimitry Andric delete m_data_32; 12390b57cec5SDimitry Andric m_data_32 = nullptr; 12400b57cec5SDimitry Andric delete m_data_64; 12410b57cec5SDimitry Andric m_data_64 = nullptr; 12420b57cec5SDimitry Andric } 12430b57cec5SDimitry Andric 12440b57cec5SDimitry Andric size_t 12450b57cec5SDimitry Andric lldb_private::formatters::Foundation1100:: 12460b57cec5SDimitry Andric NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) { 12470b57cec5SDimitry Andric const char *item_name = name.GetCString(); 12480b57cec5SDimitry Andric uint32_t idx = ExtractIndexFromString(item_name); 1249*0fca6ea1SDimitry Andric if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors()) 12500b57cec5SDimitry Andric return UINT32_MAX; 12510b57cec5SDimitry Andric return idx; 12520b57cec5SDimitry Andric } 12530b57cec5SDimitry Andric 1254*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> lldb_private::formatters::Foundation1100:: 12550b57cec5SDimitry Andric NSDictionaryMSyntheticFrontEnd::CalculateNumChildren() { 12560b57cec5SDimitry Andric if (!m_data_32 && !m_data_64) 12570b57cec5SDimitry Andric return 0; 12580b57cec5SDimitry Andric return (m_data_32 ? m_data_32->_used : m_data_64->_used); 12590b57cec5SDimitry Andric } 12600b57cec5SDimitry Andric 1261*0fca6ea1SDimitry Andric lldb::ChildCacheState lldb_private::formatters::Foundation1100:: 12620b57cec5SDimitry Andric NSDictionaryMSyntheticFrontEnd::Update() { 12630b57cec5SDimitry Andric m_children.clear(); 12640b57cec5SDimitry Andric ValueObjectSP valobj_sp = m_backend.GetSP(); 12650b57cec5SDimitry Andric m_ptr_size = 0; 12660b57cec5SDimitry Andric delete m_data_32; 12670b57cec5SDimitry Andric m_data_32 = nullptr; 12680b57cec5SDimitry Andric delete m_data_64; 12690b57cec5SDimitry Andric m_data_64 = nullptr; 12700b57cec5SDimitry Andric if (!valobj_sp) 1271*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 12720b57cec5SDimitry Andric m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 12730b57cec5SDimitry Andric Status error; 12740b57cec5SDimitry Andric error.Clear(); 12750b57cec5SDimitry Andric lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 12760b57cec5SDimitry Andric if (!process_sp) 1277*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 12780b57cec5SDimitry Andric m_ptr_size = process_sp->GetAddressByteSize(); 12790b57cec5SDimitry Andric m_order = process_sp->GetByteOrder(); 12800b57cec5SDimitry Andric uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 12810b57cec5SDimitry Andric if (m_ptr_size == 4) { 12820b57cec5SDimitry Andric m_data_32 = new DataDescriptor_32(); 12830b57cec5SDimitry Andric process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), 12840b57cec5SDimitry Andric error); 12850b57cec5SDimitry Andric } else { 12860b57cec5SDimitry Andric m_data_64 = new DataDescriptor_64(); 12870b57cec5SDimitry Andric process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), 12880b57cec5SDimitry Andric error); 12890b57cec5SDimitry Andric } 1290bdd1243dSDimitry Andric 1291*0fca6ea1SDimitry Andric return error.Success() ? lldb::ChildCacheState::eReuse 1292*0fca6ea1SDimitry Andric : lldb::ChildCacheState::eRefetch; 12930b57cec5SDimitry Andric } 12940b57cec5SDimitry Andric 12950b57cec5SDimitry Andric bool 12960b57cec5SDimitry Andric lldb_private::formatters::Foundation1100:: 12970b57cec5SDimitry Andric NSDictionaryMSyntheticFrontEnd::MightHaveChildren() { 12980b57cec5SDimitry Andric return true; 12990b57cec5SDimitry Andric } 13000b57cec5SDimitry Andric 13010b57cec5SDimitry Andric lldb::ValueObjectSP 13020b57cec5SDimitry Andric lldb_private::formatters::Foundation1100:: 1303*0fca6ea1SDimitry Andric NSDictionaryMSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) { 13040b57cec5SDimitry Andric lldb::addr_t m_keys_ptr = 13050b57cec5SDimitry Andric (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr); 13060b57cec5SDimitry Andric lldb::addr_t m_values_ptr = 13070b57cec5SDimitry Andric (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr); 13080b57cec5SDimitry Andric 1309*0fca6ea1SDimitry Andric uint32_t num_children = CalculateNumChildrenIgnoringErrors(); 13100b57cec5SDimitry Andric 13110b57cec5SDimitry Andric if (idx >= num_children) 13120b57cec5SDimitry Andric return lldb::ValueObjectSP(); 13130b57cec5SDimitry Andric 13140b57cec5SDimitry Andric if (m_children.empty()) { 13150b57cec5SDimitry Andric // do the scan phase 13160b57cec5SDimitry Andric lldb::addr_t key_at_idx = 0, val_at_idx = 0; 13170b57cec5SDimitry Andric 13180b57cec5SDimitry Andric uint32_t tries = 0; 13190b57cec5SDimitry Andric uint32_t test_idx = 0; 13200b57cec5SDimitry Andric 13210b57cec5SDimitry Andric while (tries < num_children) { 13220b57cec5SDimitry Andric key_at_idx = m_keys_ptr + (test_idx * m_ptr_size); 13230b57cec5SDimitry Andric val_at_idx = m_values_ptr + (test_idx * m_ptr_size); 13240b57cec5SDimitry Andric ; 13250b57cec5SDimitry Andric ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 13260b57cec5SDimitry Andric if (!process_sp) 13270b57cec5SDimitry Andric return lldb::ValueObjectSP(); 13280b57cec5SDimitry Andric Status error; 13290b57cec5SDimitry Andric key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); 13300b57cec5SDimitry Andric if (error.Fail()) 13310b57cec5SDimitry Andric return lldb::ValueObjectSP(); 13320b57cec5SDimitry Andric val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); 13330b57cec5SDimitry Andric if (error.Fail()) 13340b57cec5SDimitry Andric return lldb::ValueObjectSP(); 13350b57cec5SDimitry Andric 13360b57cec5SDimitry Andric test_idx++; 13370b57cec5SDimitry Andric 13380b57cec5SDimitry Andric if (!key_at_idx || !val_at_idx) 13390b57cec5SDimitry Andric continue; 13400b57cec5SDimitry Andric tries++; 13410b57cec5SDimitry Andric 13420b57cec5SDimitry Andric DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx, 13430b57cec5SDimitry Andric lldb::ValueObjectSP()}; 13440b57cec5SDimitry Andric 13450b57cec5SDimitry Andric m_children.push_back(descriptor); 13460b57cec5SDimitry Andric } 13470b57cec5SDimitry Andric } 13480b57cec5SDimitry Andric 13490b57cec5SDimitry Andric if (idx >= m_children.size()) // should never happen 13500b57cec5SDimitry Andric return lldb::ValueObjectSP(); 13510b57cec5SDimitry Andric 13520b57cec5SDimitry Andric DictionaryItemDescriptor &dict_item = m_children[idx]; 13530b57cec5SDimitry Andric if (!dict_item.valobj_sp) { 13540b57cec5SDimitry Andric if (!m_pair_type.IsValid()) { 13550b57cec5SDimitry Andric TargetSP target_sp(m_backend.GetTargetSP()); 13560b57cec5SDimitry Andric if (!target_sp) 13570b57cec5SDimitry Andric return ValueObjectSP(); 13580b57cec5SDimitry Andric m_pair_type = GetLLDBNSPairType(target_sp); 13590b57cec5SDimitry Andric } 13600b57cec5SDimitry Andric if (!m_pair_type.IsValid()) 13610b57cec5SDimitry Andric return ValueObjectSP(); 13620b57cec5SDimitry Andric 136381ad6265SDimitry Andric WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0)); 13640b57cec5SDimitry Andric 13650b57cec5SDimitry Andric if (m_ptr_size == 8) { 13660b57cec5SDimitry Andric uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); 13670b57cec5SDimitry Andric *data_ptr = dict_item.key_ptr; 13680b57cec5SDimitry Andric *(data_ptr + 1) = dict_item.val_ptr; 13690b57cec5SDimitry Andric } else { 13700b57cec5SDimitry Andric uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); 13710b57cec5SDimitry Andric *data_ptr = dict_item.key_ptr; 13720b57cec5SDimitry Andric *(data_ptr + 1) = dict_item.val_ptr; 13730b57cec5SDimitry Andric } 13740b57cec5SDimitry Andric 13750b57cec5SDimitry Andric StreamString idx_name; 13760b57cec5SDimitry Andric idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 13770b57cec5SDimitry Andric DataExtractor data(buffer_sp, m_order, m_ptr_size); 13780b57cec5SDimitry Andric dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data, 13790b57cec5SDimitry Andric m_exe_ctx_ref, m_pair_type); 13800b57cec5SDimitry Andric } 13810b57cec5SDimitry Andric return dict_item.valobj_sp; 13820b57cec5SDimitry Andric } 13830b57cec5SDimitry Andric 13840b57cec5SDimitry Andric template bool lldb_private::formatters::NSDictionarySummaryProvider<true>( 13850b57cec5SDimitry Andric ValueObject &, Stream &, const TypeSummaryOptions &); 13860b57cec5SDimitry Andric 13870b57cec5SDimitry Andric template bool lldb_private::formatters::NSDictionarySummaryProvider<false>( 13880b57cec5SDimitry Andric ValueObject &, Stream &, const TypeSummaryOptions &); 1389