Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
39644 views
//===-- NSDictionary.cpp --------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include <mutex>910#include "clang/AST/DeclCXX.h"1112#include "CFBasicHash.h"13#include "NSDictionary.h"1415#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"16#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"1718#include "lldb/Core/ValueObject.h"19#include "lldb/Core/ValueObjectConstResult.h"20#include "lldb/DataFormatters/FormattersHelpers.h"21#include "lldb/Target/Language.h"22#include "lldb/Target/StackFrame.h"23#include "lldb/Target/Target.h"24#include "lldb/Utility/DataBufferHeap.h"25#include "lldb/Utility/Endian.h"26#include "lldb/Utility/Status.h"27#include "lldb/Utility/Stream.h"2829using namespace lldb;30using namespace lldb_private;31using namespace lldb_private::formatters;3233NSDictionary_Additionals::AdditionalFormatterMatching::Prefix::Prefix(34ConstString p)35: m_prefix(p) {}3637bool NSDictionary_Additionals::AdditionalFormatterMatching::Prefix::Match(38ConstString class_name) {39return class_name.GetStringRef().starts_with(m_prefix.GetStringRef());40}4142NSDictionary_Additionals::AdditionalFormatterMatching::Full::Full(ConstString n)43: m_name(n) {}4445bool NSDictionary_Additionals::AdditionalFormatterMatching::Full::Match(46ConstString class_name) {47return (class_name == m_name);48}4950NSDictionary_Additionals::AdditionalFormatters<51CXXFunctionSummaryFormat::Callback> &52NSDictionary_Additionals::GetAdditionalSummaries() {53static AdditionalFormatters<CXXFunctionSummaryFormat::Callback> g_map;54return g_map;55}5657NSDictionary_Additionals::AdditionalFormatters<58CXXSyntheticChildren::CreateFrontEndCallback> &59NSDictionary_Additionals::GetAdditionalSynthetics() {60static AdditionalFormatters<CXXSyntheticChildren::CreateFrontEndCallback>61g_map;62return g_map;63}6465static CompilerType GetLLDBNSPairType(TargetSP target_sp) {66CompilerType compiler_type;67TypeSystemClangSP scratch_ts_sp =68ScratchTypeSystemClang::GetForTarget(*target_sp);6970if (!scratch_ts_sp)71return compiler_type;7273static constexpr llvm::StringLiteral g_lldb_autogen_nspair("__lldb_autogen_nspair");7475compiler_type = scratch_ts_sp->GetTypeForIdentifier<clang::CXXRecordDecl>(g_lldb_autogen_nspair);7677if (!compiler_type) {78compiler_type = scratch_ts_sp->CreateRecordType(79nullptr, OptionalClangModuleID(), lldb::eAccessPublic,80g_lldb_autogen_nspair, llvm::to_underlying(clang::TagTypeKind::Struct),81lldb::eLanguageTypeC);8283if (compiler_type) {84TypeSystemClang::StartTagDeclarationDefinition(compiler_type);85CompilerType id_compiler_type =86scratch_ts_sp->GetBasicType(eBasicTypeObjCID);87TypeSystemClang::AddFieldToRecordType(88compiler_type, "key", id_compiler_type, lldb::eAccessPublic, 0);89TypeSystemClang::AddFieldToRecordType(90compiler_type, "value", id_compiler_type, lldb::eAccessPublic, 0);91TypeSystemClang::CompleteTagDeclarationDefinition(compiler_type);92}93}94return compiler_type;95}9697namespace lldb_private {98namespace formatters {99class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd {100public:101NSDictionaryISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);102103~NSDictionaryISyntheticFrontEnd() override;104105llvm::Expected<uint32_t> CalculateNumChildren() override;106107lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;108109lldb::ChildCacheState Update() override;110111bool MightHaveChildren() override;112113size_t GetIndexOfChildWithName(ConstString name) override;114115private:116struct DataDescriptor_32 {117uint32_t _used : 26;118uint32_t _szidx : 6;119};120121struct DataDescriptor_64 {122uint64_t _used : 58;123uint32_t _szidx : 6;124};125126struct DictionaryItemDescriptor {127lldb::addr_t key_ptr;128lldb::addr_t val_ptr;129lldb::ValueObjectSP valobj_sp;130};131132ExecutionContextRef m_exe_ctx_ref;133uint8_t m_ptr_size = 8;134lldb::ByteOrder m_order = lldb::eByteOrderInvalid;135DataDescriptor_32 *m_data_32 = nullptr;136DataDescriptor_64 *m_data_64 = nullptr;137lldb::addr_t m_data_ptr = LLDB_INVALID_ADDRESS;138CompilerType m_pair_type;139std::vector<DictionaryItemDescriptor> m_children;140};141142class NSConstantDictionarySyntheticFrontEnd : public SyntheticChildrenFrontEnd {143public:144NSConstantDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);145146llvm::Expected<uint32_t> CalculateNumChildren() override;147148lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;149150lldb::ChildCacheState Update() override;151152bool MightHaveChildren() override;153154size_t GetIndexOfChildWithName(ConstString name) override;155156private:157ExecutionContextRef m_exe_ctx_ref;158CompilerType m_pair_type;159uint8_t m_ptr_size = 8;160lldb::ByteOrder m_order = lldb::eByteOrderInvalid;161unsigned int m_size = 0;162lldb::addr_t m_keys_ptr = LLDB_INVALID_ADDRESS;163lldb::addr_t m_objects_ptr = LLDB_INVALID_ADDRESS;164165struct DictionaryItemDescriptor {166lldb::addr_t key_ptr;167lldb::addr_t val_ptr;168lldb::ValueObjectSP valobj_sp;169};170171std::vector<DictionaryItemDescriptor> m_children;172};173174class NSCFDictionarySyntheticFrontEnd : public SyntheticChildrenFrontEnd {175public:176NSCFDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);177178llvm::Expected<uint32_t> CalculateNumChildren() override;179180lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;181182lldb::ChildCacheState Update() override;183184bool MightHaveChildren() override;185186size_t GetIndexOfChildWithName(ConstString name) override;187188private:189struct DictionaryItemDescriptor {190lldb::addr_t key_ptr;191lldb::addr_t val_ptr;192lldb::ValueObjectSP valobj_sp;193};194195ExecutionContextRef m_exe_ctx_ref;196uint8_t m_ptr_size = 8;197lldb::ByteOrder m_order = lldb::eByteOrderInvalid;198199CFBasicHash m_hashtable;200201CompilerType m_pair_type;202std::vector<DictionaryItemDescriptor> m_children;203};204205class NSDictionary1SyntheticFrontEnd : public SyntheticChildrenFrontEnd {206public:207NSDictionary1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);208209~NSDictionary1SyntheticFrontEnd() override = default;210211llvm::Expected<uint32_t> CalculateNumChildren() override;212213lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;214215lldb::ChildCacheState Update() override;216217bool MightHaveChildren() override;218219size_t GetIndexOfChildWithName(ConstString name) override;220221private:222ValueObjectSP m_pair;223};224225template <typename D32, typename D64>226class GenericNSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd {227public:228GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);229230~GenericNSDictionaryMSyntheticFrontEnd() override;231232llvm::Expected<uint32_t> CalculateNumChildren() override;233234lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;235236lldb::ChildCacheState Update() override;237238bool MightHaveChildren() override;239240size_t GetIndexOfChildWithName(ConstString name) override;241242private:243struct DictionaryItemDescriptor {244lldb::addr_t key_ptr;245lldb::addr_t val_ptr;246lldb::ValueObjectSP valobj_sp;247};248249ExecutionContextRef m_exe_ctx_ref;250uint8_t m_ptr_size = 8;251lldb::ByteOrder m_order = lldb::eByteOrderInvalid;252D32 *m_data_32;253D64 *m_data_64;254CompilerType m_pair_type;255std::vector<DictionaryItemDescriptor> m_children;256};257258namespace Foundation1100 {259class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd {260public:261NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);262263~NSDictionaryMSyntheticFrontEnd() override;264265llvm::Expected<uint32_t> CalculateNumChildren() override;266267lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;268269lldb::ChildCacheState Update() override;270271bool MightHaveChildren() override;272273size_t GetIndexOfChildWithName(ConstString name) override;274275private:276struct DataDescriptor_32 {277uint32_t _used : 26;278uint32_t _kvo : 1;279uint32_t _size;280uint32_t _mutations;281uint32_t _objs_addr;282uint32_t _keys_addr;283};284285struct DataDescriptor_64 {286uint64_t _used : 58;287uint32_t _kvo : 1;288uint64_t _size;289uint64_t _mutations;290uint64_t _objs_addr;291uint64_t _keys_addr;292};293294struct DictionaryItemDescriptor {295lldb::addr_t key_ptr;296lldb::addr_t val_ptr;297lldb::ValueObjectSP valobj_sp;298};299300ExecutionContextRef m_exe_ctx_ref;301uint8_t m_ptr_size = 8;302lldb::ByteOrder m_order = lldb::eByteOrderInvalid;303DataDescriptor_32 *m_data_32 = nullptr;304DataDescriptor_64 *m_data_64 = nullptr;305CompilerType m_pair_type;306std::vector<DictionaryItemDescriptor> m_children;307};308}309310namespace Foundation1428 {311namespace {312struct DataDescriptor_32 {313uint32_t _used : 26;314uint32_t _kvo : 1;315uint32_t _size;316uint32_t _buffer;317uint64_t GetSize() { return _size; }318};319320struct DataDescriptor_64 {321uint64_t _used : 58;322uint32_t _kvo : 1;323uint64_t _size;324uint64_t _buffer;325uint64_t GetSize() { return _size; }326};327}328329using NSDictionaryMSyntheticFrontEnd =330GenericNSDictionaryMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;331}332333namespace Foundation1437 {334static const uint64_t NSDictionaryCapacities[] = {3350, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723,3362803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607,337214519, 346607, 561109, 907759, 1468927, 2376191, 3845119,3386221311, 10066421, 16287743, 26354171, 42641881, 68996069,339111638519, 180634607, 292272623, 472907251340};341342static const size_t NSDictionaryNumSizeBuckets =343sizeof(NSDictionaryCapacities) / sizeof(uint64_t);344345namespace {346struct DataDescriptor_32 {347uint32_t _buffer;348uint32_t _muts;349uint32_t _used : 25;350uint32_t _kvo : 1;351uint32_t _szidx : 6;352353uint64_t GetSize() {354return (_szidx) >= NSDictionaryNumSizeBuckets ?3550 : NSDictionaryCapacities[_szidx];356}357};358359struct DataDescriptor_64 {360uint64_t _buffer;361uint32_t _muts;362uint32_t _used : 25;363uint32_t _kvo : 1;364uint32_t _szidx : 6;365366uint64_t GetSize() {367return (_szidx) >= NSDictionaryNumSizeBuckets ?3680 : NSDictionaryCapacities[_szidx];369}370};371} // namespace372373using NSDictionaryMSyntheticFrontEnd =374GenericNSDictionaryMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;375376template <typename DD>377uint64_t378__NSDictionaryMSize_Impl(lldb_private::Process &process,379lldb::addr_t valobj_addr, Status &error) {380const lldb::addr_t start_of_descriptor =381valobj_addr + process.GetAddressByteSize();382DD descriptor = DD();383process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor),384error);385if (error.Fail()) {386return 0;387}388return descriptor._used;389}390391uint64_t392__NSDictionaryMSize(lldb_private::Process &process, lldb::addr_t valobj_addr,393Status &error) {394if (process.GetAddressByteSize() == 4) {395return __NSDictionaryMSize_Impl<DataDescriptor_32>(process, valobj_addr,396error);397} else {398return __NSDictionaryMSize_Impl<DataDescriptor_64>(process, valobj_addr,399error);400}401}402403}404} // namespace formatters405} // namespace lldb_private406407template <bool name_entries>408bool lldb_private::formatters::NSDictionarySummaryProvider(409ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {410static constexpr llvm::StringLiteral g_TypeHint("NSDictionary");411ProcessSP process_sp = valobj.GetProcessSP();412if (!process_sp)413return false;414415ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);416417if (!runtime)418return false;419420ObjCLanguageRuntime::ClassDescriptorSP descriptor(421runtime->GetNonKVOClassDescriptor(valobj));422423if (!descriptor || !descriptor->IsValid())424return false;425426uint32_t ptr_size = process_sp->GetAddressByteSize();427bool is_64bit = (ptr_size == 8);428429lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);430431if (!valobj_addr)432return false;433434uint64_t value = 0;435436ConstString class_name(descriptor->GetClassName());437438static const ConstString g_DictionaryI("__NSDictionaryI");439static const ConstString g_DictionaryM("__NSDictionaryM");440static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");441static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable");442static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");443static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");444static const ConstString g_Dictionary0("__NSDictionary0");445static const ConstString g_DictionaryCF("__CFDictionary");446static const ConstString g_DictionaryNSCF("__NSCFDictionary");447static const ConstString g_DictionaryCFRef("CFDictionaryRef");448static const ConstString g_ConstantDictionary("NSConstantDictionary");449450if (class_name.IsEmpty())451return false;452453if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) {454Status error;455value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,456ptr_size, 0, error);457if (error.Fail())458return false;459460value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);461} else if (class_name == g_ConstantDictionary) {462Status error;463value = process_sp->ReadUnsignedIntegerFromMemory(464valobj_addr + 2 * ptr_size, ptr_size, 0, error);465if (error.Fail())466return false;467} else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy ||468class_name == g_DictionaryMFrozen) {469AppleObjCRuntime *apple_runtime =470llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);471Status error;472if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) {473value = Foundation1437::__NSDictionaryMSize(*process_sp, valobj_addr,474error);475} else {476value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,477ptr_size, 0, error);478value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);479}480if (error.Fail())481return false;482} else if (class_name == g_Dictionary1) {483value = 1;484} else if (class_name == g_Dictionary0) {485value = 0;486} else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||487class_name == g_DictionaryCFRef) {488ExecutionContext exe_ctx(process_sp);489CFBasicHash cfbh;490if (!cfbh.Update(valobj_addr, exe_ctx))491return false;492value = cfbh.GetCount();493} else {494auto &map(NSDictionary_Additionals::GetAdditionalSummaries());495for (auto &candidate : map) {496if (candidate.first && candidate.first->Match(class_name))497return candidate.second(valobj, stream, options);498}499return false;500}501502llvm::StringRef prefix, suffix;503if (Language *language = Language::FindPlugin(options.GetLanguage()))504std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);505506stream << prefix;507stream.Printf("%" PRIu64 " %s%s", value, "key/value pair",508value == 1 ? "" : "s");509stream << suffix;510return true;511}512513SyntheticChildrenFrontEnd *514lldb_private::formatters::NSDictionarySyntheticFrontEndCreator(515CXXSyntheticChildren *synth, lldb::ValueObjectSP valobj_sp) {516lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());517if (!process_sp)518return nullptr;519AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(520ObjCLanguageRuntime::Get(*process_sp));521if (!runtime)522return nullptr;523524CompilerType valobj_type(valobj_sp->GetCompilerType());525Flags flags(valobj_type.GetTypeInfo());526527if (flags.IsClear(eTypeIsPointer)) {528Status error;529valobj_sp = valobj_sp->AddressOf(error);530if (error.Fail() || !valobj_sp)531return nullptr;532}533534ObjCLanguageRuntime::ClassDescriptorSP descriptor(535runtime->GetClassDescriptor(*valobj_sp));536537if (!descriptor || !descriptor->IsValid())538return nullptr;539540ConstString class_name(descriptor->GetClassName());541542static const ConstString g_DictionaryI("__NSDictionaryI");543static const ConstString g_DictionaryM("__NSDictionaryM");544static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");545static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable");546static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");547static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");548static const ConstString g_Dictionary0("__NSDictionary0");549static const ConstString g_DictionaryCF("__CFDictionary");550static const ConstString g_DictionaryNSCF("__NSCFDictionary");551static const ConstString g_DictionaryCFRef("CFDictionaryRef");552static const ConstString g_ConstantDictionary("NSConstantDictionary");553554if (class_name.IsEmpty())555return nullptr;556557if (class_name == g_DictionaryI) {558return (new NSDictionaryISyntheticFrontEnd(valobj_sp));559} else if (class_name == g_ConstantDictionary) {560return (new NSConstantDictionarySyntheticFrontEnd(valobj_sp));561} else if (class_name == g_DictionaryM || class_name == g_DictionaryMFrozen) {562if (runtime->GetFoundationVersion() >= 1437) {563return (new Foundation1437::NSDictionaryMSyntheticFrontEnd(valobj_sp));564} else if (runtime->GetFoundationVersion() >= 1428) {565return (new Foundation1428::NSDictionaryMSyntheticFrontEnd(valobj_sp));566} else {567return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp));568}569} else if (class_name == g_DictionaryMLegacy) {570return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp));571} else if (class_name == g_Dictionary1) {572return (new NSDictionary1SyntheticFrontEnd(valobj_sp));573} else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||574class_name == g_DictionaryCFRef) {575return (new NSCFDictionarySyntheticFrontEnd(valobj_sp));576} else {577auto &map(NSDictionary_Additionals::GetAdditionalSynthetics());578for (auto &candidate : map) {579if (candidate.first && candidate.first->Match((class_name)))580return candidate.second(synth, valobj_sp);581}582}583584return nullptr;585}586587lldb_private::formatters::NSDictionaryISyntheticFrontEnd::588NSDictionaryISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)589: SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_type() {}590591lldb_private::formatters::NSDictionaryISyntheticFrontEnd::592~NSDictionaryISyntheticFrontEnd() {593delete m_data_32;594m_data_32 = nullptr;595delete m_data_64;596m_data_64 = nullptr;597}598599size_t lldb_private::formatters::NSDictionaryISyntheticFrontEnd::600GetIndexOfChildWithName(ConstString name) {601const char *item_name = name.GetCString();602uint32_t idx = ExtractIndexFromString(item_name);603if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())604return UINT32_MAX;605return idx;606}607608llvm::Expected<uint32_t> lldb_private::formatters::609NSDictionaryISyntheticFrontEnd::CalculateNumChildren() {610if (!m_data_32 && !m_data_64)611return 0;612return (m_data_32 ? m_data_32->_used : m_data_64->_used);613}614615lldb::ChildCacheState616lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update() {617m_children.clear();618delete m_data_32;619m_data_32 = nullptr;620delete m_data_64;621m_data_64 = nullptr;622m_ptr_size = 0;623ValueObjectSP valobj_sp = m_backend.GetSP();624if (!valobj_sp)625return lldb::ChildCacheState::eRefetch;626m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();627Status error;628error.Clear();629lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());630if (!process_sp)631return lldb::ChildCacheState::eRefetch;632m_ptr_size = process_sp->GetAddressByteSize();633m_order = process_sp->GetByteOrder();634uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;635if (m_ptr_size == 4) {636m_data_32 = new DataDescriptor_32();637process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),638error);639} else {640m_data_64 = new DataDescriptor_64();641process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),642error);643}644if (error.Fail())645return lldb::ChildCacheState::eRefetch;646m_data_ptr = data_location + m_ptr_size;647return lldb::ChildCacheState::eRefetch;648}649650bool lldb_private::formatters::NSDictionaryISyntheticFrontEnd::651MightHaveChildren() {652return true;653}654655lldb::ValueObjectSP656lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex(657uint32_t idx) {658uint32_t num_children = CalculateNumChildrenIgnoringErrors();659660if (idx >= num_children)661return lldb::ValueObjectSP();662663if (m_children.empty()) {664// do the scan phase665lldb::addr_t key_at_idx = 0, val_at_idx = 0;666667uint32_t tries = 0;668uint32_t test_idx = 0;669670while (tries < num_children) {671key_at_idx = m_data_ptr + (2 * test_idx * m_ptr_size);672val_at_idx = key_at_idx + m_ptr_size;673ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();674if (!process_sp)675return lldb::ValueObjectSP();676Status error;677key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);678if (error.Fail())679return lldb::ValueObjectSP();680val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);681if (error.Fail())682return lldb::ValueObjectSP();683684test_idx++;685686if (!key_at_idx || !val_at_idx)687continue;688tries++;689690DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,691lldb::ValueObjectSP()};692693m_children.push_back(descriptor);694}695}696697if (idx >= m_children.size()) // should never happen698return lldb::ValueObjectSP();699700DictionaryItemDescriptor &dict_item = m_children[idx];701if (!dict_item.valobj_sp) {702if (!m_pair_type.IsValid()) {703TargetSP target_sp(m_backend.GetTargetSP());704if (!target_sp)705return ValueObjectSP();706m_pair_type = GetLLDBNSPairType(target_sp);707}708if (!m_pair_type.IsValid())709return ValueObjectSP();710711WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));712713if (m_ptr_size == 8) {714uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();715*data_ptr = dict_item.key_ptr;716*(data_ptr + 1) = dict_item.val_ptr;717} else {718uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();719*data_ptr = dict_item.key_ptr;720*(data_ptr + 1) = dict_item.val_ptr;721}722723StreamString idx_name;724idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);725DataExtractor data(buffer_sp, m_order, m_ptr_size);726dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,727m_exe_ctx_ref, m_pair_type);728}729return dict_item.valobj_sp;730}731732lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::733NSCFDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)734: SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_hashtable(),735m_pair_type() {}736737size_t lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::738GetIndexOfChildWithName(ConstString name) {739const char *item_name = name.GetCString();740const uint32_t idx = ExtractIndexFromString(item_name);741if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())742return UINT32_MAX;743return idx;744}745746llvm::Expected<uint32_t> lldb_private::formatters::747NSCFDictionarySyntheticFrontEnd::CalculateNumChildren() {748if (!m_hashtable.IsValid())749return 0;750return m_hashtable.GetCount();751}752753lldb::ChildCacheState754lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::Update() {755m_children.clear();756ValueObjectSP valobj_sp = m_backend.GetSP();757m_ptr_size = 0;758if (!valobj_sp)759return lldb::ChildCacheState::eRefetch;760m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();761762lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());763if (!process_sp)764return lldb::ChildCacheState::eRefetch;765m_ptr_size = process_sp->GetAddressByteSize();766m_order = process_sp->GetByteOrder();767return m_hashtable.Update(valobj_sp->GetValueAsUnsigned(0), m_exe_ctx_ref)768? lldb::ChildCacheState::eReuse769: lldb::ChildCacheState::eRefetch;770}771772bool lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::773MightHaveChildren() {774return true;775}776777lldb::ValueObjectSP778lldb_private::formatters::NSCFDictionarySyntheticFrontEnd::GetChildAtIndex(779uint32_t idx) {780lldb::addr_t m_keys_ptr = m_hashtable.GetKeyPointer();781lldb::addr_t m_values_ptr = m_hashtable.GetValuePointer();782783const uint32_t num_children = CalculateNumChildrenIgnoringErrors();784785if (idx >= num_children)786return lldb::ValueObjectSP();787788if (m_children.empty()) {789ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();790if (!process_sp)791return lldb::ValueObjectSP();792793Status error;794lldb::addr_t key_at_idx = 0, val_at_idx = 0;795796uint32_t tries = 0;797uint32_t test_idx = 0;798799// Iterate over inferior memory, reading key/value pointers by shifting each800// cursor by test_index * m_ptr_size. Returns an empty ValueObject if a read801// fails, otherwise, continue until the number of tries matches the number802// of childen.803while (tries < num_children) {804key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);805val_at_idx = m_values_ptr + (test_idx * m_ptr_size);806807key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);808if (error.Fail())809return lldb::ValueObjectSP();810val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);811if (error.Fail())812return lldb::ValueObjectSP();813814test_idx++;815816if (!key_at_idx || !val_at_idx)817continue;818tries++;819820DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,821lldb::ValueObjectSP()};822823m_children.push_back(descriptor);824}825}826827if (idx >= m_children.size()) // should never happen828return lldb::ValueObjectSP();829830DictionaryItemDescriptor &dict_item = m_children[idx];831if (!dict_item.valobj_sp) {832if (!m_pair_type.IsValid()) {833TargetSP target_sp(m_backend.GetTargetSP());834if (!target_sp)835return ValueObjectSP();836m_pair_type = GetLLDBNSPairType(target_sp);837}838if (!m_pair_type.IsValid())839return ValueObjectSP();840841WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));842843switch (m_ptr_size) {844case 0: // architecture has no clue - fail845return lldb::ValueObjectSP();846case 4: {847uint32_t *data_ptr = reinterpret_cast<uint32_t *>(buffer_sp->GetBytes());848*data_ptr = dict_item.key_ptr;849*(data_ptr + 1) = dict_item.val_ptr;850} break;851case 8: {852uint64_t *data_ptr = reinterpret_cast<uint64_t *>(buffer_sp->GetBytes());853*data_ptr = dict_item.key_ptr;854*(data_ptr + 1) = dict_item.val_ptr;855} break;856default:857lldbassert(false && "pointer size is not 4 nor 8");858}859860StreamString idx_name;861idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);862DataExtractor data(buffer_sp, m_order, m_ptr_size);863dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,864m_exe_ctx_ref, m_pair_type);865}866return dict_item.valobj_sp;867}868869lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd::870NSConstantDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)871: SyntheticChildrenFrontEnd(*valobj_sp) {}872873size_t lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd::874GetIndexOfChildWithName(ConstString name) {875const char *item_name = name.GetCString();876uint32_t idx = ExtractIndexFromString(item_name);877if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())878return UINT32_MAX;879return idx;880}881882llvm::Expected<uint32_t> lldb_private::formatters::883NSConstantDictionarySyntheticFrontEnd::CalculateNumChildren() {884return m_size;885}886887lldb::ChildCacheState888lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd::Update() {889ValueObjectSP valobj_sp = m_backend.GetSP();890if (!valobj_sp)891return lldb::ChildCacheState::eRefetch;892m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();893Status error;894error.Clear();895lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());896if (!process_sp)897return lldb::ChildCacheState::eRefetch;898m_ptr_size = process_sp->GetAddressByteSize();899m_order = process_sp->GetByteOrder();900uint64_t valobj_addr = valobj_sp->GetValueAsUnsigned(0);901m_size = process_sp->ReadUnsignedIntegerFromMemory(902valobj_addr + 2 * m_ptr_size, m_ptr_size, 0, error);903if (error.Fail())904return lldb::ChildCacheState::eRefetch;905m_keys_ptr =906process_sp->ReadPointerFromMemory(valobj_addr + 3 * m_ptr_size, error);907if (error.Fail())908return lldb::ChildCacheState::eRefetch;909m_objects_ptr =910process_sp->ReadPointerFromMemory(valobj_addr + 4 * m_ptr_size, error);911912return error.Success() ? lldb::ChildCacheState::eReuse913: lldb::ChildCacheState::eRefetch;914}915916bool lldb_private::formatters::NSConstantDictionarySyntheticFrontEnd::917MightHaveChildren() {918return true;919}920921lldb::ValueObjectSP lldb_private::formatters::922NSConstantDictionarySyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {923uint32_t num_children = CalculateNumChildrenIgnoringErrors();924925if (idx >= num_children)926return lldb::ValueObjectSP();927928if (m_children.empty()) {929// do the scan phase930lldb::addr_t key_at_idx = 0, val_at_idx = 0;931ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();932if (!process_sp)933return lldb::ValueObjectSP();934935for (unsigned int child = 0; child < num_children; ++child) {936Status error;937key_at_idx = process_sp->ReadPointerFromMemory(938m_keys_ptr + child * m_ptr_size, error);939if (error.Fail())940return lldb::ValueObjectSP();941val_at_idx = process_sp->ReadPointerFromMemory(942m_objects_ptr + child * m_ptr_size, error);943if (error.Fail())944return lldb::ValueObjectSP();945DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,946lldb::ValueObjectSP()};947m_children.push_back(descriptor);948}949}950951if (idx >= m_children.size()) // should never happen952return lldb::ValueObjectSP();953954DictionaryItemDescriptor &dict_item = m_children[idx];955if (!dict_item.valobj_sp) {956if (!m_pair_type.IsValid()) {957TargetSP target_sp(m_backend.GetTargetSP());958if (!target_sp)959return ValueObjectSP();960m_pair_type = GetLLDBNSPairType(target_sp);961}962if (!m_pair_type.IsValid())963return ValueObjectSP();964965WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));966967if (m_ptr_size == 8) {968uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();969*data_ptr = dict_item.key_ptr;970*(data_ptr + 1) = dict_item.val_ptr;971} else {972uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();973*data_ptr = dict_item.key_ptr;974*(data_ptr + 1) = dict_item.val_ptr;975}976977StreamString idx_name;978idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);979DataExtractor data(buffer_sp, m_order, m_ptr_size);980dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,981m_exe_ctx_ref, m_pair_type);982}983return dict_item.valobj_sp;984}985986lldb_private::formatters::NSDictionary1SyntheticFrontEnd::987NSDictionary1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)988: SyntheticChildrenFrontEnd(*valobj_sp.get()), m_pair(nullptr) {}989990size_t lldb_private::formatters::NSDictionary1SyntheticFrontEnd::991GetIndexOfChildWithName(ConstString name) {992static const ConstString g_zero("[0]");993return name == g_zero ? 0 : UINT32_MAX;994}995996llvm::Expected<uint32_t> lldb_private::formatters::997NSDictionary1SyntheticFrontEnd::CalculateNumChildren() {998return 1;999}10001001lldb::ChildCacheState1002lldb_private::formatters::NSDictionary1SyntheticFrontEnd::Update() {1003m_pair.reset();1004return lldb::ChildCacheState::eRefetch;1005}10061007bool lldb_private::formatters::NSDictionary1SyntheticFrontEnd::1008MightHaveChildren() {1009return true;1010}10111012lldb::ValueObjectSP1013lldb_private::formatters::NSDictionary1SyntheticFrontEnd::GetChildAtIndex(1014uint32_t idx) {1015if (idx != 0)1016return lldb::ValueObjectSP();10171018if (m_pair.get())1019return m_pair;10201021auto process_sp(m_backend.GetProcessSP());1022if (!process_sp)1023return nullptr;10241025auto ptr_size = process_sp->GetAddressByteSize();10261027lldb::addr_t key_ptr =1028m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS) + ptr_size;1029lldb::addr_t value_ptr = key_ptr + ptr_size;10301031Status error;10321033lldb::addr_t value_at_idx = process_sp->ReadPointerFromMemory(key_ptr, error);1034if (error.Fail())1035return nullptr;1036lldb::addr_t key_at_idx = process_sp->ReadPointerFromMemory(value_ptr, error);1037if (error.Fail())1038return nullptr;10391040auto pair_type =1041GetLLDBNSPairType(process_sp->GetTarget().shared_from_this());10421043WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * ptr_size, 0));10441045if (ptr_size == 8) {1046uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();1047*data_ptr = key_at_idx;1048*(data_ptr + 1) = value_at_idx;1049} else {1050uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();1051*data_ptr = key_at_idx;1052*(data_ptr + 1) = value_at_idx;1053}10541055DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size);1056m_pair = CreateValueObjectFromData(1057"[0]", data, m_backend.GetExecutionContextRef(), pair_type);10581059return m_pair;1060}10611062template <typename D32, typename D64>1063lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32, D64>::1064GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)1065: SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(),1066m_data_32(nullptr), m_data_64(nullptr), m_pair_type() {}10671068template <typename D32, typename D64>1069lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<1070D32, D64>::GenericNSDictionaryMSyntheticFrontEnd::1071~GenericNSDictionaryMSyntheticFrontEnd() {1072delete m_data_32;1073m_data_32 = nullptr;1074delete m_data_64;1075m_data_64 = nullptr;1076}10771078template <typename D32, typename D64>1079size_t lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<1080D32, D64>::GetIndexOfChildWithName(ConstString name) {1081const char *item_name = name.GetCString();1082uint32_t idx = ExtractIndexFromString(item_name);1083if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())1084return UINT32_MAX;1085return idx;1086}10871088template <typename D32, typename D64>1089llvm::Expected<uint32_t>1090lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<1091D32, D64>::CalculateNumChildren() {1092if (!m_data_32 && !m_data_64)1093return 0;1094return (m_data_32 ? (uint32_t)m_data_32->_used : (uint32_t)m_data_64->_used);1095}10961097template <typename D32, typename D64>1098lldb::ChildCacheState1099lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,1100D64>::Update() {1101m_children.clear();1102ValueObjectSP valobj_sp = m_backend.GetSP();1103m_ptr_size = 0;1104delete m_data_32;1105m_data_32 = nullptr;1106delete m_data_64;1107m_data_64 = nullptr;1108if (!valobj_sp)1109return lldb::ChildCacheState::eRefetch;1110m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();1111Status error;1112error.Clear();1113lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());1114if (!process_sp)1115return lldb::ChildCacheState::eRefetch;1116m_ptr_size = process_sp->GetAddressByteSize();1117m_order = process_sp->GetByteOrder();1118uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;1119if (m_ptr_size == 4) {1120m_data_32 = new D32();1121process_sp->ReadMemory(data_location, m_data_32, sizeof(D32),1122error);1123} else {1124m_data_64 = new D64();1125process_sp->ReadMemory(data_location, m_data_64, sizeof(D64),1126error);1127}11281129return error.Success() ? lldb::ChildCacheState::eReuse1130: lldb::ChildCacheState::eRefetch;1131}11321133template <typename D32, typename D64>1134bool1135lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>::1136MightHaveChildren() {1137return true;1138}11391140template <typename D32, typename D64>1141lldb::ValueObjectSP1142lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<1143D32, D64>::GetChildAtIndex(uint32_t idx) {1144lldb::addr_t m_keys_ptr;1145lldb::addr_t m_values_ptr;1146if (m_data_32) {1147uint32_t size = m_data_32->GetSize();1148m_keys_ptr = m_data_32->_buffer;1149m_values_ptr = m_data_32->_buffer + (m_ptr_size * size);1150} else {1151uint32_t size = m_data_64->GetSize();1152m_keys_ptr = m_data_64->_buffer;1153m_values_ptr = m_data_64->_buffer + (m_ptr_size * size);1154}11551156uint32_t num_children = CalculateNumChildrenIgnoringErrors();11571158if (idx >= num_children)1159return lldb::ValueObjectSP();11601161if (m_children.empty()) {1162// do the scan phase1163lldb::addr_t key_at_idx = 0, val_at_idx = 0;11641165uint32_t tries = 0;1166uint32_t test_idx = 0;11671168while (tries < num_children) {1169key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);1170val_at_idx = m_values_ptr + (test_idx * m_ptr_size);1171;1172ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();1173if (!process_sp)1174return lldb::ValueObjectSP();1175Status error;1176key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);1177if (error.Fail())1178return lldb::ValueObjectSP();1179val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);1180if (error.Fail())1181return lldb::ValueObjectSP();11821183test_idx++;11841185if (!key_at_idx || !val_at_idx)1186continue;1187tries++;11881189DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,1190lldb::ValueObjectSP()};11911192m_children.push_back(descriptor);1193}1194}11951196if (idx >= m_children.size()) // should never happen1197return lldb::ValueObjectSP();11981199DictionaryItemDescriptor &dict_item = m_children[idx];1200if (!dict_item.valobj_sp) {1201if (!m_pair_type.IsValid()) {1202TargetSP target_sp(m_backend.GetTargetSP());1203if (!target_sp)1204return ValueObjectSP();1205m_pair_type = GetLLDBNSPairType(target_sp);1206}1207if (!m_pair_type.IsValid())1208return ValueObjectSP();12091210WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));12111212if (m_ptr_size == 8) {1213uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();1214*data_ptr = dict_item.key_ptr;1215*(data_ptr + 1) = dict_item.val_ptr;1216} else {1217uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();1218*data_ptr = dict_item.key_ptr;1219*(data_ptr + 1) = dict_item.val_ptr;1220}12211222StreamString idx_name;1223idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);1224DataExtractor data(buffer_sp, m_order, m_ptr_size);1225dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,1226m_exe_ctx_ref, m_pair_type);1227}1228return dict_item.valobj_sp;1229}12301231lldb_private::formatters::Foundation1100::NSDictionaryMSyntheticFrontEnd::1232NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)1233: SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_type() {}12341235lldb_private::formatters::Foundation1100::1236NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd() {1237delete m_data_32;1238m_data_32 = nullptr;1239delete m_data_64;1240m_data_64 = nullptr;1241}12421243size_t1244lldb_private::formatters::Foundation1100::1245NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName(ConstString name) {1246const char *item_name = name.GetCString();1247uint32_t idx = ExtractIndexFromString(item_name);1248if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())1249return UINT32_MAX;1250return idx;1251}12521253llvm::Expected<uint32_t> lldb_private::formatters::Foundation1100::1254NSDictionaryMSyntheticFrontEnd::CalculateNumChildren() {1255if (!m_data_32 && !m_data_64)1256return 0;1257return (m_data_32 ? m_data_32->_used : m_data_64->_used);1258}12591260lldb::ChildCacheState lldb_private::formatters::Foundation1100::1261NSDictionaryMSyntheticFrontEnd::Update() {1262m_children.clear();1263ValueObjectSP valobj_sp = m_backend.GetSP();1264m_ptr_size = 0;1265delete m_data_32;1266m_data_32 = nullptr;1267delete m_data_64;1268m_data_64 = nullptr;1269if (!valobj_sp)1270return lldb::ChildCacheState::eRefetch;1271m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();1272Status error;1273error.Clear();1274lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());1275if (!process_sp)1276return lldb::ChildCacheState::eRefetch;1277m_ptr_size = process_sp->GetAddressByteSize();1278m_order = process_sp->GetByteOrder();1279uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;1280if (m_ptr_size == 4) {1281m_data_32 = new DataDescriptor_32();1282process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),1283error);1284} else {1285m_data_64 = new DataDescriptor_64();1286process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),1287error);1288}12891290return error.Success() ? lldb::ChildCacheState::eReuse1291: lldb::ChildCacheState::eRefetch;1292}12931294bool1295lldb_private::formatters::Foundation1100::1296NSDictionaryMSyntheticFrontEnd::MightHaveChildren() {1297return true;1298}12991300lldb::ValueObjectSP1301lldb_private::formatters::Foundation1100::1302NSDictionaryMSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {1303lldb::addr_t m_keys_ptr =1304(m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr);1305lldb::addr_t m_values_ptr =1306(m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);13071308uint32_t num_children = CalculateNumChildrenIgnoringErrors();13091310if (idx >= num_children)1311return lldb::ValueObjectSP();13121313if (m_children.empty()) {1314// do the scan phase1315lldb::addr_t key_at_idx = 0, val_at_idx = 0;13161317uint32_t tries = 0;1318uint32_t test_idx = 0;13191320while (tries < num_children) {1321key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);1322val_at_idx = m_values_ptr + (test_idx * m_ptr_size);1323;1324ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();1325if (!process_sp)1326return lldb::ValueObjectSP();1327Status error;1328key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);1329if (error.Fail())1330return lldb::ValueObjectSP();1331val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);1332if (error.Fail())1333return lldb::ValueObjectSP();13341335test_idx++;13361337if (!key_at_idx || !val_at_idx)1338continue;1339tries++;13401341DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,1342lldb::ValueObjectSP()};13431344m_children.push_back(descriptor);1345}1346}13471348if (idx >= m_children.size()) // should never happen1349return lldb::ValueObjectSP();13501351DictionaryItemDescriptor &dict_item = m_children[idx];1352if (!dict_item.valobj_sp) {1353if (!m_pair_type.IsValid()) {1354TargetSP target_sp(m_backend.GetTargetSP());1355if (!target_sp)1356return ValueObjectSP();1357m_pair_type = GetLLDBNSPairType(target_sp);1358}1359if (!m_pair_type.IsValid())1360return ValueObjectSP();13611362WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));13631364if (m_ptr_size == 8) {1365uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();1366*data_ptr = dict_item.key_ptr;1367*(data_ptr + 1) = dict_item.val_ptr;1368} else {1369uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();1370*data_ptr = dict_item.key_ptr;1371*(data_ptr + 1) = dict_item.val_ptr;1372}13731374StreamString idx_name;1375idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);1376DataExtractor data(buffer_sp, m_order, m_ptr_size);1377dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,1378m_exe_ctx_ref, m_pair_type);1379}1380return dict_item.valobj_sp;1381}13821383template bool lldb_private::formatters::NSDictionarySummaryProvider<true>(1384ValueObject &, Stream &, const TypeSummaryOptions &);13851386template bool lldb_private::formatters::NSDictionarySummaryProvider<false>(1387ValueObject &, Stream &, const TypeSummaryOptions &);138813891390