]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
Merge clang trunk r321414 to contrib/llvm.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / Language / CPlusPlus / LibStdcpp.cpp
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 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/ValueObject.h"
17 #include "lldb/Core/ValueObjectConstResult.h"
18 #include "lldb/DataFormatters/StringPrinter.h"
19 #include "lldb/DataFormatters/VectorIterator.h"
20 #include "lldb/Symbol/ClangASTContext.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Utility/DataBufferHeap.h"
23 #include "lldb/Utility/Endian.h"
24 #include "lldb/Utility/Status.h"
25 #include "lldb/Utility/Stream.h"
26
27 using namespace lldb;
28 using namespace lldb_private;
29 using namespace lldb_private::formatters;
30
31 namespace {
32
33 class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
34   /*
35    (std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char,
36    std::char_traits<char>, std::allocator<char> > > >) ibeg = {
37    (_Base_ptr) _M_node = 0x0000000100103910 {
38    (std::_Rb_tree_color) _M_color = _S_black
39    (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0
40    (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000
41    (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000
42    }
43    }
44    */
45
46 public:
47   explicit LibstdcppMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
48
49   size_t CalculateNumChildren() override;
50
51   lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
52
53   bool Update() override;
54
55   bool MightHaveChildren() override;
56
57   size_t GetIndexOfChildWithName(const ConstString &name) override;
58
59 private:
60   ExecutionContextRef m_exe_ctx_ref;
61   lldb::addr_t m_pair_address;
62   CompilerType m_pair_type;
63   lldb::ValueObjectSP m_pair_sp;
64 };
65
66 class LibStdcppSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
67 public:
68   explicit LibStdcppSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
69
70   size_t CalculateNumChildren() override;
71
72   lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
73
74   bool Update() override;
75
76   bool MightHaveChildren() override;
77
78   size_t GetIndexOfChildWithName(const ConstString &name) override;
79 };
80
81 } // end of anonymous namespace
82
83 LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd(
84     lldb::ValueObjectSP valobj_sp)
85     : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_address(0),
86       m_pair_type(), m_pair_sp() {
87   if (valobj_sp)
88     Update();
89 }
90
91 bool LibstdcppMapIteratorSyntheticFrontEnd::Update() {
92   ValueObjectSP valobj_sp = m_backend.GetSP();
93   if (!valobj_sp)
94     return false;
95
96   TargetSP target_sp(valobj_sp->GetTargetSP());
97
98   if (!target_sp)
99     return false;
100
101   bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8);
102
103   if (!valobj_sp)
104     return false;
105   m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
106
107   ValueObjectSP _M_node_sp(
108       valobj_sp->GetChildMemberWithName(ConstString("_M_node"), true));
109   if (!_M_node_sp)
110     return false;
111
112   m_pair_address = _M_node_sp->GetValueAsUnsigned(0);
113   if (m_pair_address == 0)
114     return false;
115
116   m_pair_address += (is_64bit ? 32 : 16);
117
118   CompilerType my_type(valobj_sp->GetCompilerType());
119   if (my_type.GetNumTemplateArguments() >= 1) {
120     CompilerType pair_type = my_type.GetTypeTemplateArgument(0);
121     if (!pair_type)
122       return false;
123     m_pair_type = pair_type;
124   } else
125     return false;
126
127   return true;
128 }
129
130 size_t LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren() {
131   return 2;
132 }
133
134 lldb::ValueObjectSP
135 LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
136   if (m_pair_address != 0 && m_pair_type) {
137     if (!m_pair_sp)
138       m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address,
139                                                m_exe_ctx_ref, m_pair_type);
140     if (m_pair_sp)
141       return m_pair_sp->GetChildAtIndex(idx, true);
142   }
143   return lldb::ValueObjectSP();
144 }
145
146 bool LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren() { return true; }
147
148 size_t LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName(
149     const ConstString &name) {
150   if (name == ConstString("first"))
151     return 0;
152   if (name == ConstString("second"))
153     return 1;
154   return UINT32_MAX;
155 }
156
157 SyntheticChildrenFrontEnd *
158 lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator(
159     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
160   return (valobj_sp ? new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp)
161                     : nullptr);
162 }
163
164 /*
165  (lldb) fr var ibeg --ptr-depth 1
166  (__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >)
167  ibeg = {
168  _M_current = 0x00000001001037a0 {
169  *_M_current = 1
170  }
171  }
172  */
173
174 SyntheticChildrenFrontEnd *
175 lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator(
176     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
177   static ConstString g_item_name;
178   if (!g_item_name)
179     g_item_name.SetCString("_M_current");
180   return (valobj_sp
181               ? new VectorIteratorSyntheticFrontEnd(valobj_sp, g_item_name)
182               : nullptr);
183 }
184
185 lldb_private::formatters::VectorIteratorSyntheticFrontEnd::
186     VectorIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp,
187                                     ConstString item_name)
188     : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(),
189       m_item_name(item_name), m_item_sp() {
190   if (valobj_sp)
191     Update();
192 }
193
194 bool VectorIteratorSyntheticFrontEnd::Update() {
195   m_item_sp.reset();
196
197   ValueObjectSP valobj_sp = m_backend.GetSP();
198   if (!valobj_sp)
199     return false;
200
201   if (!valobj_sp)
202     return false;
203
204   ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name, true));
205   if (!item_ptr)
206     return false;
207   if (item_ptr->GetValueAsUnsigned(0) == 0)
208     return false;
209   Status err;
210   m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
211   m_item_sp = CreateValueObjectFromAddress(
212       "item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref,
213       item_ptr->GetCompilerType().GetPointeeType());
214   if (err.Fail())
215     m_item_sp.reset();
216   return false;
217 }
218
219 size_t VectorIteratorSyntheticFrontEnd::CalculateNumChildren() { return 1; }
220
221 lldb::ValueObjectSP
222 VectorIteratorSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
223   if (idx == 0)
224     return m_item_sp;
225   return lldb::ValueObjectSP();
226 }
227
228 bool VectorIteratorSyntheticFrontEnd::MightHaveChildren() { return true; }
229
230 size_t VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName(
231     const ConstString &name) {
232   if (name == ConstString("item"))
233     return 0;
234   return UINT32_MAX;
235 }
236
237 bool lldb_private::formatters::LibStdcppStringSummaryProvider(
238     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
239   const bool scalar_is_load_addr = true;
240   AddressType addr_type;
241   lldb::addr_t addr_of_string =
242       valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
243   if (addr_of_string != LLDB_INVALID_ADDRESS) {
244     switch (addr_type) {
245     case eAddressTypeLoad: {
246       ProcessSP process_sp(valobj.GetProcessSP());
247       if (!process_sp)
248         return false;
249
250       StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
251       Status error;
252       lldb::addr_t addr_of_data =
253           process_sp->ReadPointerFromMemory(addr_of_string, error);
254       if (error.Fail() || addr_of_data == 0 ||
255           addr_of_data == LLDB_INVALID_ADDRESS)
256         return false;
257       options.SetLocation(addr_of_data);
258       options.SetProcessSP(process_sp);
259       options.SetStream(&stream);
260       options.SetNeedsZeroTermination(false);
261       options.SetBinaryZeroIsTerminator(true);
262       lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(
263           addr_of_string + process_sp->GetAddressByteSize(), error);
264       if (error.Fail())
265         return false;
266       options.SetSourceSize(size_of_data);
267
268       if (!StringPrinter::ReadStringAndDumpToStream<
269               StringPrinter::StringElementType::UTF8>(options)) {
270         stream.Printf("Summary Unavailable");
271         return true;
272       } else
273         return true;
274     } break;
275     case eAddressTypeHost:
276       break;
277     case eAddressTypeInvalid:
278     case eAddressTypeFile:
279       break;
280     }
281   }
282   return false;
283 }
284
285 bool lldb_private::formatters::LibStdcppWStringSummaryProvider(
286     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
287   const bool scalar_is_load_addr = true;
288   AddressType addr_type;
289   lldb::addr_t addr_of_string =
290       valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
291   if (addr_of_string != LLDB_INVALID_ADDRESS) {
292     switch (addr_type) {
293     case eAddressTypeLoad: {
294       ProcessSP process_sp(valobj.GetProcessSP());
295       if (!process_sp)
296         return false;
297
298       CompilerType wchar_compiler_type =
299           valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
300
301       if (!wchar_compiler_type)
302         return false;
303
304       const uint32_t wchar_size = wchar_compiler_type.GetBitSize(
305           nullptr); // Safe to pass NULL for exe_scope here
306
307       StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
308       Status error;
309       lldb::addr_t addr_of_data =
310           process_sp->ReadPointerFromMemory(addr_of_string, error);
311       if (error.Fail() || addr_of_data == 0 ||
312           addr_of_data == LLDB_INVALID_ADDRESS)
313         return false;
314       options.SetLocation(addr_of_data);
315       options.SetProcessSP(process_sp);
316       options.SetStream(&stream);
317       options.SetNeedsZeroTermination(false);
318       options.SetBinaryZeroIsTerminator(false);
319       lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(
320           addr_of_string + process_sp->GetAddressByteSize(), error);
321       if (error.Fail())
322         return false;
323       options.SetSourceSize(size_of_data);
324       options.SetPrefixToken("L");
325
326       switch (wchar_size) {
327       case 8:
328         return StringPrinter::ReadStringAndDumpToStream<
329             StringPrinter::StringElementType::UTF8>(options);
330       case 16:
331         return StringPrinter::ReadStringAndDumpToStream<
332             StringPrinter::StringElementType::UTF16>(options);
333       case 32:
334         return StringPrinter::ReadStringAndDumpToStream<
335             StringPrinter::StringElementType::UTF32>(options);
336       default:
337         stream.Printf("size for wchar_t is not valid");
338         return true;
339       }
340       return true;
341     } break;
342     case eAddressTypeHost:
343       break;
344     case eAddressTypeInvalid:
345     case eAddressTypeFile:
346       break;
347     }
348   }
349   return false;
350 }
351
352 LibStdcppSharedPtrSyntheticFrontEnd::LibStdcppSharedPtrSyntheticFrontEnd(
353     lldb::ValueObjectSP valobj_sp)
354     : SyntheticChildrenFrontEnd(*valobj_sp) {
355   if (valobj_sp)
356     Update();
357 }
358
359 size_t LibStdcppSharedPtrSyntheticFrontEnd::CalculateNumChildren() { return 1; }
360
361 lldb::ValueObjectSP
362 LibStdcppSharedPtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
363   ValueObjectSP valobj_sp = m_backend.GetSP();
364   if (!valobj_sp)
365     return lldb::ValueObjectSP();
366
367   if (idx == 0)
368     return valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true);
369   else
370     return lldb::ValueObjectSP();
371 }
372
373 bool LibStdcppSharedPtrSyntheticFrontEnd::Update() { return false; }
374
375 bool LibStdcppSharedPtrSyntheticFrontEnd::MightHaveChildren() { return true; }
376
377 size_t LibStdcppSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName(
378     const ConstString &name) {
379   if (name == ConstString("_M_ptr"))
380     return 0;
381   return UINT32_MAX;
382 }
383
384 SyntheticChildrenFrontEnd *
385 lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator(
386     CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
387   return (valobj_sp ? new LibStdcppSharedPtrSyntheticFrontEnd(valobj_sp)
388                     : nullptr);
389 }
390
391 bool lldb_private::formatters::LibStdcppSmartPointerSummaryProvider(
392     ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
393   ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
394   if (!valobj_sp)
395     return false;
396
397   ValueObjectSP ptr_sp(
398       valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true));
399   if (!ptr_sp)
400     return false;
401
402   ValueObjectSP usecount_sp(valobj_sp->GetChildAtNamePath(
403       {ConstString("_M_refcount"), ConstString("_M_pi"),
404        ConstString("_M_use_count")}));
405   if (!usecount_sp)
406     return false;
407
408   if (ptr_sp->GetValueAsUnsigned(0) == 0 ||
409       usecount_sp->GetValueAsUnsigned(0) == 0) {
410     stream.Printf("nullptr");
411     return true;
412   }
413
414   Status error;
415   ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
416   if (pointee_sp && error.Success()) {
417     if (pointee_sp->DumpPrintableRepresentation(
418             stream, ValueObject::eValueObjectRepresentationStyleSummary,
419             lldb::eFormatInvalid,
420             ValueObject::PrintableRepresentationSpecialCases::eDisable,
421             false)) {
422       return true;
423     }
424   }
425
426   stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
427   return true;
428 }