15ffd83dbSDimitry Andric //===-- LibStdcpp.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 "LibStdcpp.h" 10bdd1243dSDimitry Andric #include "LibCxx.h" 110b57cec5SDimitry Andric 125ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 130b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h" 140b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResult.h" 150b57cec5SDimitry Andric #include "lldb/DataFormatters/StringPrinter.h" 160b57cec5SDimitry Andric #include "lldb/DataFormatters/VectorIterator.h" 170b57cec5SDimitry Andric #include "lldb/Target/Target.h" 180b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h" 190b57cec5SDimitry Andric #include "lldb/Utility/Endian.h" 200b57cec5SDimitry Andric #include "lldb/Utility/Status.h" 210b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 22bdd1243dSDimitry Andric #include <optional> 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric using namespace lldb; 250b57cec5SDimitry Andric using namespace lldb_private; 260b57cec5SDimitry Andric using namespace lldb_private::formatters; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric namespace { 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 310b57cec5SDimitry Andric /* 320b57cec5SDimitry Andric (std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char, 330b57cec5SDimitry Andric std::char_traits<char>, std::allocator<char> > > >) ibeg = { 340b57cec5SDimitry Andric (_Base_ptr) _M_node = 0x0000000100103910 { 350b57cec5SDimitry Andric (std::_Rb_tree_color) _M_color = _S_black 360b57cec5SDimitry Andric (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0 370b57cec5SDimitry Andric (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000 380b57cec5SDimitry Andric (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000 390b57cec5SDimitry Andric } 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric */ 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric public: 440b57cec5SDimitry Andric explicit LibstdcppMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 450b57cec5SDimitry Andric 46*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 470b57cec5SDimitry Andric 48*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 490b57cec5SDimitry Andric 50*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric bool MightHaveChildren() override; 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric private: 570b57cec5SDimitry Andric ExecutionContextRef m_exe_ctx_ref; 5881ad6265SDimitry Andric lldb::addr_t m_pair_address = 0; 590b57cec5SDimitry Andric CompilerType m_pair_type; 600b57cec5SDimitry Andric lldb::ValueObjectSP m_pair_sp; 610b57cec5SDimitry Andric }; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric class LibStdcppSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd { 640b57cec5SDimitry Andric public: 650b57cec5SDimitry Andric explicit LibStdcppSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 660b57cec5SDimitry Andric 67*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> CalculateNumChildren() override; 680b57cec5SDimitry Andric 69*0fca6ea1SDimitry Andric lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; 700b57cec5SDimitry Andric 71*0fca6ea1SDimitry Andric lldb::ChildCacheState Update() override; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric bool MightHaveChildren() override; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric size_t GetIndexOfChildWithName(ConstString name) override; 7606c3fb27SDimitry Andric private: 7706c3fb27SDimitry Andric 7806c3fb27SDimitry Andric // The lifetime of a ValueObject and all its derivative ValueObjects 7906c3fb27SDimitry Andric // (children, clones, etc.) is managed by a ClusterManager. These 8006c3fb27SDimitry Andric // objects are only destroyed when every shared pointer to any of them 8106c3fb27SDimitry Andric // is destroyed, so we must not store a shared pointer to any ValueObject 8206c3fb27SDimitry Andric // derived from our backend ValueObject (since we're in the same cluster). 8306c3fb27SDimitry Andric ValueObject* m_ptr_obj = nullptr; // Underlying pointer (held, not owned) 8406c3fb27SDimitry Andric ValueObject* m_obj_obj = nullptr; // Underlying object (held, not owned) 850b57cec5SDimitry Andric }; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric } // end of anonymous namespace 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd( 900b57cec5SDimitry Andric lldb::ValueObjectSP valobj_sp) 9181ad6265SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_type(), 9281ad6265SDimitry Andric m_pair_sp() { 930b57cec5SDimitry Andric if (valobj_sp) 940b57cec5SDimitry Andric Update(); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 97*0fca6ea1SDimitry Andric lldb::ChildCacheState LibstdcppMapIteratorSyntheticFrontEnd::Update() { 980b57cec5SDimitry Andric ValueObjectSP valobj_sp = m_backend.GetSP(); 990b57cec5SDimitry Andric if (!valobj_sp) 100*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric TargetSP target_sp(valobj_sp->GetTargetSP()); 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric if (!target_sp) 105*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8); 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric if (!valobj_sp) 110*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 1110b57cec5SDimitry Andric m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 1120b57cec5SDimitry Andric 11306c3fb27SDimitry Andric ValueObjectSP _M_node_sp(valobj_sp->GetChildMemberWithName("_M_node")); 1140b57cec5SDimitry Andric if (!_M_node_sp) 115*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric m_pair_address = _M_node_sp->GetValueAsUnsigned(0); 1180b57cec5SDimitry Andric if (m_pair_address == 0) 119*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric m_pair_address += (is_64bit ? 32 : 16); 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric CompilerType my_type(valobj_sp->GetCompilerType()); 1240b57cec5SDimitry Andric if (my_type.GetNumTemplateArguments() >= 1) { 1250b57cec5SDimitry Andric CompilerType pair_type = my_type.GetTypeTemplateArgument(0); 1260b57cec5SDimitry Andric if (!pair_type) 127*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 1280b57cec5SDimitry Andric m_pair_type = pair_type; 1290b57cec5SDimitry Andric } else 130*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 1310b57cec5SDimitry Andric 132*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eReuse; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 135*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> 136*0fca6ea1SDimitry Andric LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren() { 1370b57cec5SDimitry Andric return 2; 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric lldb::ValueObjectSP 141*0fca6ea1SDimitry Andric LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) { 1420b57cec5SDimitry Andric if (m_pair_address != 0 && m_pair_type) { 1430b57cec5SDimitry Andric if (!m_pair_sp) 1440b57cec5SDimitry Andric m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address, 1450b57cec5SDimitry Andric m_exe_ctx_ref, m_pair_type); 1460b57cec5SDimitry Andric if (m_pair_sp) 14706c3fb27SDimitry Andric return m_pair_sp->GetChildAtIndex(idx); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric return lldb::ValueObjectSP(); 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric bool LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren() { return true; } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric size_t LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName( 1550b57cec5SDimitry Andric ConstString name) { 1560b57cec5SDimitry Andric if (name == "first") 1570b57cec5SDimitry Andric return 0; 1580b57cec5SDimitry Andric if (name == "second") 1590b57cec5SDimitry Andric return 1; 1600b57cec5SDimitry Andric return UINT32_MAX; 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric SyntheticChildrenFrontEnd * 1640b57cec5SDimitry Andric lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator( 1650b57cec5SDimitry Andric CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 1660b57cec5SDimitry Andric return (valobj_sp ? new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp) 1670b57cec5SDimitry Andric : nullptr); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric /* 1710b57cec5SDimitry Andric (lldb) fr var ibeg --ptr-depth 1 1720b57cec5SDimitry Andric (__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >) 1730b57cec5SDimitry Andric ibeg = { 1740b57cec5SDimitry Andric _M_current = 0x00000001001037a0 { 1750b57cec5SDimitry Andric *_M_current = 1 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric */ 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric SyntheticChildrenFrontEnd * 1810b57cec5SDimitry Andric lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator( 1820b57cec5SDimitry Andric CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 183bdd1243dSDimitry Andric return (valobj_sp ? new VectorIteratorSyntheticFrontEnd( 184bdd1243dSDimitry Andric valobj_sp, {ConstString("_M_current")}) 1850b57cec5SDimitry Andric : nullptr); 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric lldb_private::formatters::VectorIteratorSyntheticFrontEnd:: 1890b57cec5SDimitry Andric VectorIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp, 190bdd1243dSDimitry Andric llvm::ArrayRef<ConstString> item_names) 1910b57cec5SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), 192bdd1243dSDimitry Andric m_item_names(item_names), m_item_sp() { 1930b57cec5SDimitry Andric if (valobj_sp) 1940b57cec5SDimitry Andric Update(); 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 197*0fca6ea1SDimitry Andric lldb::ChildCacheState VectorIteratorSyntheticFrontEnd::Update() { 1980b57cec5SDimitry Andric m_item_sp.reset(); 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric ValueObjectSP valobj_sp = m_backend.GetSP(); 2010b57cec5SDimitry Andric if (!valobj_sp) 202*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric if (!valobj_sp) 205*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 2060b57cec5SDimitry Andric 207bdd1243dSDimitry Andric ValueObjectSP item_ptr = 208bdd1243dSDimitry Andric formatters::GetChildMemberWithName(*valobj_sp, m_item_names); 2090b57cec5SDimitry Andric if (!item_ptr) 210*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 2110b57cec5SDimitry Andric if (item_ptr->GetValueAsUnsigned(0) == 0) 212*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 2130b57cec5SDimitry Andric Status err; 2140b57cec5SDimitry Andric m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 2150b57cec5SDimitry Andric m_item_sp = CreateValueObjectFromAddress( 2160b57cec5SDimitry Andric "item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, 2170b57cec5SDimitry Andric item_ptr->GetCompilerType().GetPointeeType()); 2180b57cec5SDimitry Andric if (err.Fail()) 2190b57cec5SDimitry Andric m_item_sp.reset(); 220*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 223*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> 224*0fca6ea1SDimitry Andric VectorIteratorSyntheticFrontEnd::CalculateNumChildren() { 225*0fca6ea1SDimitry Andric return 1; 226*0fca6ea1SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric lldb::ValueObjectSP 229*0fca6ea1SDimitry Andric VectorIteratorSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) { 2300b57cec5SDimitry Andric if (idx == 0) 2310b57cec5SDimitry Andric return m_item_sp; 2320b57cec5SDimitry Andric return lldb::ValueObjectSP(); 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric bool VectorIteratorSyntheticFrontEnd::MightHaveChildren() { return true; } 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric size_t VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName( 2380b57cec5SDimitry Andric ConstString name) { 2390b57cec5SDimitry Andric if (name == "item") 2400b57cec5SDimitry Andric return 0; 2410b57cec5SDimitry Andric return UINT32_MAX; 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric bool lldb_private::formatters::LibStdcppStringSummaryProvider( 2450b57cec5SDimitry Andric ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { 2460b57cec5SDimitry Andric const bool scalar_is_load_addr = true; 2470b57cec5SDimitry Andric AddressType addr_type; 24806c3fb27SDimitry Andric lldb::addr_t addr_of_string = LLDB_INVALID_ADDRESS; 24906c3fb27SDimitry Andric if (valobj.IsPointerOrReferenceType()) { 25006c3fb27SDimitry Andric Status error; 25106c3fb27SDimitry Andric ValueObjectSP pointee_sp = valobj.Dereference(error); 25206c3fb27SDimitry Andric if (pointee_sp && error.Success()) 25306c3fb27SDimitry Andric addr_of_string = pointee_sp->GetAddressOf(scalar_is_load_addr, &addr_type); 25406c3fb27SDimitry Andric } else 25506c3fb27SDimitry Andric addr_of_string = 2560b57cec5SDimitry Andric valobj.GetAddressOf(scalar_is_load_addr, &addr_type); 2570b57cec5SDimitry Andric if (addr_of_string != LLDB_INVALID_ADDRESS) { 2580b57cec5SDimitry Andric switch (addr_type) { 2590b57cec5SDimitry Andric case eAddressTypeLoad: { 2600b57cec5SDimitry Andric ProcessSP process_sp(valobj.GetProcessSP()); 2610b57cec5SDimitry Andric if (!process_sp) 2620b57cec5SDimitry Andric return false; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); 2650b57cec5SDimitry Andric Status error; 2660b57cec5SDimitry Andric lldb::addr_t addr_of_data = 2670b57cec5SDimitry Andric process_sp->ReadPointerFromMemory(addr_of_string, error); 2680b57cec5SDimitry Andric if (error.Fail() || addr_of_data == 0 || 2690b57cec5SDimitry Andric addr_of_data == LLDB_INVALID_ADDRESS) 2700b57cec5SDimitry Andric return false; 2710b57cec5SDimitry Andric options.SetLocation(addr_of_data); 272349cc55cSDimitry Andric options.SetTargetSP(valobj.GetTargetSP()); 2730b57cec5SDimitry Andric options.SetStream(&stream); 2740b57cec5SDimitry Andric options.SetNeedsZeroTermination(false); 2750b57cec5SDimitry Andric options.SetBinaryZeroIsTerminator(true); 2760b57cec5SDimitry Andric lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory( 2770b57cec5SDimitry Andric addr_of_string + process_sp->GetAddressByteSize(), error); 2780b57cec5SDimitry Andric if (error.Fail()) 2790b57cec5SDimitry Andric return false; 2800b57cec5SDimitry Andric options.SetSourceSize(size_of_data); 2815ffd83dbSDimitry Andric options.SetHasSourceSize(true); 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric if (!StringPrinter::ReadStringAndDumpToStream< 2840b57cec5SDimitry Andric StringPrinter::StringElementType::UTF8>(options)) { 2850b57cec5SDimitry Andric stream.Printf("Summary Unavailable"); 2860b57cec5SDimitry Andric return true; 2870b57cec5SDimitry Andric } else 2880b57cec5SDimitry Andric return true; 2890b57cec5SDimitry Andric } break; 2900b57cec5SDimitry Andric case eAddressTypeHost: 2910b57cec5SDimitry Andric break; 2920b57cec5SDimitry Andric case eAddressTypeInvalid: 2930b57cec5SDimitry Andric case eAddressTypeFile: 2940b57cec5SDimitry Andric break; 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric return false; 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric bool lldb_private::formatters::LibStdcppWStringSummaryProvider( 3010b57cec5SDimitry Andric ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { 3020b57cec5SDimitry Andric const bool scalar_is_load_addr = true; 3030b57cec5SDimitry Andric AddressType addr_type; 3040b57cec5SDimitry Andric lldb::addr_t addr_of_string = 3050b57cec5SDimitry Andric valobj.GetAddressOf(scalar_is_load_addr, &addr_type); 3060b57cec5SDimitry Andric if (addr_of_string != LLDB_INVALID_ADDRESS) { 3070b57cec5SDimitry Andric switch (addr_type) { 3080b57cec5SDimitry Andric case eAddressTypeLoad: { 3090b57cec5SDimitry Andric ProcessSP process_sp(valobj.GetProcessSP()); 3100b57cec5SDimitry Andric if (!process_sp) 3110b57cec5SDimitry Andric return false; 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric CompilerType wchar_compiler_type = 3140b57cec5SDimitry Andric valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric if (!wchar_compiler_type) 3170b57cec5SDimitry Andric return false; 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric // Safe to pass nullptr for exe_scope here. 320bdd1243dSDimitry Andric std::optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr); 3210b57cec5SDimitry Andric if (!size) 3220b57cec5SDimitry Andric return false; 3230b57cec5SDimitry Andric const uint32_t wchar_size = *size; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); 3260b57cec5SDimitry Andric Status error; 3270b57cec5SDimitry Andric lldb::addr_t addr_of_data = 3280b57cec5SDimitry Andric process_sp->ReadPointerFromMemory(addr_of_string, error); 3290b57cec5SDimitry Andric if (error.Fail() || addr_of_data == 0 || 3300b57cec5SDimitry Andric addr_of_data == LLDB_INVALID_ADDRESS) 3310b57cec5SDimitry Andric return false; 3320b57cec5SDimitry Andric options.SetLocation(addr_of_data); 333349cc55cSDimitry Andric options.SetTargetSP(valobj.GetTargetSP()); 3340b57cec5SDimitry Andric options.SetStream(&stream); 3350b57cec5SDimitry Andric options.SetNeedsZeroTermination(false); 3360b57cec5SDimitry Andric options.SetBinaryZeroIsTerminator(false); 3370b57cec5SDimitry Andric lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory( 3380b57cec5SDimitry Andric addr_of_string + process_sp->GetAddressByteSize(), error); 3390b57cec5SDimitry Andric if (error.Fail()) 3400b57cec5SDimitry Andric return false; 3410b57cec5SDimitry Andric options.SetSourceSize(size_of_data); 3425ffd83dbSDimitry Andric options.SetHasSourceSize(true); 3430b57cec5SDimitry Andric options.SetPrefixToken("L"); 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric switch (wchar_size) { 3460b57cec5SDimitry Andric case 8: 3470b57cec5SDimitry Andric return StringPrinter::ReadStringAndDumpToStream< 3480b57cec5SDimitry Andric StringPrinter::StringElementType::UTF8>(options); 3490b57cec5SDimitry Andric case 16: 3500b57cec5SDimitry Andric return StringPrinter::ReadStringAndDumpToStream< 3510b57cec5SDimitry Andric StringPrinter::StringElementType::UTF16>(options); 3520b57cec5SDimitry Andric case 32: 3530b57cec5SDimitry Andric return StringPrinter::ReadStringAndDumpToStream< 3540b57cec5SDimitry Andric StringPrinter::StringElementType::UTF32>(options); 3550b57cec5SDimitry Andric default: 3560b57cec5SDimitry Andric stream.Printf("size for wchar_t is not valid"); 3570b57cec5SDimitry Andric return true; 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric return true; 3600b57cec5SDimitry Andric } break; 3610b57cec5SDimitry Andric case eAddressTypeHost: 3620b57cec5SDimitry Andric break; 3630b57cec5SDimitry Andric case eAddressTypeInvalid: 3640b57cec5SDimitry Andric case eAddressTypeFile: 3650b57cec5SDimitry Andric break; 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric return false; 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric LibStdcppSharedPtrSyntheticFrontEnd::LibStdcppSharedPtrSyntheticFrontEnd( 3720b57cec5SDimitry Andric lldb::ValueObjectSP valobj_sp) 3730b57cec5SDimitry Andric : SyntheticChildrenFrontEnd(*valobj_sp) { 3740b57cec5SDimitry Andric if (valobj_sp) 3750b57cec5SDimitry Andric Update(); 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric 378*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> 379*0fca6ea1SDimitry Andric LibStdcppSharedPtrSyntheticFrontEnd::CalculateNumChildren() { 380*0fca6ea1SDimitry Andric return 1; 381*0fca6ea1SDimitry Andric } 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric lldb::ValueObjectSP 384*0fca6ea1SDimitry Andric LibStdcppSharedPtrSyntheticFrontEnd::GetChildAtIndex(uint32_t idx) { 3850b57cec5SDimitry Andric if (idx == 0) 38606c3fb27SDimitry Andric return m_ptr_obj->GetSP(); 3875f757f3fSDimitry Andric if (idx == 1) { 3885f757f3fSDimitry Andric if (m_ptr_obj && !m_obj_obj) { 3895f757f3fSDimitry Andric Status error; 3905f757f3fSDimitry Andric ValueObjectSP obj_obj = m_ptr_obj->Dereference(error); 3915f757f3fSDimitry Andric if (error.Success()) 3925f757f3fSDimitry Andric m_obj_obj = obj_obj->Clone(ConstString("object")).get(); 3935f757f3fSDimitry Andric } 3945f757f3fSDimitry Andric if (m_obj_obj) 39506c3fb27SDimitry Andric return m_obj_obj->GetSP(); 3965f757f3fSDimitry Andric } 3970b57cec5SDimitry Andric return lldb::ValueObjectSP(); 3980b57cec5SDimitry Andric } 3990b57cec5SDimitry Andric 400*0fca6ea1SDimitry Andric lldb::ChildCacheState LibStdcppSharedPtrSyntheticFrontEnd::Update() { 40106c3fb27SDimitry Andric auto backend = m_backend.GetSP(); 40206c3fb27SDimitry Andric if (!backend) 403*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 40406c3fb27SDimitry Andric 40506c3fb27SDimitry Andric auto valobj_sp = backend->GetNonSyntheticValue(); 40606c3fb27SDimitry Andric if (!valobj_sp) 407*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 40806c3fb27SDimitry Andric 40906c3fb27SDimitry Andric auto ptr_obj_sp = valobj_sp->GetChildMemberWithName("_M_ptr"); 41006c3fb27SDimitry Andric if (!ptr_obj_sp) 411*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 41206c3fb27SDimitry Andric 41306c3fb27SDimitry Andric m_ptr_obj = ptr_obj_sp->Clone(ConstString("pointer")).get(); 4145f757f3fSDimitry Andric m_obj_obj = nullptr; 41506c3fb27SDimitry Andric 416*0fca6ea1SDimitry Andric return lldb::ChildCacheState::eRefetch; 41706c3fb27SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric bool LibStdcppSharedPtrSyntheticFrontEnd::MightHaveChildren() { return true; } 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric size_t LibStdcppSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName( 4220b57cec5SDimitry Andric ConstString name) { 42306c3fb27SDimitry Andric if (name == "pointer") 4240b57cec5SDimitry Andric return 0; 42506c3fb27SDimitry Andric if (name == "object" || name == "$$dereference$$") 42606c3fb27SDimitry Andric return 1; 4270b57cec5SDimitry Andric return UINT32_MAX; 4280b57cec5SDimitry Andric } 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric SyntheticChildrenFrontEnd * 4310b57cec5SDimitry Andric lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator( 4320b57cec5SDimitry Andric CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { 4330b57cec5SDimitry Andric return (valobj_sp ? new LibStdcppSharedPtrSyntheticFrontEnd(valobj_sp) 4340b57cec5SDimitry Andric : nullptr); 4350b57cec5SDimitry Andric } 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric bool lldb_private::formatters::LibStdcppSmartPointerSummaryProvider( 4380b57cec5SDimitry Andric ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { 4390b57cec5SDimitry Andric ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue()); 4400b57cec5SDimitry Andric if (!valobj_sp) 4410b57cec5SDimitry Andric return false; 4420b57cec5SDimitry Andric 44306c3fb27SDimitry Andric ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("_M_ptr")); 4440b57cec5SDimitry Andric if (!ptr_sp) 4450b57cec5SDimitry Andric return false; 4460b57cec5SDimitry Andric 44706c3fb27SDimitry Andric ValueObjectSP usecount_sp( 44806c3fb27SDimitry Andric valobj_sp->GetChildAtNamePath({"_M_refcount", "_M_pi", "_M_use_count"})); 4490b57cec5SDimitry Andric if (!usecount_sp) 4500b57cec5SDimitry Andric return false; 4510b57cec5SDimitry Andric 4520b57cec5SDimitry Andric if (ptr_sp->GetValueAsUnsigned(0) == 0 || 4530b57cec5SDimitry Andric usecount_sp->GetValueAsUnsigned(0) == 0) { 4540b57cec5SDimitry Andric stream.Printf("nullptr"); 4550b57cec5SDimitry Andric return true; 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric Status error; 4590b57cec5SDimitry Andric ValueObjectSP pointee_sp = ptr_sp->Dereference(error); 4600b57cec5SDimitry Andric if (pointee_sp && error.Success()) { 4610b57cec5SDimitry Andric if (pointee_sp->DumpPrintableRepresentation( 4620b57cec5SDimitry Andric stream, ValueObject::eValueObjectRepresentationStyleSummary, 4630b57cec5SDimitry Andric lldb::eFormatInvalid, 4640b57cec5SDimitry Andric ValueObject::PrintableRepresentationSpecialCases::eDisable, 4650b57cec5SDimitry Andric false)) { 4660b57cec5SDimitry Andric return true; 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric } 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0)); 4710b57cec5SDimitry Andric return true; 4720b57cec5SDimitry Andric } 473