118316Swollman//===-- NSSet.cpp -----------------------------------------------*- C++ -*-===// 218316Swollman// 318316Swollman// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 418316Swollman// See https://llvm.org/LICENSE.txt for license information. 518316Swollman// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 618316Swollman// 718316Swollman//===----------------------------------------------------------------------===// 818316Swollman 918316Swollman#include "NSSet.h" 1018316Swollman 1118316Swollman#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" 1218316Swollman#include "lldb/Core/ValueObject.h" 1318316Swollman#include "lldb/Core/ValueObjectConstResult.h" 1418316Swollman#include "lldb/DataFormatters/FormattersHelpers.h" 1518316Swollman#include "lldb/Symbol/ClangASTContext.h" 1618316Swollman#include "lldb/Target/Language.h" 1718316Swollman#include "lldb/Target/Target.h" 1818316Swollman#include "lldb/Utility/DataBufferHeap.h" 1918316Swollman#include "lldb/Utility/Endian.h" 2018316Swollman#include "lldb/Utility/Status.h" 2118316Swollman#include "lldb/Utility/Stream.h" 2218316Swollman 2318316Swollmanusing namespace lldb; 2418316Swollmanusing namespace lldb_private; 2518316Swollmanusing namespace lldb_private::formatters; 2618316Swollman 2718316Swollmanstd::map<ConstString, CXXFunctionSummaryFormat::Callback> & 2846303SmarkmNSSet_Additionals::GetAdditionalSummaries() { 2950476Speter static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map; 3018316Swollman return g_map; 3118316Swollman} 3218316Swollman 3318316Swollmanstd::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> & 3420339SwollmanNSSet_Additionals::GetAdditionalSynthetics() { 3518316Swollman static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> 36126250Sbms g_map; 3746303Smarkm return g_map; 38126250Sbms} 39126250Sbms 40126250Sbmsnamespace lldb_private { 41126250Sbmsnamespace formatters { 42126250Sbmsclass NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd { 4346303Smarkmpublic: 4446303Smarkm NSSetISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 4546303Smarkm 46190715Sphk ~NSSetISyntheticFrontEnd() override; 4718316Swollman 4846303Smarkm size_t CalculateNumChildren() override; 4919880Swollman 5018316Swollman lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 5118316Swollman 5218316Swollman bool Update() override; 5318316Swollman 5418316Swollman bool MightHaveChildren() override; 5518316Swollman 5618316Swollman size_t GetIndexOfChildWithName(ConstString name) override; 5746303Smarkm 5818316Swollmanprivate: 5920339Swollman struct DataDescriptor_32 { 6018316Swollman uint32_t _used : 26; 6118316Swollman uint32_t _szidx : 6; 6218316Swollman }; 6318316Swollman 6419880Swollman struct DataDescriptor_64 { 6519880Swollman uint64_t _used : 58; 6619880Swollman uint32_t _szidx : 6; 6719880Swollman }; 6819880Swollman 6919880Swollman struct SetItemDescriptor { 7019880Swollman lldb::addr_t item_ptr; 7118316Swollman lldb::ValueObjectSP valobj_sp; 7218316Swollman }; 7318316Swollman 7420339Swollman ExecutionContextRef m_exe_ctx_ref; 7520339Swollman uint8_t m_ptr_size; 7620339Swollman DataDescriptor_32 *m_data_32; 7720339Swollman DataDescriptor_64 *m_data_64; 7846303Smarkm lldb::addr_t m_data_ptr; 7946303Smarkm std::vector<SetItemDescriptor> m_children; 8046303Smarkm}; 8120339Swollman 8218316Swollmantemplate <typename D32, typename D64> 8318316Swollmanclass GenericNSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 8418316Swollmanpublic: 8518316Swollman GenericNSSetMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 86126250Sbms 87126250Sbms ~GenericNSSetMSyntheticFrontEnd() override; 88126250Sbms 89126250Sbms size_t CalculateNumChildren() override; 9019880Swollman 9118316Swollman lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 9219880Swollman 9319880Swollman bool Update() override; 9419880Swollman 9519880Swollman bool MightHaveChildren() override; 9619880Swollman 9719880Swollman size_t GetIndexOfChildWithName(ConstString name) override; 9818316Swollman 9918316Swollmanprivate: 10018316Swollman 10119880Swollman struct SetItemDescriptor { 10218316Swollman lldb::addr_t item_ptr; 10318316Swollman lldb::ValueObjectSP valobj_sp; 10418316Swollman }; 10518316Swollman 10618316Swollman ExecutionContextRef m_exe_ctx_ref; 10719880Swollman uint8_t m_ptr_size; 10818316Swollman D32 *m_data_32; 10918316Swollman D64 *m_data_64; 11018316Swollman std::vector<SetItemDescriptor> m_children; 11118316Swollman}; 11218316Swollman 11318316Swollmannamespace Foundation1300 { 11418316Swollman struct DataDescriptor_32 { 11546303Smarkm uint32_t _used : 26; 11618316Swollman uint32_t _size; 11746303Smarkm uint32_t _mutations; 11818316Swollman uint32_t _objs_addr; 11918316Swollman }; 12018316Swollman 12118316Swollman struct DataDescriptor_64 { 12218316Swollman uint64_t _used : 58; 12318316Swollman uint64_t _size; 12419880Swollman uint64_t _mutations; 12519880Swollman uint64_t _objs_addr; 12619880Swollman }; 12720339Swollman 12819880Swollman using NSSetMSyntheticFrontEnd = 12919880Swollman GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; 13019880Swollman} 13119880Swollman 13219880Swollmannamespace Foundation1428 { 13319880Swollman struct DataDescriptor_32 { 13419880Swollman uint32_t _used : 26; 13519880Swollman uint32_t _size; 13620339Swollman uint32_t _objs_addr; 13720339Swollman uint32_t _mutations; 13820339Swollman }; 13920339Swollman 14020339Swollman struct DataDescriptor_64 { 14120339Swollman uint64_t _used : 58; 14220339Swollman uint64_t _size; 14320339Swollman uint64_t _objs_addr; 14419880Swollman uint64_t _mutations; 14518316Swollman }; 14618316Swollman 14718316Swollman using NSSetMSyntheticFrontEnd = 14818316Swollman GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; 14918316Swollman} 15018316Swollman 15118316Swollmannamespace Foundation1437 { 15218316Swollman struct DataDescriptor_32 { 15318316Swollman uint32_t _cow; 15418316Swollman // __table storage 15518316Swollman uint32_t _objs_addr; 15618316Swollman uint32_t _muts; 15718316Swollman uint32_t _used : 26; 15818316Swollman uint32_t _szidx : 6; 15918316Swollman }; 16018316Swollman 16118316Swollman struct DataDescriptor_64 { 16218316Swollman uint64_t _cow; 16318316Swollman // __Table storage 16418316Swollman uint64_t _objs_addr; 16518316Swollman uint32_t _muts; 16618316Swollman uint32_t _used : 26; 16718316Swollman uint32_t _szidx : 6; 16818316Swollman }; 16946303Smarkm 17046303Smarkm using NSSetMSyntheticFrontEnd = 17146303Smarkm GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; 17218316Swollman 17318316Swollman template <typename DD> 17446303Smarkm uint64_t 17520339Swollman __NSSetMSize_Impl(lldb_private::Process &process, lldb::addr_t valobj_addr, 17618316Swollman Status &error) { 17746303Smarkm const lldb::addr_t start_of_descriptor = 17818316Swollman valobj_addr + process.GetAddressByteSize(); 17918316Swollman DD descriptor = DD(); 18018316Swollman process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor), 18118316Swollman error); 18218316Swollman if (error.Fail()) { 18318316Swollman return 0; 18420339Swollman } 18520339Swollman return descriptor._used; 18620339Swollman } 18720339Swollman 18820339Swollman uint64_t 18920339Swollman __NSSetMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, 19046303Smarkm Status &error) { 191230045Skevlo if (process.GetAddressByteSize() == 4) { 19218316Swollman return __NSSetMSize_Impl<DataDescriptor_32>(process, valobj_addr, error); 19318316Swollman } else { 19418316Swollman return __NSSetMSize_Impl<DataDescriptor_64>(process, valobj_addr, error); 19518316Swollman } 19646303Smarkm } 19746303Smarkm} 19846303Smarkm 19946303Smarkmclass NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 20046303Smarkmpublic: 20118316Swollman NSSetCodeRunningSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 20218316Swollman 20318316Swollman ~NSSetCodeRunningSyntheticFrontEnd() override; 20418316Swollman 20518316Swollman size_t CalculateNumChildren() override; 20618316Swollman 20718316Swollman lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 20846303Smarkm 20946303Smarkm bool Update() override; 21046303Smarkm 21146303Smarkm bool MightHaveChildren() override; 21246303Smarkm 21346303Smarkm size_t GetIndexOfChildWithName(ConstString name) override; 21418316Swollman}; 21518316Swollman} // namespace formatters 21618316Swollman} // namespace lldb_private 21718316Swollman 21819880Swollmantemplate <bool cf_style> 21946303Smarkmbool lldb_private::formatters::NSSetSummaryProvider( 22018316Swollman ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { 22119880Swollman static ConstString g_TypeHint("NSSet"); 22218316Swollman 22319880Swollman ProcessSP process_sp = valobj.GetProcessSP(); 22419880Swollman if (!process_sp) 22519880Swollman return false; 22618316Swollman 22718316Swollman ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp); 22819880Swollman 22918316Swollman if (!runtime) 23018316Swollman return false; 23118316Swollman 23218316Swollman ObjCLanguageRuntime::ClassDescriptorSP descriptor( 23319880Swollman runtime->GetClassDescriptor(valobj)); 23418316Swollman 23518316Swollman if (!descriptor || !descriptor->IsValid()) 23618316Swollman return false; 23718316Swollman 23818316Swollman uint32_t ptr_size = process_sp->GetAddressByteSize(); 23918316Swollman bool is_64bit = (ptr_size == 8); 24019880Swollman 24118316Swollman lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 24218316Swollman 24318316Swollman if (!valobj_addr) 24418316Swollman return false; 24518316Swollman 24646303Smarkm uint64_t value = 0; 24746303Smarkm 24846303Smarkm ConstString class_name_cs = descriptor->GetClassName(); 24946303Smarkm const char *class_name = class_name_cs.GetCString(); 25046303Smarkm 25146303Smarkm if (!class_name || !*class_name) 25290868Smike return false; 25390868Smike 25418316Swollman if (!strcmp(class_name, "__NSSetI") || 25518316Swollman !strcmp(class_name, "__NSOrderedSetI")) { 25646303Smarkm Status error; 25718316Swollman value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 25818316Swollman ptr_size, 0, error); 25918316Swollman if (error.Fail()) 26018316Swollman return false; 26118316Swollman value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 26218316Swollman } else if (!strcmp(class_name, "__NSSetM")) { 26318316Swollman AppleObjCRuntime *apple_runtime = 26418316Swollman llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); 26518316Swollman Status error; 26619880Swollman if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { 26718316Swollman value = Foundation1437::__NSSetMSize(*process_sp, valobj_addr, error); 26818316Swollman } else { 26918316Swollman value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 27018316Swollman ptr_size, 0, error); 27118316Swollman value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 27218316Swollman } 27318316Swollman if (error.Fail()) 27418316Swollman return false; 27518316Swollman } else { 27618316Swollman auto &map(NSSet_Additionals::GetAdditionalSummaries()); 27719880Swollman auto iter = map.find(class_name_cs), end = map.end(); 27818316Swollman if (iter != end) 27918316Swollman return iter->second(valobj, stream, options); 28018316Swollman else 28118316Swollman return false; 28218316Swollman } 28319880Swollman 28418316Swollman std::string prefix, suffix; 28518316Swollman if (Language *language = Language::FindPlugin(options.GetLanguage())) { 28618316Swollman if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, 28718316Swollman suffix)) { 28819880Swollman prefix.clear(); 28919880Swollman suffix.clear(); 29018316Swollman } 29118316Swollman } 29218316Swollman 29318316Swollman stream.Printf("%s%" PRIu64 " %s%s%s", prefix.c_str(), value, "element", 29418316Swollman value == 1 ? "" : "s", suffix.c_str()); 29518316Swollman return true; 29618316Swollman} 29718316Swollman 29818316SwollmanSyntheticChildrenFrontEnd * 29918316Swollmanlldb_private::formatters::NSSetSyntheticFrontEndCreator( 30018316Swollman CXXSyntheticChildren *synth, lldb::ValueObjectSP valobj_sp) { 30118316Swollman lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 30219880Swollman if (!process_sp) 30318316Swollman return nullptr; 30418316Swollman ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp); 30518316Swollman if (!runtime) 30618316Swollman return nullptr; 30719880Swollman 30819880Swollman CompilerType valobj_type(valobj_sp->GetCompilerType()); 30918316Swollman Flags flags(valobj_type.GetTypeInfo()); 31018316Swollman 31118316Swollman if (flags.IsClear(eTypeIsPointer)) { 31218316Swollman Status error; 31318316Swollman valobj_sp = valobj_sp->AddressOf(error); 31418316Swollman if (error.Fail() || !valobj_sp) 31519880Swollman return nullptr; 31618316Swollman } 317126250Sbms 31818316Swollman ObjCLanguageRuntime::ClassDescriptorSP descriptor( 31919880Swollman runtime->GetClassDescriptor(*valobj_sp)); 32018316Swollman 32118316Swollman if (!descriptor || !descriptor->IsValid()) 32218316Swollman return nullptr; 32346303Smarkm 32446303Smarkm ConstString class_name_cs = descriptor->GetClassName(); 32518316Swollman const char *class_name = class_name_cs.GetCString(); 32618316Swollman 32718316Swollman if (!class_name || !*class_name) 32846303Smarkm return nullptr; 32919880Swollman 33046303Smarkm if (!strcmp(class_name, "__NSSetI") || 33119880Swollman !strcmp(class_name, "__NSOrderedSetI")) { 33219880Swollman return (new NSSetISyntheticFrontEnd(valobj_sp)); 33318316Swollman } else if (!strcmp(class_name, "__NSSetM")) { 33419880Swollman AppleObjCRuntime *apple_runtime = 33519880Swollman llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); 33619880Swollman if (apple_runtime) { 33719880Swollman if (apple_runtime->GetFoundationVersion() >= 1437) 33819880Swollman return (new Foundation1437::NSSetMSyntheticFrontEnd(valobj_sp)); 33919880Swollman else if (apple_runtime->GetFoundationVersion() >= 1428) 34018316Swollman return (new Foundation1428::NSSetMSyntheticFrontEnd(valobj_sp)); 34119880Swollman else 34219880Swollman return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp)); 34319880Swollman } else { 34419880Swollman return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp)); 34518316Swollman } 34618316Swollman } else { 34719880Swollman auto &map(NSSet_Additionals::GetAdditionalSynthetics()); 34819880Swollman auto iter = map.find(class_name_cs), end = map.end(); 34919880Swollman if (iter != end) 35019880Swollman return iter->second(synth, valobj_sp); 35119880Swollman return nullptr; 35219880Swollman } 353190711Sphk} 35418316Swollman 35518316Swollmanlldb_private::formatters::NSSetISyntheticFrontEnd::NSSetISyntheticFrontEnd( 35619880Swollman lldb::ValueObjectSP valobj_sp) 35719880Swollman : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), 35819880Swollman m_data_32(nullptr), m_data_64(nullptr) { 35919880Swollman if (valobj_sp) 36018316Swollman Update(); 36118316Swollman} 36220339Swollman 36320339Swollmanlldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd() { 36418316Swollman delete m_data_32; 36518316Swollman m_data_32 = nullptr; 36618316Swollman delete m_data_64; 36746303Smarkm m_data_64 = nullptr; 36818316Swollman} 36920339Swollman 37046303Smarkmsize_t 37146303Smarkmlldb_private::formatters::NSSetISyntheticFrontEnd::GetIndexOfChildWithName( 37246303Smarkm ConstString name) { 37346303Smarkm const char *item_name = name.GetCString(); 37446303Smarkm uint32_t idx = ExtractIndexFromString(item_name); 37519880Swollman if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 37646303Smarkm return UINT32_MAX; 37746303Smarkm return idx; 37819880Swollman} 37919880Swollman 38019880Swollmansize_t 38119880Swollmanlldb_private::formatters::NSSetISyntheticFrontEnd::CalculateNumChildren() { 38219880Swollman if (!m_data_32 && !m_data_64) 38319880Swollman return 0; 38420339Swollman return (m_data_32 ? m_data_32->_used : m_data_64->_used); 38519880Swollman} 38619880Swollman 38719880Swollmanbool lldb_private::formatters::NSSetISyntheticFrontEnd::Update() { 38819880Swollman m_children.clear(); 38937815Sphk delete m_data_32; 39019880Swollman m_data_32 = nullptr; 39119880Swollman delete m_data_64; 39219880Swollman m_data_64 = nullptr; 39319880Swollman m_ptr_size = 0; 39419880Swollman ValueObjectSP valobj_sp = m_backend.GetSP(); 39519880Swollman if (!valobj_sp) 39619880Swollman return false; 39719880Swollman if (!valobj_sp) 39819880Swollman return false; 39919880Swollman m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 40019880Swollman Status error; 40119880Swollman if (valobj_sp->IsPointerType()) { 40219880Swollman valobj_sp = valobj_sp->Dereference(error); 40319880Swollman if (error.Fail() || !valobj_sp) 40419880Swollman return false; 40519880Swollman } 40619880Swollman error.Clear(); 40719880Swollman lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 40819880Swollman if (!process_sp) 40919880Swollman return false; 41019880Swollman m_ptr_size = process_sp->GetAddressByteSize(); 41119880Swollman uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size; 41219880Swollman if (m_ptr_size == 4) { 41319880Swollman m_data_32 = new DataDescriptor_32(); 41419880Swollman process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), 41519880Swollman error); 41619880Swollman } else { 41719880Swollman m_data_64 = new DataDescriptor_64(); 41820339Swollman process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), 41920339Swollman error); 42020339Swollman } 42146303Smarkm if (error.Fail()) 42219880Swollman return false; 42346303Smarkm m_data_ptr = data_location + m_ptr_size; 42446303Smarkm return false; 42519880Swollman} 42619880Swollman 42719880Swollmanbool lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren() { 42819880Swollman return true; 42919880Swollman} 43019880Swollman 43119880Swollmanlldb::ValueObjectSP 43219880Swollmanlldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex(size_t idx) { 43319880Swollman uint32_t num_children = CalculateNumChildren(); 43419880Swollman 43519880Swollman if (idx >= num_children) 43619880Swollman return lldb::ValueObjectSP(); 43719880Swollman 43819880Swollman ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 43919880Swollman if (!process_sp) 44046303Smarkm return lldb::ValueObjectSP(); 44119880Swollman 44219880Swollman if (m_children.empty()) { 44319880Swollman // do the scan phase 44419880Swollman lldb::addr_t obj_at_idx = 0; 44519880Swollman 44620339Swollman uint32_t tries = 0; 44719880Swollman uint32_t test_idx = 0; 44819880Swollman 44919880Swollman while (tries < num_children) { 45046303Smarkm obj_at_idx = m_data_ptr + (test_idx * m_ptr_size); 45146303Smarkm if (!process_sp) 45246303Smarkm return lldb::ValueObjectSP(); 45346303Smarkm Status error; 45446303Smarkm obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error); 45546303Smarkm if (error.Fail()) 45619880Swollman return lldb::ValueObjectSP(); 45719880Swollman 45820339Swollman test_idx++; 45919880Swollman 46019880Swollman if (!obj_at_idx) 46119880Swollman continue; 46219880Swollman tries++; 46319880Swollman 46419880Swollman SetItemDescriptor descriptor = {obj_at_idx, lldb::ValueObjectSP()}; 46519880Swollman 46620339Swollman m_children.push_back(descriptor); 46720339Swollman } 46819880Swollman } 46946303Smarkm 47020339Swollman if (idx >= m_children.size()) // should never happen 47120339Swollman return lldb::ValueObjectSP(); 47220339Swollman 47346303Smarkm SetItemDescriptor &set_item = m_children[idx]; 47420339Swollman if (!set_item.valobj_sp) { 47519880Swollman auto ptr_size = process_sp->GetAddressByteSize(); 47619880Swollman DataBufferHeap buffer(ptr_size, 0); 47719880Swollman switch (ptr_size) { 47820339Swollman case 0: // architecture has no clue?? - fail 47919880Swollman return lldb::ValueObjectSP(); 48019880Swollman case 4: 48119880Swollman *((uint32_t *)buffer.GetBytes()) = (uint32_t)set_item.item_ptr; 482190718Sphk break; 48320339Swollman case 8: 48446303Smarkm *((uint64_t *)buffer.GetBytes()) = (uint64_t)set_item.item_ptr; 48519880Swollman break; 48620339Swollman default: 48720339Swollman assert(false && "pointer size is not 4 nor 8 - get out of here ASAP"); 48820339Swollman } 48920339Swollman StreamString idx_name; 49020339Swollman idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 49119880Swollman 49246303Smarkm DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), 49320339Swollman process_sp->GetByteOrder(), 49420339Swollman process_sp->GetAddressByteSize()); 49519880Swollman 49620339Swollman set_item.valobj_sp = CreateValueObjectFromData( 49720339Swollman idx_name.GetString(), data, m_exe_ctx_ref, 49820339Swollman m_backend.GetCompilerType().GetBasicTypeFromAST( 49920339Swollman lldb::eBasicTypeObjCID)); 50019880Swollman } 50120339Swollman return set_item.valobj_sp; 50220339Swollman} 50320339Swollman 50420339Swollmantemplate <typename D32, typename D64> 50519880Swollmanlldb_private::formatters:: 50620339Swollman GenericNSSetMSyntheticFrontEnd<D32, D64>::GenericNSSetMSyntheticFrontEnd( 50719880Swollman lldb::ValueObjectSP valobj_sp) 50819880Swollman : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), 50919880Swollman m_data_32(nullptr), m_data_64(nullptr) { 51019880Swollman if (valobj_sp) 51120339Swollman Update(); 51219880Swollman} 51319880Swollman 51420339Swollmantemplate <typename D32, typename D64> 51520339Swollmanlldb_private::formatters:: 51619880Swollman GenericNSSetMSyntheticFrontEnd<D32, D64>::~GenericNSSetMSyntheticFrontEnd() { 51719880Swollman delete m_data_32; 51819880Swollman m_data_32 = nullptr; 51919880Swollman delete m_data_64; 52020339Swollman m_data_64 = nullptr; 52119880Swollman} 52220339Swollman 52320339Swollmantemplate <typename D32, typename D64> 52420339Swollmansize_t 52520339Swollmanlldb_private::formatters:: 52620339Swollman GenericNSSetMSyntheticFrontEnd<D32, D64>::GetIndexOfChildWithName( 52720339Swollman ConstString name) { 52820339Swollman const char *item_name = name.GetCString(); 52920339Swollman uint32_t idx = ExtractIndexFromString(item_name); 53020339Swollman if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 53120339Swollman return UINT32_MAX; 53220339Swollman return idx; 53320339Swollman} 53420339Swollman 53520339Swollmantemplate <typename D32, typename D64> 53620339Swollmansize_t 53720339Swollmanlldb_private::formatters:: 53819880Swollman GenericNSSetMSyntheticFrontEnd<D32, D64>::CalculateNumChildren() { 53919880Swollman if (!m_data_32 && !m_data_64) 54020339Swollman return 0; 54120339Swollman return (m_data_32 ? m_data_32->_used : m_data_64->_used); 54219880Swollman} 54346303Smarkm 54420339Swollmantemplate <typename D32, typename D64> 54519880Swollmanbool 54619880Swollmanlldb_private::formatters:: 54719880Swollman GenericNSSetMSyntheticFrontEnd<D32, D64>::Update() { 54846303Smarkm m_children.clear(); 54946303Smarkm ValueObjectSP valobj_sp = m_backend.GetSP(); 55046303Smarkm m_ptr_size = 0; 55146303Smarkm delete m_data_32; 55246303Smarkm m_data_32 = nullptr; 55346303Smarkm delete m_data_64; 55446303Smarkm m_data_64 = nullptr; 55546303Smarkm if (!valobj_sp) 55646303Smarkm return false; 55746303Smarkm if (!valobj_sp) 55819880Swollman return false; 55919880Swollman m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 56046303Smarkm Status error; 56120339Swollman if (valobj_sp->IsPointerType()) { 56220339Swollman valobj_sp = valobj_sp->Dereference(error); 56318316Swollman if (error.Fail() || !valobj_sp) 56419880Swollman return false; 56519880Swollman } 56618316Swollman error.Clear(); 56718316Swollman lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 56818316Swollman if (!process_sp) 56918316Swollman return false; 57046303Smarkm m_ptr_size = process_sp->GetAddressByteSize(); 57119880Swollman uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size; 57219880Swollman if (m_ptr_size == 4) { 57346303Smarkm m_data_32 = new D32(); 57446303Smarkm process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), 57546303Smarkm error); 57646303Smarkm } else { 57718316Swollman m_data_64 = new D64(); 57818316Swollman process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), 57946303Smarkm error); 58019880Swollman } 58135306Sphk if (error.Fail()) 58246303Smarkm return false; 58346303Smarkm return false; 58446303Smarkm} 58546303Smarkm 58618316Swollmantemplate <typename D32, typename D64> 58746303Smarkmbool 58846303Smarkmlldb_private::formatters:: 58918316Swollman GenericNSSetMSyntheticFrontEnd<D32, D64>::MightHaveChildren() { 59018316Swollman return true; 59118316Swollman} 59246303Smarkm 59318316Swollmantemplate <typename D32, typename D64> 59446303Smarkmlldb::ValueObjectSP 59518316Swollmanlldb_private::formatters:: 59618316Swollman GenericNSSetMSyntheticFrontEnd<D32, D64>::GetChildAtIndex(size_t idx) { 59718316Swollman lldb::addr_t m_objs_addr = 59846303Smarkm (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr); 59918316Swollman 60090868Smike uint32_t num_children = CalculateNumChildren(); 60118316Swollman 60218316Swollman if (idx >= num_children) 60318316Swollman return lldb::ValueObjectSP(); 60418316Swollman 60518316Swollman ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 60646303Smarkm if (!process_sp) 60746303Smarkm return lldb::ValueObjectSP(); 60846303Smarkm 60946303Smarkm if (m_children.empty()) { 61046303Smarkm // do the scan phase 61146303Smarkm lldb::addr_t obj_at_idx = 0; 61246303Smarkm 61346303Smarkm uint32_t tries = 0; 61446303Smarkm uint32_t test_idx = 0; 61546303Smarkm 61646303Smarkm while (tries < num_children) { 61746303Smarkm obj_at_idx = m_objs_addr + (test_idx * m_ptr_size); 61846303Smarkm if (!process_sp) 61946303Smarkm return lldb::ValueObjectSP(); 62046303Smarkm Status error; 62146303Smarkm obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error); 62246303Smarkm if (error.Fail()) 62346303Smarkm return lldb::ValueObjectSP(); 62446303Smarkm 62546303Smarkm test_idx++; 62646303Smarkm 62746303Smarkm if (!obj_at_idx) 62846303Smarkm continue; 62946303Smarkm tries++; 63046303Smarkm 63118316Swollman SetItemDescriptor descriptor = {obj_at_idx, lldb::ValueObjectSP()}; 63246303Smarkm 63346303Smarkm m_children.push_back(descriptor); 63419880Swollman } 63519880Swollman } 63646303Smarkm 63719880Swollman if (idx >= m_children.size()) // should never happen 63846303Smarkm return lldb::ValueObjectSP(); 63919880Swollman 64019880Swollman SetItemDescriptor &set_item = m_children[idx]; 64119880Swollman if (!set_item.valobj_sp) { 64246303Smarkm auto ptr_size = process_sp->GetAddressByteSize(); 64319880Swollman DataBufferHeap buffer(ptr_size, 0); 64446303Smarkm switch (ptr_size) { 645190718Sphk case 0: // architecture has no clue?? - fail 646190718Sphk return lldb::ValueObjectSP(); 64719880Swollman case 4: 64846303Smarkm *((uint32_t *)buffer.GetBytes()) = (uint32_t)set_item.item_ptr; 64946303Smarkm break; 65046303Smarkm case 8: 65146303Smarkm *((uint64_t *)buffer.GetBytes()) = (uint64_t)set_item.item_ptr; 65246303Smarkm break; 65346303Smarkm default: 65446303Smarkm assert(false && "pointer size is not 4 nor 8 - get out of here ASAP"); 65546303Smarkm } 65646303Smarkm StreamString idx_name; 65746303Smarkm idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 65846303Smarkm 65919880Swollman DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), 66019880Swollman process_sp->GetByteOrder(), 66118316Swollman process_sp->GetAddressByteSize()); 66246303Smarkm 66346303Smarkm set_item.valobj_sp = CreateValueObjectFromData( 66419880Swollman idx_name.GetString(), data, m_exe_ctx_ref, 66518316Swollman m_backend.GetCompilerType().GetBasicTypeFromAST( 66619880Swollman lldb::eBasicTypeObjCID)); 66719880Swollman } 66819880Swollman return set_item.valobj_sp; 66919880Swollman} 67019880Swollman 67119880Swollmantemplate bool lldb_private::formatters::NSSetSummaryProvider<true>( 67219880Swollman ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); 67320339Swollman 67419880Swollmantemplate bool lldb_private::formatters::NSSetSummaryProvider<false>( 67546303Smarkm ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); 67619880Swollman