blob: ed89c5c84ea3a03e97416c53de746208d20a84d9 [file] [log] [blame]
Enrico Granataea2bc0f2013-02-21 19:57:10 +00001//===-- 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
Enrico Granata33e97e62015-09-04 21:01:18 +000010#include "LibStdcpp.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000011
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"
Todd Fiala82ffb8e2015-10-22 00:23:38 +000017#include "lldb/DataFormatters/StringPrinter.h"
Enrico Granata419d7912015-09-04 00:33:51 +000018#include "lldb/DataFormatters/VectorIterator.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000019#include "lldb/Host/Endian.h"
20#include "lldb/Symbol/ClangASTContext.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000021#include "lldb/Target/Target.h"
22
23using namespace lldb;
24using namespace lldb_private;
25using namespace lldb_private::formatters;
26
Enrico Granata419d7912015-09-04 00:33:51 +000027class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
28{
29public:
30 LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
31
32 size_t
33 CalculateNumChildren() override;
34
35 lldb::ValueObjectSP
36 GetChildAtIndex(size_t idx) override;
37
38 bool
39 Update() override;
40
41 bool
42 MightHaveChildren() override;
43
44 size_t
45 GetIndexOfChildWithName (const ConstString &name) override;
46
47 ~LibstdcppMapIteratorSyntheticFrontEnd() override;
48
49private:
50 ExecutionContextRef m_exe_ctx_ref;
51 lldb::addr_t m_pair_address;
52 CompilerType m_pair_type;
53 EvaluateExpressionOptions m_options;
54 lldb::ValueObjectSP m_pair_sp;
55};
56
Enrico Granataea2bc0f2013-02-21 19:57:10 +000057/*
58 (std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) ibeg = {
59 (_Base_ptr) _M_node = 0x0000000100103910 {
60 (std::_Rb_tree_color) _M_color = _S_black
61 (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0
62 (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000
63 (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000
64 }
65 }
66 */
67
Enrico Granata419d7912015-09-04 00:33:51 +000068LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
Greg Clayton57ee3062013-07-11 22:46:58 +000069 SyntheticChildrenFrontEnd(*valobj_sp.get()),
70 m_exe_ctx_ref(),
71 m_pair_address(0),
72 m_pair_type(),
73 m_options(),
74 m_pair_sp()
Enrico Granataea2bc0f2013-02-21 19:57:10 +000075{
76 if (valobj_sp)
77 Update();
Jim Ingham6fbc48b2013-11-07 00:11:47 +000078 m_options.SetCoerceToId(false);
79 m_options.SetUnwindOnError(true);
80 m_options.SetKeepInMemory(true);
81 m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
Enrico Granataea2bc0f2013-02-21 19:57:10 +000082}
83
84bool
Enrico Granata419d7912015-09-04 00:33:51 +000085LibstdcppMapIteratorSyntheticFrontEnd::Update()
Enrico Granataea2bc0f2013-02-21 19:57:10 +000086{
87 ValueObjectSP valobj_sp = m_backend.GetSP();
88 if (!valobj_sp)
89 return false;
90
91 TargetSP target_sp(valobj_sp->GetTargetSP());
92
93 if (!target_sp)
94 return false;
95
96 bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8);
97
98 if (!valobj_sp)
99 return false;
100 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
101
102 ValueObjectSP _M_node_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_node"), true));
103 if (!_M_node_sp)
104 return false;
105
106 m_pair_address = _M_node_sp->GetValueAsUnsigned(0);
107 if (m_pair_address == 0)
108 return false;
109
110 m_pair_address += (is_64bit ? 32 : 16);
111
Greg Clayton99558cc42015-08-24 23:46:31 +0000112 CompilerType my_type(valobj_sp->GetCompilerType());
Enrico Granata53f2a4a2015-08-13 00:24:24 +0000113 if (my_type.GetNumTemplateArguments() >= 1)
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000114 {
115 TemplateArgumentKind kind;
Enrico Granata53f2a4a2015-08-13 00:24:24 +0000116 CompilerType pair_type = my_type.GetTemplateArgument(0, kind);
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000117 if (kind != eTemplateArgumentKindType && kind != eTemplateArgumentKindTemplate && kind != eTemplateArgumentKindTemplateExpansion)
118 return false;
Greg Clayton57ee3062013-07-11 22:46:58 +0000119 m_pair_type = pair_type;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000120 }
121 else
122 return false;
123
124 return true;
125}
126
127size_t
Enrico Granata419d7912015-09-04 00:33:51 +0000128LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren ()
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000129{
130 return 2;
131}
132
133lldb::ValueObjectSP
Enrico Granata419d7912015-09-04 00:33:51 +0000134LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000135{
Greg Clayton57ee3062013-07-11 22:46:58 +0000136 if (m_pair_address != 0 && m_pair_type)
137 {
138 if (!m_pair_sp)
Enrico Granatae29df232014-12-09 19:51:20 +0000139 m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type);
Greg Clayton57ee3062013-07-11 22:46:58 +0000140 if (m_pair_sp)
141 return m_pair_sp->GetChildAtIndex(idx, true);
142 }
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000143 return lldb::ValueObjectSP();
144}
145
146bool
Enrico Granata419d7912015-09-04 00:33:51 +0000147LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren ()
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000148{
149 return true;
150}
151
152size_t
Enrico Granata419d7912015-09-04 00:33:51 +0000153LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000154{
155 if (name == ConstString("first"))
156 return 0;
157 if (name == ConstString("second"))
158 return 1;
159 return UINT32_MAX;
160}
161
Enrico Granata419d7912015-09-04 00:33:51 +0000162LibstdcppMapIteratorSyntheticFrontEnd::~LibstdcppMapIteratorSyntheticFrontEnd ()
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000163{}
164
165SyntheticChildrenFrontEnd*
166lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
167{
168 if (!valobj_sp)
169 return NULL;
170 return (new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp));
171}
172
173/*
174 (lldb) fr var ibeg --ptr-depth 1
175 (__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >) ibeg = {
176 _M_current = 0x00000001001037a0 {
177 *_M_current = 1
178 }
179 }
180 */
181
182SyntheticChildrenFrontEnd*
183lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
184{
185 static ConstString g_item_name;
186 if (!g_item_name)
187 g_item_name.SetCString("_M_current");
188 if (!valobj_sp)
189 return NULL;
190 return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name));
191}
Enrico Granatad87cc312015-09-03 01:29:42 +0000192
193lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
194 ConstString item_name) :
195SyntheticChildrenFrontEnd(*valobj_sp.get()),
196m_exe_ctx_ref(),
197m_item_name(item_name),
198m_item_sp()
199{
200 if (valobj_sp)
201 Update();
202}
203
204bool
205lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
206{
207 m_item_sp.reset();
208
209 ValueObjectSP valobj_sp = m_backend.GetSP();
210 if (!valobj_sp)
211 return false;
212
213 if (!valobj_sp)
214 return false;
215
216 ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
217 if (!item_ptr)
218 return false;
219 if (item_ptr->GetValueAsUnsigned(0) == 0)
220 return false;
221 Error err;
222 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
223 m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetCompilerType().GetPointeeType());
224 if (err.Fail())
225 m_item_sp.reset();
226 return false;
227}
228
229size_t
230lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
231{
232 return 1;
233}
234
235lldb::ValueObjectSP
236lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
237{
238 if (idx == 0)
239 return m_item_sp;
240 return lldb::ValueObjectSP();
241}
242
243bool
244lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
245{
246 return true;
247}
248
249size_t
250lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
251{
252 if (name == ConstString("item"))
253 return 0;
254 return UINT32_MAX;
255}
256
257lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
258{
259}
Todd Fiala82ffb8e2015-10-22 00:23:38 +0000260
261bool
262lldb_private::formatters::LibStdcppStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
263{
264 const bool scalar_is_load_addr = true;
265 AddressType addr_type;
266 lldb::addr_t addr_of_string = valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
267 if (addr_of_string != LLDB_INVALID_ADDRESS)
268 {
269 switch (addr_type)
270 {
271 case eAddressTypeLoad:
272 {
273 ProcessSP process_sp(valobj.GetProcessSP());
274 if (!process_sp)
275 return false;
276
277 StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
278 Error error;
279 lldb::addr_t addr_of_data = process_sp->ReadPointerFromMemory(addr_of_string, error);
280 if (error.Fail() || addr_of_data == 0 || addr_of_data == LLDB_INVALID_ADDRESS)
281 return false;
282 options.SetLocation(addr_of_data);
283 options.SetProcessSP(process_sp);
284 options.SetStream(&stream);
285 options.SetNeedsZeroTermination(false);
286 options.SetBinaryZeroIsTerminator(true);
287 lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(addr_of_string + process_sp->GetAddressByteSize(), error);
288 if (error.Fail())
289 return false;
290 options.SetSourceSize(size_of_data);
291
292 if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options))
293 {
294 stream.Printf("Summary Unavailable");
295 return true;
296 }
297 else
298 return true;
299 }
300 break;
301 case eAddressTypeHost:
302 break;
303 case eAddressTypeInvalid:
304 case eAddressTypeFile:
305 break;
306 }
307 }
308 return false;
309}
310
311bool
312lldb_private::formatters::LibStdcppWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
313{
314 const bool scalar_is_load_addr = true;
315 AddressType addr_type;
316 lldb::addr_t addr_of_string = valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
317 if (addr_of_string != LLDB_INVALID_ADDRESS)
318 {
319 switch (addr_type)
320 {
321 case eAddressTypeLoad:
322 {
323 ProcessSP process_sp(valobj.GetProcessSP());
324 if (!process_sp)
325 return false;
326
327 CompilerType wchar_compiler_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
328
329 if (!wchar_compiler_type)
330 return false;
331
332 const uint32_t wchar_size = wchar_compiler_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here
333
334 StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
335 Error error;
336 lldb::addr_t addr_of_data = process_sp->ReadPointerFromMemory(addr_of_string, error);
337 if (error.Fail() || addr_of_data == 0 || addr_of_data == LLDB_INVALID_ADDRESS)
338 return false;
339 options.SetLocation(addr_of_data);
340 options.SetProcessSP(process_sp);
341 options.SetStream(&stream);
342 options.SetNeedsZeroTermination(false);
343 options.SetBinaryZeroIsTerminator(false);
344 lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(addr_of_string + process_sp->GetAddressByteSize(), error);
345 if (error.Fail())
346 return false;
347 options.SetSourceSize(size_of_data);
348 options.SetPrefixToken("L");
349
350 switch (wchar_size)
351 {
352 case 8:
353 return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options);
354 case 16:
355 return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
356 case 32:
357 return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32>(options);
358 default:
359 stream.Printf("size for wchar_t is not valid");
360 return true;
361 }
362 return true;
363 }
364 break;
365 case eAddressTypeHost:
366 break;
367 case eAddressTypeInvalid:
368 case eAddressTypeFile:
369 break;
370 }
371 }
372 return false;
373}