15ffd83dbSDimitry Andric //===-- NSSet.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 "NSSet.h" 105ffd83dbSDimitry Andric #include "CFBasicHash.h" 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" 135ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 140b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h" 150b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResult.h" 160b57cec5SDimitry Andric #include "lldb/DataFormatters/FormattersHelpers.h" 170b57cec5SDimitry Andric #include "lldb/Target/Language.h" 180b57cec5SDimitry Andric #include "lldb/Target/Target.h" 190b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h" 200b57cec5SDimitry Andric #include "lldb/Utility/Endian.h" 210b57cec5SDimitry Andric #include "lldb/Utility/Status.h" 220b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric using namespace lldb; 250b57cec5SDimitry Andric using namespace lldb_private; 260b57cec5SDimitry Andric using namespace lldb_private::formatters; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric std::map<ConstString, CXXFunctionSummaryFormat::Callback> & 290b57cec5SDimitry Andric NSSet_Additionals::GetAdditionalSummaries() { 300b57cec5SDimitry Andric static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map; 310b57cec5SDimitry Andric return g_map; 320b57cec5SDimitry Andric } 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> & 350b57cec5SDimitry Andric NSSet_Additionals::GetAdditionalSynthetics() { 360b57cec5SDimitry Andric static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> 370b57cec5SDimitry Andric g_map; 380b57cec5SDimitry Andric return g_map; 390b57cec5SDimitry Andric } 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric namespace lldb_private { 420b57cec5SDimitry Andric namespace formatters { 430b57cec5SDimitry Andric class NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd { 440b57cec5SDimitry Andric public: 450b57cec5SDimitry Andric NSSetISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric ~NSSetISyntheticFrontEnd() override; 480b57cec5SDimitry Andric 49*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 500b57cec5SDimitry Andric 51*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 520b57cec5SDimitry Andric 53*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric bool MightHaveChildren() override; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric private: 600b57cec5SDimitry Andric struct DataDescriptor_32 { 610b57cec5SDimitry Andric uint32_t _used : 26; 620b57cec5SDimitry Andric uint32_t _szidx : 6; 630b57cec5SDimitry Andric }; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric struct DataDescriptor_64 { 660b57cec5SDimitry Andric uint64_t _used : 58; 670b57cec5SDimitry Andric uint32_t _szidx : 6; 680b57cec5SDimitry Andric }; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric struct SetItemDescriptor { 710b57cec5SDimitry Andric lldb::addr_t item_ptr; 720b57cec5SDimitry Andric lldb::ValueObjectSP valobj_sp; 730b57cec5SDimitry Andric }; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric ExecutionContextRef m_exe_ctx_ref; 7681ad6265SDimitry Andric uint8_t m_ptr_size = 8; 7781ad6265SDimitry Andric DataDescriptor_32 *m_data_32 = nullptr; 7881ad6265SDimitry Andric DataDescriptor_64 *m_data_64 = nullptr; 79fcaf7f86SDimitry Andric lldb::addr_t m_data_ptr = LLDB_INVALID_ADDRESS; 800b57cec5SDimitry Andric std::vector<SetItemDescriptor> m_children; 810b57cec5SDimitry Andric }; 820b57cec5SDimitry Andric 835ffd83dbSDimitry Andric class NSCFSetSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 845ffd83dbSDimitry Andric public: 855ffd83dbSDimitry Andric NSCFSetSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 865ffd83dbSDimitry Andric 87*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 885ffd83dbSDimitry Andric 89*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 905ffd83dbSDimitry Andric 91*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 925ffd83dbSDimitry Andric 935ffd83dbSDimitry Andric bool MightHaveChildren() override; 945ffd83dbSDimitry Andric 955ffd83dbSDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 965ffd83dbSDimitry Andric 975ffd83dbSDimitry Andric private: 985ffd83dbSDimitry Andric struct SetItemDescriptor { 995ffd83dbSDimitry Andric lldb::addr_t item_ptr; 1005ffd83dbSDimitry Andric lldb::ValueObjectSP valobj_sp; 1015ffd83dbSDimitry Andric }; 1025ffd83dbSDimitry Andric 1035ffd83dbSDimitry Andric ExecutionContextRef m_exe_ctx_ref; 10481ad6265SDimitry Andric uint8_t m_ptr_size = 8; 10581ad6265SDimitry Andric lldb::ByteOrder m_order = lldb::eByteOrderInvalid; 1065ffd83dbSDimitry Andric 1075ffd83dbSDimitry Andric CFBasicHash m_hashtable; 1085ffd83dbSDimitry Andric 1095ffd83dbSDimitry Andric CompilerType m_pair_type; 1105ffd83dbSDimitry Andric std::vector<SetItemDescriptor> m_children; 1115ffd83dbSDimitry Andric }; 1125ffd83dbSDimitry Andric 1130b57cec5SDimitry Andric template <typename D32, typename D64> 1140b57cec5SDimitry Andric class GenericNSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 1150b57cec5SDimitry Andric public: 1160b57cec5SDimitry Andric GenericNSSetMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric ~GenericNSSetMSyntheticFrontEnd() override; 1190b57cec5SDimitry Andric 120*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 1210b57cec5SDimitry Andric 122*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 1230b57cec5SDimitry Andric 124*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric bool MightHaveChildren() override; 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric private: 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric struct SetItemDescriptor { 1330b57cec5SDimitry Andric lldb::addr_t item_ptr; 1340b57cec5SDimitry Andric lldb::ValueObjectSP valobj_sp; 1350b57cec5SDimitry Andric }; 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric ExecutionContextRef m_exe_ctx_ref; 13881ad6265SDimitry Andric uint8_t m_ptr_size = 8; 1390b57cec5SDimitry Andric D32 *m_data_32; 1400b57cec5SDimitry Andric D64 *m_data_64; 1410b57cec5SDimitry Andric std::vector<SetItemDescriptor> m_children; 1420b57cec5SDimitry Andric }; 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric namespace Foundation1300 { 1450b57cec5SDimitry Andric struct DataDescriptor_32 { 1460b57cec5SDimitry Andric uint32_t _used : 26; 1470b57cec5SDimitry Andric uint32_t _size; 1480b57cec5SDimitry Andric uint32_t _mutations; 1490b57cec5SDimitry Andric uint32_t _objs_addr; 1500b57cec5SDimitry Andric }; 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric struct DataDescriptor_64 { 1530b57cec5SDimitry Andric uint64_t _used : 58; 1540b57cec5SDimitry Andric uint64_t _size; 1550b57cec5SDimitry Andric uint64_t _mutations; 1560b57cec5SDimitry Andric uint64_t _objs_addr; 1570b57cec5SDimitry Andric }; 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric using NSSetMSyntheticFrontEnd = 1600b57cec5SDimitry Andric GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric namespace Foundation1428 { 1640b57cec5SDimitry Andric struct DataDescriptor_32 { 1650b57cec5SDimitry Andric uint32_t _used : 26; 1660b57cec5SDimitry Andric uint32_t _size; 1670b57cec5SDimitry Andric uint32_t _objs_addr; 1680b57cec5SDimitry Andric uint32_t _mutations; 1690b57cec5SDimitry Andric }; 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric struct DataDescriptor_64 { 1720b57cec5SDimitry Andric uint64_t _used : 58; 1730b57cec5SDimitry Andric uint64_t _size; 1740b57cec5SDimitry Andric uint64_t _objs_addr; 1750b57cec5SDimitry Andric uint64_t _mutations; 1760b57cec5SDimitry Andric }; 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric using NSSetMSyntheticFrontEnd = 1790b57cec5SDimitry Andric GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric namespace Foundation1437 { 1830b57cec5SDimitry Andric struct DataDescriptor_32 { 1840b57cec5SDimitry Andric uint32_t _cow; 1850b57cec5SDimitry Andric // __table storage 1860b57cec5SDimitry Andric uint32_t _objs_addr; 1870b57cec5SDimitry Andric uint32_t _muts; 1880b57cec5SDimitry Andric uint32_t _used : 26; 1890b57cec5SDimitry Andric uint32_t _szidx : 6; 1900b57cec5SDimitry Andric }; 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric struct DataDescriptor_64 { 1930b57cec5SDimitry Andric uint64_t _cow; 1940b57cec5SDimitry Andric // __Table storage 1950b57cec5SDimitry Andric uint64_t _objs_addr; 1960b57cec5SDimitry Andric uint32_t _muts; 1970b57cec5SDimitry Andric uint32_t _used : 26; 1980b57cec5SDimitry Andric uint32_t _szidx : 6; 1990b57cec5SDimitry Andric }; 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric using NSSetMSyntheticFrontEnd = 2020b57cec5SDimitry Andric GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric template <typename DD> 2050b57cec5SDimitry Andric uint64_t 2060b57cec5SDimitry Andric __NSSetMSize_Impl(lldb_private::Process &process, lldb::addr_t valobj_addr, 2070b57cec5SDimitry Andric Status &error) { 2080b57cec5SDimitry Andric const lldb::addr_t start_of_descriptor = 2090b57cec5SDimitry Andric valobj_addr + process.GetAddressByteSize(); 2100b57cec5SDimitry Andric DD descriptor = DD(); 2110b57cec5SDimitry Andric process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor), 2120b57cec5SDimitry Andric error); 2130b57cec5SDimitry Andric if (error.Fail()) { 2140b57cec5SDimitry Andric return 0; 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric return descriptor._used; 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric uint64_t 2200b57cec5SDimitry Andric __NSSetMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, 2210b57cec5SDimitry Andric Status &error) { 2220b57cec5SDimitry Andric if (process.GetAddressByteSize() == 4) { 2230b57cec5SDimitry Andric return __NSSetMSize_Impl<DataDescriptor_32>(process, valobj_addr, error); 2240b57cec5SDimitry Andric } else { 2250b57cec5SDimitry Andric return __NSSetMSize_Impl<DataDescriptor_64>(process, valobj_addr, error); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 2310b57cec5SDimitry Andric public: 2320b57cec5SDimitry Andric NSSetCodeRunningSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric ~NSSetCodeRunningSyntheticFrontEnd() override; 2350b57cec5SDimitry Andric 236*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 2370b57cec5SDimitry Andric 238*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 2390b57cec5SDimitry Andric 240*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric bool MightHaveChildren() override; 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 2450b57cec5SDimitry Andric }; 2460b57cec5SDimitry Andric } // namespace formatters 2470b57cec5SDimitry Andric } // namespace lldb_private 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric template <bool cf_style> 2500b57cec5SDimitry Andric bool lldb_private::formatters::NSSetSummaryProvider( 2510b57cec5SDimitry Andric ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { 25206c3fb27SDimitry Andric static constexpr llvm::StringLiteral g_TypeHint("NSSet"); 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric ProcessSP process_sp = valobj.GetProcessSP(); 2550b57cec5SDimitry Andric if (!process_sp) 2560b57cec5SDimitry Andric return false; 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp); 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric if (!runtime) 2610b57cec5SDimitry Andric return false; 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP descriptor( 2640b57cec5SDimitry Andric runtime->GetClassDescriptor(valobj)); 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric if (!descriptor || !descriptor->IsValid()) 2670b57cec5SDimitry Andric return false; 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric uint32_t ptr_size = process_sp->GetAddressByteSize(); 2700b57cec5SDimitry Andric bool is_64bit = (ptr_size == 8); 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric if (!valobj_addr) 2750b57cec5SDimitry Andric return false; 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric uint64_t value = 0; 2780b57cec5SDimitry Andric 2795ffd83dbSDimitry Andric ConstString class_name(descriptor->GetClassName()); 2800b57cec5SDimitry Andric 2815ffd83dbSDimitry Andric static const ConstString g_SetI("__NSSetI"); 2825ffd83dbSDimitry Andric static const ConstString g_OrderedSetI("__NSOrderedSetI"); 2835ffd83dbSDimitry Andric static const ConstString g_SetM("__NSSetM"); 2845ffd83dbSDimitry Andric static const ConstString g_SetCF("__NSCFSet"); 2855ffd83dbSDimitry Andric static const ConstString g_SetCFRef("CFSetRef"); 2865ffd83dbSDimitry Andric 2875ffd83dbSDimitry Andric if (class_name.IsEmpty()) 2880b57cec5SDimitry Andric return false; 2890b57cec5SDimitry Andric 2905ffd83dbSDimitry Andric if (class_name == g_SetI || class_name == g_OrderedSetI) { 2910b57cec5SDimitry Andric Status error; 2920b57cec5SDimitry Andric value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 2930b57cec5SDimitry Andric ptr_size, 0, error); 2940b57cec5SDimitry Andric if (error.Fail()) 2950b57cec5SDimitry Andric return false; 2960b57cec5SDimitry Andric value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 2975ffd83dbSDimitry Andric } else if (class_name == g_SetM) { 2980b57cec5SDimitry Andric AppleObjCRuntime *apple_runtime = 2990b57cec5SDimitry Andric llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); 3000b57cec5SDimitry Andric Status error; 3010b57cec5SDimitry Andric if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { 3020b57cec5SDimitry Andric value = Foundation1437::__NSSetMSize(*process_sp, valobj_addr, error); 3030b57cec5SDimitry Andric } else { 3040b57cec5SDimitry Andric value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 3050b57cec5SDimitry Andric ptr_size, 0, error); 3060b57cec5SDimitry Andric value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric if (error.Fail()) 3090b57cec5SDimitry Andric return false; 3105ffd83dbSDimitry Andric } else if (class_name == g_SetCF || class_name == g_SetCFRef) { 3115ffd83dbSDimitry Andric ExecutionContext exe_ctx(process_sp); 3125ffd83dbSDimitry Andric CFBasicHash cfbh; 3135ffd83dbSDimitry Andric if (!cfbh.Update(valobj_addr, exe_ctx)) 3145ffd83dbSDimitry Andric return false; 3155ffd83dbSDimitry Andric value = cfbh.GetCount(); 3160b57cec5SDimitry Andric } else { 3170b57cec5SDimitry Andric auto &map(NSSet_Additionals::GetAdditionalSummaries()); 3185ffd83dbSDimitry Andric auto iter = map.find(class_name), end = map.end(); 3190b57cec5SDimitry Andric if (iter != end) 3200b57cec5SDimitry Andric return iter->second(valobj, stream, options); 3210b57cec5SDimitry Andric else 3220b57cec5SDimitry Andric return false; 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric 32506c3fb27SDimitry Andric llvm::StringRef prefix, suffix; 32606c3fb27SDimitry Andric if (Language *language = Language::FindPlugin(options.GetLanguage())) 32706c3fb27SDimitry Andric std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint); 3280b57cec5SDimitry Andric 32906c3fb27SDimitry Andric stream << prefix; 33006c3fb27SDimitry Andric stream.Printf("%" PRIu64 " %s%s", value, "element", value == 1 ? "" : "s"); 33106c3fb27SDimitry Andric stream << suffix; 3320b57cec5SDimitry Andric return true; 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric SyntheticChildrenFrontEnd * 3360b57cec5SDimitry Andric lldb_private::formatters::NSSetSyntheticFrontEndCreator( 3370b57cec5SDimitry Andric CXXSyntheticChildren *synth, lldb::ValueObjectSP valobj_sp) { 3380b57cec5SDimitry Andric lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 3390b57cec5SDimitry Andric if (!process_sp) 3400b57cec5SDimitry Andric return nullptr; 3410b57cec5SDimitry Andric ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp); 3420b57cec5SDimitry Andric if (!runtime) 3430b57cec5SDimitry Andric return nullptr; 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric CompilerType valobj_type(valobj_sp->GetCompilerType()); 3460b57cec5SDimitry Andric Flags flags(valobj_type.GetTypeInfo()); 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric if (flags.IsClear(eTypeIsPointer)) { 3490b57cec5SDimitry Andric Status error; 3500b57cec5SDimitry Andric valobj_sp = valobj_sp->AddressOf(error); 3510b57cec5SDimitry Andric if (error.Fail() || !valobj_sp) 3520b57cec5SDimitry Andric return nullptr; 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric ObjCLanguageRuntime::ClassDescriptorSP descriptor( 3560b57cec5SDimitry Andric runtime->GetClassDescriptor(*valobj_sp)); 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric if (!descriptor || !descriptor->IsValid()) 3590b57cec5SDimitry Andric return nullptr; 3600b57cec5SDimitry Andric 3615ffd83dbSDimitry Andric ConstString class_name = descriptor->GetClassName(); 3620b57cec5SDimitry Andric 3635ffd83dbSDimitry Andric static const ConstString g_SetI("__NSSetI"); 3645ffd83dbSDimitry Andric static const ConstString g_OrderedSetI("__NSOrderedSetI"); 3655ffd83dbSDimitry Andric static const ConstString g_SetM("__NSSetM"); 3665ffd83dbSDimitry Andric static const ConstString g_SetCF("__NSCFSet"); 3675ffd83dbSDimitry Andric static const ConstString g_SetCFRef("CFSetRef"); 3685ffd83dbSDimitry Andric 3695ffd83dbSDimitry Andric if (class_name.IsEmpty()) 3700b57cec5SDimitry Andric return nullptr; 3710b57cec5SDimitry Andric 3725ffd83dbSDimitry Andric if (class_name == g_SetI || class_name == g_OrderedSetI) { 3730b57cec5SDimitry Andric return (new NSSetISyntheticFrontEnd(valobj_sp)); 3745ffd83dbSDimitry Andric } else if (class_name == g_SetM) { 3750b57cec5SDimitry Andric AppleObjCRuntime *apple_runtime = 3760b57cec5SDimitry Andric llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); 3770b57cec5SDimitry Andric if (apple_runtime) { 3780b57cec5SDimitry Andric if (apple_runtime->GetFoundationVersion() >= 1437) 3790b57cec5SDimitry Andric return (new Foundation1437::NSSetMSyntheticFrontEnd(valobj_sp)); 3800b57cec5SDimitry Andric else if (apple_runtime->GetFoundationVersion() >= 1428) 3810b57cec5SDimitry Andric return (new Foundation1428::NSSetMSyntheticFrontEnd(valobj_sp)); 3820b57cec5SDimitry Andric else 3830b57cec5SDimitry Andric return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp)); 3840b57cec5SDimitry Andric } else { 3850b57cec5SDimitry Andric return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp)); 3860b57cec5SDimitry Andric } 3875ffd83dbSDimitry Andric } else if (class_name == g_SetCF || class_name == g_SetCFRef) { 3885ffd83dbSDimitry Andric return (new NSCFSetSyntheticFrontEnd(valobj_sp)); 3890b57cec5SDimitry Andric } else { 3900b57cec5SDimitry Andric auto &map(NSSet_Additionals::GetAdditionalSynthetics()); 3915ffd83dbSDimitry Andric auto iter = map.find(class_name), end = map.end(); 3920b57cec5SDimitry Andric if (iter != end) 3930b57cec5SDimitry Andric return iter->second(synth, valobj_sp); 3940b57cec5SDimitry Andric return nullptr; 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric lldb_private::formatters::NSSetISyntheticFrontEnd::NSSetISyntheticFrontEnd( 3990b57cec5SDimitry Andric lldb::ValueObjectSP valobj_sp) 40081ad6265SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref() { 4010b57cec5SDimitry Andric if (valobj_sp) 4020b57cec5SDimitry Andric Update(); 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric lldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd() { 4060b57cec5SDimitry Andric delete m_data_32; 4070b57cec5SDimitry Andric m_data_32 = nullptr; 4080b57cec5SDimitry Andric delete m_data_64; 4090b57cec5SDimitry Andric m_data_64 = nullptr; 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric size_t 4130b57cec5SDimitry Andric lldb_private::formatters::NSSetISyntheticFrontEnd::GetIndexOfChildWithName( 4140b57cec5SDimitry Andric ConstString name) { 4150b57cec5SDimitry Andric const char *item_name = name.GetCString(); 4160b57cec5SDimitry Andric uint32_t idx = ExtractIndexFromString(item_name); 417*0fca6ea1SDimitry Andric if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors()) 4180b57cec5SDimitry Andric return UINT32_MAX; 4190b57cec5SDimitry Andric return idx; 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric 422*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> 4230b57cec5SDimitry Andric lldb_private::formatters::NSSetISyntheticFrontEnd::CalculateNumChildren() { 4240b57cec5SDimitry Andric if (!m_data_32 && !m_data_64) 4250b57cec5SDimitry Andric return 0; 4260b57cec5SDimitry Andric return (m_data_32 ? m_data_32->_used : m_data_64->_used); 4270b57cec5SDimitry Andric } 4280b57cec5SDimitry Andric 429*0fca6ea1SDimitry Andric lldb::ChildCacheState 430*0fca6ea1SDimitry Andric lldb_private::formatters::NSSetISyntheticFrontEnd::Update() { 4310b57cec5SDimitry Andric m_children.clear(); 4320b57cec5SDimitry Andric delete m_data_32; 4330b57cec5SDimitry Andric m_data_32 = nullptr; 4340b57cec5SDimitry Andric delete m_data_64; 4350b57cec5SDimitry Andric m_data_64 = nullptr; 4360b57cec5SDimitry Andric m_ptr_size = 0; 4370b57cec5SDimitry Andric ValueObjectSP valobj_sp = m_backend.GetSP(); 4380b57cec5SDimitry Andric if (!valobj_sp) 439*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 4400b57cec5SDimitry Andric if (!valobj_sp) 441*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 4420b57cec5SDimitry Andric m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 4430b57cec5SDimitry Andric lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 4440b57cec5SDimitry Andric if (!process_sp) 445*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 4460b57cec5SDimitry Andric m_ptr_size = process_sp->GetAddressByteSize(); 447fe6060f1SDimitry Andric uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 448fe6060f1SDimitry Andric Status error; 4490b57cec5SDimitry Andric if (m_ptr_size == 4) { 4500b57cec5SDimitry Andric m_data_32 = new DataDescriptor_32(); 4510b57cec5SDimitry Andric process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), 4520b57cec5SDimitry Andric error); 4530b57cec5SDimitry Andric } else { 4540b57cec5SDimitry Andric m_data_64 = new DataDescriptor_64(); 4550b57cec5SDimitry Andric process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), 4560b57cec5SDimitry Andric error); 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric if (error.Fail()) 459*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 4600b57cec5SDimitry Andric m_data_ptr = data_location + m_ptr_size; 461*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eReuse; 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric bool lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren() { 4650b57cec5SDimitry Andric return true; 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric lldb::ValueObjectSP 469*0fca6ea1SDimitry Andric lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex( 470*0fca6ea1SDimitry Andric uint32_t idx) { 471*0fca6ea1SDimitry Andric uint32_t num_children = CalculateNumChildrenIgnoringErrors(); 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric if (idx >= num_children) 4740b57cec5SDimitry Andric return lldb::ValueObjectSP(); 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 4770b57cec5SDimitry Andric if (!process_sp) 4780b57cec5SDimitry Andric return lldb::ValueObjectSP(); 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric if (m_children.empty()) { 4810b57cec5SDimitry Andric // do the scan phase 4820b57cec5SDimitry Andric lldb::addr_t obj_at_idx = 0; 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric uint32_t tries = 0; 4850b57cec5SDimitry Andric uint32_t test_idx = 0; 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric while (tries < num_children) { 4880b57cec5SDimitry Andric obj_at_idx = m_data_ptr + (test_idx * m_ptr_size); 4890b57cec5SDimitry Andric if (!process_sp) 4900b57cec5SDimitry Andric return lldb::ValueObjectSP(); 4910b57cec5SDimitry Andric Status error; 4920b57cec5SDimitry Andric obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error); 4930b57cec5SDimitry Andric if (error.Fail()) 4940b57cec5SDimitry Andric return lldb::ValueObjectSP(); 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric test_idx++; 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric if (!obj_at_idx) 4990b57cec5SDimitry Andric continue; 5000b57cec5SDimitry Andric tries++; 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric SetItemDescriptor descriptor = {obj_at_idx, lldb::ValueObjectSP()}; 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric m_children.push_back(descriptor); 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric if (idx >= m_children.size()) // should never happen 5090b57cec5SDimitry Andric return lldb::ValueObjectSP(); 5100b57cec5SDimitry Andric 5110b57cec5SDimitry Andric SetItemDescriptor &set_item = m_children[idx]; 5120b57cec5SDimitry Andric if (!set_item.valobj_sp) { 5130b57cec5SDimitry Andric auto ptr_size = process_sp->GetAddressByteSize(); 5140b57cec5SDimitry Andric DataBufferHeap buffer(ptr_size, 0); 5150b57cec5SDimitry Andric switch (ptr_size) { 5165ffd83dbSDimitry Andric case 0: // architecture has no clue - fail 5170b57cec5SDimitry Andric return lldb::ValueObjectSP(); 5180b57cec5SDimitry Andric case 4: 5195ffd83dbSDimitry Andric *reinterpret_cast<uint32_t *>(buffer.GetBytes()) = 5205ffd83dbSDimitry Andric static_cast<uint32_t>(set_item.item_ptr); 5210b57cec5SDimitry Andric break; 5220b57cec5SDimitry Andric case 8: 5235ffd83dbSDimitry Andric *reinterpret_cast<uint64_t *>(buffer.GetBytes()) = 5245ffd83dbSDimitry Andric static_cast<uint64_t>(set_item.item_ptr); 5250b57cec5SDimitry Andric break; 5260b57cec5SDimitry Andric default: 5275ffd83dbSDimitry Andric lldbassert(false && "pointer size is not 4 nor 8"); 5280b57cec5SDimitry Andric } 5290b57cec5SDimitry Andric StreamString idx_name; 5300b57cec5SDimitry Andric idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), 5330b57cec5SDimitry Andric process_sp->GetByteOrder(), 5340b57cec5SDimitry Andric process_sp->GetAddressByteSize()); 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric set_item.valobj_sp = CreateValueObjectFromData( 5370b57cec5SDimitry Andric idx_name.GetString(), data, m_exe_ctx_ref, 5380b57cec5SDimitry Andric m_backend.GetCompilerType().GetBasicTypeFromAST( 5390b57cec5SDimitry Andric lldb::eBasicTypeObjCID)); 5400b57cec5SDimitry Andric } 5410b57cec5SDimitry Andric return set_item.valobj_sp; 5420b57cec5SDimitry Andric } 5430b57cec5SDimitry Andric 5445ffd83dbSDimitry Andric lldb_private::formatters::NSCFSetSyntheticFrontEnd::NSCFSetSyntheticFrontEnd( 5455ffd83dbSDimitry Andric lldb::ValueObjectSP valobj_sp) 54681ad6265SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_hashtable(), 54781ad6265SDimitry Andric m_pair_type() {} 5485ffd83dbSDimitry Andric 5495ffd83dbSDimitry Andric size_t 5505ffd83dbSDimitry Andric lldb_private::formatters::NSCFSetSyntheticFrontEnd::GetIndexOfChildWithName( 5515ffd83dbSDimitry Andric ConstString name) { 5525ffd83dbSDimitry Andric const char *item_name = name.GetCString(); 5535ffd83dbSDimitry Andric const uint32_t idx = ExtractIndexFromString(item_name); 554*0fca6ea1SDimitry Andric if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors()) 5555ffd83dbSDimitry Andric return UINT32_MAX; 5565ffd83dbSDimitry Andric return idx; 5575ffd83dbSDimitry Andric } 5585ffd83dbSDimitry Andric 559*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> 5605ffd83dbSDimitry Andric lldb_private::formatters::NSCFSetSyntheticFrontEnd::CalculateNumChildren() { 5615ffd83dbSDimitry Andric if (!m_hashtable.IsValid()) 5625ffd83dbSDimitry Andric return 0; 5635ffd83dbSDimitry Andric return m_hashtable.GetCount(); 5645ffd83dbSDimitry Andric } 5655ffd83dbSDimitry Andric 566*0fca6ea1SDimitry Andric lldb::ChildCacheState 567*0fca6ea1SDimitry Andric lldb_private::formatters::NSCFSetSyntheticFrontEnd::Update() { 5685ffd83dbSDimitry Andric m_children.clear(); 5695ffd83dbSDimitry Andric ValueObjectSP valobj_sp = m_backend.GetSP(); 5705ffd83dbSDimitry Andric m_ptr_size = 0; 5715ffd83dbSDimitry Andric if (!valobj_sp) 572*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 5735ffd83dbSDimitry Andric m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 5745ffd83dbSDimitry Andric 5755ffd83dbSDimitry Andric lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 5765ffd83dbSDimitry Andric if (!process_sp) 577*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 5785ffd83dbSDimitry Andric m_ptr_size = process_sp->GetAddressByteSize(); 5795ffd83dbSDimitry Andric m_order = process_sp->GetByteOrder(); 580*0fca6ea1SDimitry Andric return m_hashtable.Update(valobj_sp->GetValueAsUnsigned(0), m_exe_ctx_ref) 581*0fca6ea1SDimitry Andric ? lldb::ChildCacheState::eReuse 582*0fca6ea1SDimitry Andric : lldb::ChildCacheState::eRefetch; 5835ffd83dbSDimitry Andric } 5845ffd83dbSDimitry Andric 5855ffd83dbSDimitry Andric bool lldb_private::formatters::NSCFSetSyntheticFrontEnd::MightHaveChildren() { 5865ffd83dbSDimitry Andric return true; 5875ffd83dbSDimitry Andric } 5885ffd83dbSDimitry Andric 5895ffd83dbSDimitry Andric lldb::ValueObjectSP 5905ffd83dbSDimitry Andric lldb_private::formatters::NSCFSetSyntheticFrontEnd::GetChildAtIndex( 591*0fca6ea1SDimitry Andric uint32_t idx) { 5925ffd83dbSDimitry Andric lldb::addr_t m_values_ptr = m_hashtable.GetValuePointer(); 5935ffd83dbSDimitry Andric 594*0fca6ea1SDimitry Andric const uint32_t num_children = CalculateNumChildrenIgnoringErrors(); 5955ffd83dbSDimitry Andric 5965ffd83dbSDimitry Andric if (idx >= num_children) 5975ffd83dbSDimitry Andric return lldb::ValueObjectSP(); 5985ffd83dbSDimitry Andric 5995ffd83dbSDimitry Andric if (m_children.empty()) { 6005ffd83dbSDimitry Andric ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 6015ffd83dbSDimitry Andric if (!process_sp) 6025ffd83dbSDimitry Andric return lldb::ValueObjectSP(); 6035ffd83dbSDimitry Andric 6045ffd83dbSDimitry Andric Status error; 6055ffd83dbSDimitry Andric lldb::addr_t val_at_idx = 0; 6065ffd83dbSDimitry Andric 6075ffd83dbSDimitry Andric uint32_t tries = 0; 6085ffd83dbSDimitry Andric uint32_t test_idx = 0; 6095ffd83dbSDimitry Andric 6105ffd83dbSDimitry Andric // Iterate over inferior memory, reading value pointers by shifting the 6115ffd83dbSDimitry Andric // cursor by test_index * m_ptr_size. Returns an empty ValueObject if a read 6125ffd83dbSDimitry Andric // fails, otherwise, continue until the number of tries matches the number 6135ffd83dbSDimitry Andric // of childen. 6145ffd83dbSDimitry Andric while (tries < num_children) { 6155ffd83dbSDimitry Andric val_at_idx = m_values_ptr + (test_idx * m_ptr_size); 6165ffd83dbSDimitry Andric 6175ffd83dbSDimitry Andric val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); 6185ffd83dbSDimitry Andric if (error.Fail()) 6195ffd83dbSDimitry Andric return lldb::ValueObjectSP(); 6205ffd83dbSDimitry Andric 6215ffd83dbSDimitry Andric test_idx++; 6225ffd83dbSDimitry Andric 6235ffd83dbSDimitry Andric if (!val_at_idx) 6245ffd83dbSDimitry Andric continue; 6255ffd83dbSDimitry Andric tries++; 6265ffd83dbSDimitry Andric 6275ffd83dbSDimitry Andric SetItemDescriptor descriptor = {val_at_idx, lldb::ValueObjectSP()}; 6285ffd83dbSDimitry Andric 6295ffd83dbSDimitry Andric m_children.push_back(descriptor); 6305ffd83dbSDimitry Andric } 6315ffd83dbSDimitry Andric } 6325ffd83dbSDimitry Andric 6335ffd83dbSDimitry Andric if (idx >= m_children.size()) // should never happen 6345ffd83dbSDimitry Andric return lldb::ValueObjectSP(); 6355ffd83dbSDimitry Andric 6365ffd83dbSDimitry Andric SetItemDescriptor &set_item = m_children[idx]; 6375ffd83dbSDimitry Andric if (!set_item.valobj_sp) { 6385ffd83dbSDimitry Andric 63981ad6265SDimitry Andric WritableDataBufferSP buffer_sp(new DataBufferHeap(m_ptr_size, 0)); 6405ffd83dbSDimitry Andric 6415ffd83dbSDimitry Andric switch (m_ptr_size) { 6425ffd83dbSDimitry Andric case 0: // architecture has no clue - fail 6435ffd83dbSDimitry Andric return lldb::ValueObjectSP(); 6445ffd83dbSDimitry Andric case 4: 6455ffd83dbSDimitry Andric *reinterpret_cast<uint32_t *>(buffer_sp->GetBytes()) = 6465ffd83dbSDimitry Andric static_cast<uint32_t>(set_item.item_ptr); 6475ffd83dbSDimitry Andric break; 6485ffd83dbSDimitry Andric case 8: 6495ffd83dbSDimitry Andric *reinterpret_cast<uint64_t *>(buffer_sp->GetBytes()) = 6505ffd83dbSDimitry Andric static_cast<uint64_t>(set_item.item_ptr); 6515ffd83dbSDimitry Andric break; 6525ffd83dbSDimitry Andric default: 6535ffd83dbSDimitry Andric lldbassert(false && "pointer size is not 4 nor 8"); 6545ffd83dbSDimitry Andric } 6555ffd83dbSDimitry Andric StreamString idx_name; 6565ffd83dbSDimitry Andric idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 6575ffd83dbSDimitry Andric 6585ffd83dbSDimitry Andric DataExtractor data(buffer_sp, m_order, m_ptr_size); 6595ffd83dbSDimitry Andric 6605ffd83dbSDimitry Andric set_item.valobj_sp = CreateValueObjectFromData( 6615ffd83dbSDimitry Andric idx_name.GetString(), data, m_exe_ctx_ref, 6625ffd83dbSDimitry Andric m_backend.GetCompilerType().GetBasicTypeFromAST( 6635ffd83dbSDimitry Andric lldb::eBasicTypeObjCID)); 6645ffd83dbSDimitry Andric } 6655ffd83dbSDimitry Andric 6665ffd83dbSDimitry Andric return set_item.valobj_sp; 6675ffd83dbSDimitry Andric } 6685ffd83dbSDimitry Andric 6690b57cec5SDimitry Andric template <typename D32, typename D64> 67081ad6265SDimitry Andric lldb_private::formatters::GenericNSSetMSyntheticFrontEnd< 67181ad6265SDimitry Andric D32, D64>::GenericNSSetMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 67281ad6265SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), 6730b57cec5SDimitry Andric m_data_32(nullptr), m_data_64(nullptr) { 6740b57cec5SDimitry Andric if (valobj_sp) 6750b57cec5SDimitry Andric Update(); 6760b57cec5SDimitry Andric } 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric template <typename D32, typename D64> 679*0fca6ea1SDimitry Andric lldb_private::formatters::GenericNSSetMSyntheticFrontEnd<D32, D64>:: 680*0fca6ea1SDimitry Andric GenericNSSetMSyntheticFrontEnd::~GenericNSSetMSyntheticFrontEnd() { 6810b57cec5SDimitry Andric delete m_data_32; 6820b57cec5SDimitry Andric m_data_32 = nullptr; 6830b57cec5SDimitry Andric delete m_data_64; 6840b57cec5SDimitry Andric m_data_64 = nullptr; 6850b57cec5SDimitry Andric } 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andric template <typename D32, typename D64> 6880b57cec5SDimitry Andric size_t 6890b57cec5SDimitry Andric lldb_private::formatters:: 6900b57cec5SDimitry Andric GenericNSSetMSyntheticFrontEnd<D32, D64>::GetIndexOfChildWithName( 6910b57cec5SDimitry Andric ConstString name) { 6920b57cec5SDimitry Andric const char *item_name = name.GetCString(); 6930b57cec5SDimitry Andric uint32_t idx = ExtractIndexFromString(item_name); 694*0fca6ea1SDimitry Andric if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors()) 6950b57cec5SDimitry Andric return UINT32_MAX; 6960b57cec5SDimitry Andric return idx; 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric template <typename D32, typename D64> 700*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> 701*0fca6ea1SDimitry Andric lldb_private::formatters::GenericNSSetMSyntheticFrontEnd< 702*0fca6ea1SDimitry Andric D32, D64>::CalculateNumChildren() { 7030b57cec5SDimitry Andric if (!m_data_32 && !m_data_64) 7040b57cec5SDimitry Andric return 0; 705*0fca6ea1SDimitry Andric return (m_data_32 ? (uint32_t)m_data_32->_used : (uint32_t)m_data_64->_used); 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric template <typename D32, typename D64> 709*0fca6ea1SDimitry Andric lldb::ChildCacheState 710*0fca6ea1SDimitry Andric lldb_private::formatters::GenericNSSetMSyntheticFrontEnd<D32, D64>::Update() { 7110b57cec5SDimitry Andric m_children.clear(); 7120b57cec5SDimitry Andric ValueObjectSP valobj_sp = m_backend.GetSP(); 7130b57cec5SDimitry Andric m_ptr_size = 0; 7140b57cec5SDimitry Andric delete m_data_32; 7150b57cec5SDimitry Andric m_data_32 = nullptr; 7160b57cec5SDimitry Andric delete m_data_64; 7170b57cec5SDimitry Andric m_data_64 = nullptr; 7180b57cec5SDimitry Andric if (!valobj_sp) 719*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 7200b57cec5SDimitry Andric if (!valobj_sp) 721*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 7220b57cec5SDimitry Andric m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 7230b57cec5SDimitry Andric lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 7240b57cec5SDimitry Andric if (!process_sp) 725*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 7260b57cec5SDimitry Andric m_ptr_size = process_sp->GetAddressByteSize(); 727fe6060f1SDimitry Andric uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 728fe6060f1SDimitry Andric Status error; 7290b57cec5SDimitry Andric if (m_ptr_size == 4) { 7300b57cec5SDimitry Andric m_data_32 = new D32(); 7310b57cec5SDimitry Andric process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), 7320b57cec5SDimitry Andric error); 7330b57cec5SDimitry Andric } else { 7340b57cec5SDimitry Andric m_data_64 = new D64(); 7350b57cec5SDimitry Andric process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), 7360b57cec5SDimitry Andric error); 7370b57cec5SDimitry Andric } 738*0fca6ea1SDimitry Andric return error.Success() ? lldb::ChildCacheState::eReuse 739*0fca6ea1SDimitry Andric : lldb::ChildCacheState::eRefetch; 7400b57cec5SDimitry Andric } 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andric template <typename D32, typename D64> 7430b57cec5SDimitry Andric bool 7440b57cec5SDimitry Andric lldb_private::formatters:: 7450b57cec5SDimitry Andric GenericNSSetMSyntheticFrontEnd<D32, D64>::MightHaveChildren() { 7460b57cec5SDimitry Andric return true; 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric template <typename D32, typename D64> 7500b57cec5SDimitry Andric lldb::ValueObjectSP 7510b57cec5SDimitry Andric lldb_private::formatters:: 752*0fca6ea1SDimitry Andric GenericNSSetMSyntheticFrontEnd<D32, D64>::GetChildAtIndex(uint32_t idx) { 7530b57cec5SDimitry Andric lldb::addr_t m_objs_addr = 7540b57cec5SDimitry Andric (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr); 7550b57cec5SDimitry Andric 756*0fca6ea1SDimitry Andric uint32_t num_children = CalculateNumChildrenIgnoringErrors(); 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric if (idx >= num_children) 7590b57cec5SDimitry Andric return lldb::ValueObjectSP(); 7600b57cec5SDimitry Andric 7610b57cec5SDimitry Andric ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 7620b57cec5SDimitry Andric if (!process_sp) 7630b57cec5SDimitry Andric return lldb::ValueObjectSP(); 7640b57cec5SDimitry Andric 7650b57cec5SDimitry Andric if (m_children.empty()) { 7660b57cec5SDimitry Andric // do the scan phase 7670b57cec5SDimitry Andric lldb::addr_t obj_at_idx = 0; 7680b57cec5SDimitry Andric 7690b57cec5SDimitry Andric uint32_t tries = 0; 7700b57cec5SDimitry Andric uint32_t test_idx = 0; 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric while (tries < num_children) { 7730b57cec5SDimitry Andric obj_at_idx = m_objs_addr + (test_idx * m_ptr_size); 7740b57cec5SDimitry Andric if (!process_sp) 7750b57cec5SDimitry Andric return lldb::ValueObjectSP(); 7760b57cec5SDimitry Andric Status error; 7770b57cec5SDimitry Andric obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error); 7780b57cec5SDimitry Andric if (error.Fail()) 7790b57cec5SDimitry Andric return lldb::ValueObjectSP(); 7800b57cec5SDimitry Andric 7810b57cec5SDimitry Andric test_idx++; 7820b57cec5SDimitry Andric 7830b57cec5SDimitry Andric if (!obj_at_idx) 7840b57cec5SDimitry Andric continue; 7850b57cec5SDimitry Andric tries++; 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric SetItemDescriptor descriptor = {obj_at_idx, lldb::ValueObjectSP()}; 7880b57cec5SDimitry Andric 7890b57cec5SDimitry Andric m_children.push_back(descriptor); 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric } 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric if (idx >= m_children.size()) // should never happen 7940b57cec5SDimitry Andric return lldb::ValueObjectSP(); 7950b57cec5SDimitry Andric 7960b57cec5SDimitry Andric SetItemDescriptor &set_item = m_children[idx]; 7970b57cec5SDimitry Andric if (!set_item.valobj_sp) { 7980b57cec5SDimitry Andric auto ptr_size = process_sp->GetAddressByteSize(); 7990b57cec5SDimitry Andric DataBufferHeap buffer(ptr_size, 0); 8000b57cec5SDimitry Andric switch (ptr_size) { 8010b57cec5SDimitry Andric case 0: // architecture has no clue?? - fail 8020b57cec5SDimitry Andric return lldb::ValueObjectSP(); 8030b57cec5SDimitry Andric case 4: 8040b57cec5SDimitry Andric *((uint32_t *)buffer.GetBytes()) = (uint32_t)set_item.item_ptr; 8050b57cec5SDimitry Andric break; 8060b57cec5SDimitry Andric case 8: 8070b57cec5SDimitry Andric *((uint64_t *)buffer.GetBytes()) = (uint64_t)set_item.item_ptr; 8080b57cec5SDimitry Andric break; 8090b57cec5SDimitry Andric default: 8100b57cec5SDimitry Andric assert(false && "pointer size is not 4 nor 8 - get out of here ASAP"); 8110b57cec5SDimitry Andric } 8120b57cec5SDimitry Andric StreamString idx_name; 8130b57cec5SDimitry Andric idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 8140b57cec5SDimitry Andric 8150b57cec5SDimitry Andric DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), 8160b57cec5SDimitry Andric process_sp->GetByteOrder(), 8170b57cec5SDimitry Andric process_sp->GetAddressByteSize()); 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric set_item.valobj_sp = CreateValueObjectFromData( 8200b57cec5SDimitry Andric idx_name.GetString(), data, m_exe_ctx_ref, 8210b57cec5SDimitry Andric m_backend.GetCompilerType().GetBasicTypeFromAST( 8220b57cec5SDimitry Andric lldb::eBasicTypeObjCID)); 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric return set_item.valobj_sp; 8250b57cec5SDimitry Andric } 8260b57cec5SDimitry Andric 8270b57cec5SDimitry Andric template bool lldb_private::formatters::NSSetSummaryProvider<true>( 8280b57cec5SDimitry Andric ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); 8290b57cec5SDimitry Andric 8300b57cec5SDimitry Andric template bool lldb_private::formatters::NSSetSummaryProvider<false>( 8310b57cec5SDimitry Andric ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); 832