1 //===-- LibCxxVector.cpp -----------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "LibCxx.h" 11 12 #include "lldb/Core/ConstString.h" 13 #include "lldb/Core/ValueObject.h" 14 #include "lldb/DataFormatters/FormattersHelpers.h" 15 16 using namespace lldb; 17 using namespace lldb_private; 18 using namespace lldb_private::formatters; 19 20 namespace lldb_private { 21 namespace formatters { 22 class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd 23 { 24 public: 25 LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 26 27 virtual size_t 28 CalculateNumChildren (); 29 30 virtual lldb::ValueObjectSP 31 GetChildAtIndex (size_t idx); 32 33 virtual bool 34 Update(); 35 36 virtual bool 37 MightHaveChildren (); 38 39 virtual size_t 40 GetIndexOfChildWithName (const ConstString &name); 41 42 virtual 43 ~LibcxxStdVectorSyntheticFrontEnd (); 44 private: 45 ValueObject* m_start; 46 ValueObject* m_finish; 47 CompilerType m_element_type; 48 uint32_t m_element_size; 49 std::map<size_t,lldb::ValueObjectSP> m_children; 50 }; 51 } 52 } 53 54 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 55 SyntheticChildrenFrontEnd(*valobj_sp.get()), 56 m_start(NULL), 57 m_finish(NULL), 58 m_element_type(), 59 m_element_size(0), 60 m_children() 61 { 62 if (valobj_sp) 63 Update(); 64 } 65 66 size_t 67 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren () 68 { 69 if (!m_start || !m_finish) 70 return 0; 71 uint64_t start_val = m_start->GetValueAsUnsigned(0); 72 uint64_t finish_val = m_finish->GetValueAsUnsigned(0); 73 74 if (start_val == 0 || finish_val == 0) 75 return 0; 76 77 if (start_val >= finish_val) 78 return 0; 79 80 size_t num_children = (finish_val - start_val); 81 if (num_children % m_element_size) 82 return 0; 83 return num_children/m_element_size; 84 } 85 86 lldb::ValueObjectSP 87 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx) 88 { 89 if (!m_start || !m_finish) 90 return lldb::ValueObjectSP(); 91 92 auto cached = m_children.find(idx); 93 if (cached != m_children.end()) 94 return cached->second; 95 96 uint64_t offset = idx * m_element_size; 97 offset = offset + m_start->GetValueAsUnsigned(0); 98 StreamString name; 99 name.Printf("[%" PRIu64 "]", (uint64_t)idx); 100 ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type); 101 m_children[idx] = child_sp; 102 return child_sp; 103 } 104 105 bool 106 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() 107 { 108 m_start = m_finish = NULL; 109 m_children.clear(); 110 ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true)); 111 if (!data_type_finder_sp) 112 return false; 113 data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true); 114 if (!data_type_finder_sp) 115 return false; 116 m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType(); 117 m_element_size = m_element_type.GetByteSize(nullptr); 118 119 if (m_element_size > 0) 120 { 121 // store raw pointers or end up with a circular dependency 122 m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get(); 123 m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get(); 124 } 125 return false; 126 } 127 128 bool 129 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren () 130 { 131 return true; 132 } 133 134 size_t 135 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 136 { 137 if (!m_start || !m_finish) 138 return UINT32_MAX; 139 return ExtractIndexFromString(name.GetCString()); 140 } 141 142 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd () 143 { 144 // these need to stay around because they are child objects who will follow their parent's life cycle 145 // delete m_start; 146 // delete m_finish; 147 } 148 149 lldb_private::SyntheticChildrenFrontEnd* 150 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 151 { 152 if (!valobj_sp) 153 return NULL; 154 return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp)); 155 } 156 157