1 //===-- LibStdcpp.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 "LibStdcpp.h"
11 
12 #include "lldb/Core/DataBufferHeap.h"
13 #include "lldb/Core/Error.h"
14 #include "lldb/Core/Stream.h"
15 #include "lldb/Core/ValueObject.h"
16 #include "lldb/Core/ValueObjectConstResult.h"
17 #include "lldb/DataFormatters/VectorIterator.h"
18 #include "lldb/Host/Endian.h"
19 #include "lldb/Symbol/ClangASTContext.h"
20 #include "lldb/Target/Target.h"
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 using namespace lldb_private::formatters;
25 
26 class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
27 {
28 public:
29     LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
30 
31     size_t
32     CalculateNumChildren() override;
33 
34     lldb::ValueObjectSP
35     GetChildAtIndex(size_t idx) override;
36 
37     bool
38     Update() override;
39 
40     bool
41     MightHaveChildren() override;
42 
43     size_t
44     GetIndexOfChildWithName (const ConstString &name) override;
45 
46     ~LibstdcppMapIteratorSyntheticFrontEnd() override;
47 
48 private:
49     ExecutionContextRef m_exe_ctx_ref;
50     lldb::addr_t m_pair_address;
51     CompilerType m_pair_type;
52     EvaluateExpressionOptions m_options;
53     lldb::ValueObjectSP m_pair_sp;
54 };
55 
56 /*
57  (std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) ibeg = {
58  (_Base_ptr) _M_node = 0x0000000100103910 {
59  (std::_Rb_tree_color) _M_color = _S_black
60  (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0
61  (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000
62  (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000
63  }
64  }
65  */
66 
67 LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
68     SyntheticChildrenFrontEnd(*valobj_sp.get()),
69     m_exe_ctx_ref(),
70     m_pair_address(0),
71     m_pair_type(),
72     m_options(),
73     m_pair_sp()
74 {
75     if (valobj_sp)
76         Update();
77     m_options.SetCoerceToId(false);
78     m_options.SetUnwindOnError(true);
79     m_options.SetKeepInMemory(true);
80     m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
81 }
82 
83 bool
84 LibstdcppMapIteratorSyntheticFrontEnd::Update()
85 {
86     ValueObjectSP valobj_sp = m_backend.GetSP();
87     if (!valobj_sp)
88         return false;
89 
90     TargetSP target_sp(valobj_sp->GetTargetSP());
91 
92     if (!target_sp)
93         return false;
94 
95     bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8);
96 
97     if (!valobj_sp)
98         return false;
99     m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
100 
101     ValueObjectSP _M_node_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_node"), true));
102     if (!_M_node_sp)
103         return false;
104 
105     m_pair_address = _M_node_sp->GetValueAsUnsigned(0);
106     if (m_pair_address == 0)
107         return false;
108 
109     m_pair_address += (is_64bit ? 32 : 16);
110 
111     CompilerType my_type(valobj_sp->GetCompilerType());
112     if (my_type.GetNumTemplateArguments() >= 1)
113     {
114         TemplateArgumentKind kind;
115         CompilerType pair_type = my_type.GetTemplateArgument(0, kind);
116         if (kind != eTemplateArgumentKindType && kind != eTemplateArgumentKindTemplate && kind != eTemplateArgumentKindTemplateExpansion)
117             return false;
118         m_pair_type = pair_type;
119     }
120     else
121         return false;
122 
123     return true;
124 }
125 
126 size_t
127 LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren ()
128 {
129     return 2;
130 }
131 
132 lldb::ValueObjectSP
133 LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
134 {
135     if (m_pair_address != 0 && m_pair_type)
136     {
137         if (!m_pair_sp)
138             m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type);
139         if (m_pair_sp)
140             return m_pair_sp->GetChildAtIndex(idx, true);
141     }
142     return lldb::ValueObjectSP();
143 }
144 
145 bool
146 LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren ()
147 {
148     return true;
149 }
150 
151 size_t
152 LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
153 {
154     if (name == ConstString("first"))
155         return 0;
156     if (name == ConstString("second"))
157         return 1;
158     return UINT32_MAX;
159 }
160 
161 LibstdcppMapIteratorSyntheticFrontEnd::~LibstdcppMapIteratorSyntheticFrontEnd ()
162 {}
163 
164 SyntheticChildrenFrontEnd*
165 lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
166 {
167     if (!valobj_sp)
168         return NULL;
169     return (new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp));
170 }
171 
172 /*
173  (lldb) fr var ibeg --ptr-depth 1
174  (__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >) ibeg = {
175  _M_current = 0x00000001001037a0 {
176  *_M_current = 1
177  }
178  }
179  */
180 
181 SyntheticChildrenFrontEnd*
182 lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
183 {
184     static ConstString g_item_name;
185     if (!g_item_name)
186         g_item_name.SetCString("_M_current");
187     if (!valobj_sp)
188         return NULL;
189     return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name));
190 }
191 
192 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
193                                                                                             ConstString item_name) :
194 SyntheticChildrenFrontEnd(*valobj_sp.get()),
195 m_exe_ctx_ref(),
196 m_item_name(item_name),
197 m_item_sp()
198 {
199     if (valobj_sp)
200         Update();
201 }
202 
203 bool
204 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
205 {
206     m_item_sp.reset();
207 
208     ValueObjectSP valobj_sp = m_backend.GetSP();
209     if (!valobj_sp)
210         return false;
211 
212     if (!valobj_sp)
213         return false;
214 
215     ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
216     if (!item_ptr)
217         return false;
218     if (item_ptr->GetValueAsUnsigned(0) == 0)
219         return false;
220     Error err;
221     m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
222     m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetCompilerType().GetPointeeType());
223     if (err.Fail())
224         m_item_sp.reset();
225     return false;
226 }
227 
228 size_t
229 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
230 {
231     return 1;
232 }
233 
234 lldb::ValueObjectSP
235 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
236 {
237     if (idx == 0)
238         return m_item_sp;
239     return lldb::ValueObjectSP();
240 }
241 
242 bool
243 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
244 {
245     return true;
246 }
247 
248 size_t
249 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
250 {
251     if (name == ConstString("item"))
252         return 0;
253     return UINT32_MAX;
254 }
255 
256 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
257 {
258 }
259