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 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "LibCxx.h"
15 
16 #include "lldb/Core/ConstString.h"
17 #include "lldb/Core/ValueObject.h"
18 #include "lldb/DataFormatters/FormattersHelpers.h"
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 using namespace lldb_private::formatters;
23 
24 namespace lldb_private {
25 namespace formatters {
26 class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
27 public:
28   LibcxxStdVectorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
29 
30   ~LibcxxStdVectorSyntheticFrontEnd() override;
31 
32   size_t CalculateNumChildren() override;
33 
34   lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
35 
36   bool Update() override;
37 
38   bool MightHaveChildren() override;
39 
40   size_t GetIndexOfChildWithName(const ConstString &name) override;
41 
42 private:
43   ValueObject *m_start;
44   ValueObject *m_finish;
45   CompilerType m_element_type;
46   uint32_t m_element_size;
47 };
48 } // namespace formatters
49 } // namespace lldb_private
50 
51 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::
52     LibcxxStdVectorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
53     : SyntheticChildrenFrontEnd(*valobj_sp), m_start(nullptr),
54       m_finish(nullptr), m_element_type(), m_element_size(0) {
55   if (valobj_sp)
56     Update();
57 }
58 
59 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::
60     ~LibcxxStdVectorSyntheticFrontEnd() {
61   // these need to stay around because they are child objects who will follow
62   // their parent's life cycle
63   // delete m_start;
64   // delete m_finish;
65 }
66 
67 size_t lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::
68     CalculateNumChildren() {
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(
88     size_t idx) {
89   if (!m_start || !m_finish)
90     return lldb::ValueObjectSP();
91 
92   uint64_t offset = idx * m_element_size;
93   offset = offset + m_start->GetValueAsUnsigned(0);
94   StreamString name;
95   name.Printf("[%" PRIu64 "]", (uint64_t)idx);
96   return CreateValueObjectFromAddress(name.GetData(), offset,
97                                       m_backend.GetExecutionContextRef(),
98                                       m_element_type);
99 }
100 
101 bool lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() {
102   m_start = m_finish = nullptr;
103   ValueObjectSP data_type_finder_sp(
104       m_backend.GetChildMemberWithName(ConstString("__end_cap_"), true));
105   if (!data_type_finder_sp)
106     return false;
107   data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(
108       ConstString("__first_"), true);
109   if (!data_type_finder_sp)
110     return false;
111   m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();
112   m_element_size = m_element_type.GetByteSize(nullptr);
113 
114   if (m_element_size > 0) {
115     // store raw pointers or end up with a circular dependency
116     m_start =
117         m_backend.GetChildMemberWithName(ConstString("__begin_"), true).get();
118     m_finish =
119         m_backend.GetChildMemberWithName(ConstString("__end_"), true).get();
120   }
121   return false;
122 }
123 
124 bool lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::
125     MightHaveChildren() {
126   return true;
127 }
128 
129 size_t lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::
130     GetIndexOfChildWithName(const ConstString &name) {
131   if (!m_start || !m_finish)
132     return UINT32_MAX;
133   return ExtractIndexFromString(name.GetCString());
134 }
135 
136 lldb_private::SyntheticChildrenFrontEnd *
137 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator(
138     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
139   return (valobj_sp ? new LibcxxStdVectorSyntheticFrontEnd(valobj_sp)
140                     : nullptr);
141 }
142