]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/DataFormatters/LibCxx.cpp
Merge ^/head r288035 through r288099.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / DataFormatters / LibCxx.cpp
1 //===-- LibCxx.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 "lldb/DataFormatters/CXXFormatterFunctions.h"
11
12 #include "lldb/Core/DataBufferHeap.h"
13 #include "lldb/Core/Debugger.h"
14 #include "lldb/Core/Error.h"
15 #include "lldb/Core/FormatEntity.h"
16 #include "lldb/Core/Stream.h"
17 #include "lldb/Core/ValueObject.h"
18 #include "lldb/Core/ValueObjectConstResult.h"
19 #include "lldb/Host/Endian.h"
20 #include "lldb/Symbol/ClangASTContext.h"
21 #include "lldb/Target/ObjCLanguageRuntime.h"
22 #include "lldb/Target/Target.h"
23
24 using namespace lldb;
25 using namespace lldb_private;
26 using namespace lldb_private::formatters;
27
28 bool
29 lldb_private::formatters::LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
30 {
31     ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
32     if (!valobj_sp)
33         return false;
34     ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
35     ValueObjectSP count_sp(valobj_sp->GetChildAtNamePath( {ConstString("__cntrl_"),ConstString("__shared_owners_")} ));
36     ValueObjectSP weakcount_sp(valobj_sp->GetChildAtNamePath( {ConstString("__cntrl_"),ConstString("__shared_weak_owners_")} ));
37     
38     if (!ptr_sp)
39         return false;
40     
41     if (ptr_sp->GetValueAsUnsigned(0) == 0)
42     {
43         stream.Printf("nullptr");
44         return true;
45     }
46     else
47     {
48         bool print_pointee = false;
49         Error error;
50         ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
51         if (pointee_sp && error.Success())
52         {
53             if (pointee_sp->DumpPrintableRepresentation(stream,
54                                                         ValueObject::eValueObjectRepresentationStyleSummary,
55                                                         lldb::eFormatInvalid,
56                                                         ValueObject::ePrintableRepresentationSpecialCasesDisable,
57                                                         false))
58                 print_pointee = true;
59         }
60         if (!print_pointee)
61             stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
62     }
63     
64     if (count_sp)
65         stream.Printf(" strong=%" PRIu64, 1+count_sp->GetValueAsUnsigned(0));
66
67     if (weakcount_sp)
68         stream.Printf(" weak=%" PRIu64, 1+weakcount_sp->GetValueAsUnsigned(0));
69     
70     return true;
71 }
72
73 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
74 SyntheticChildrenFrontEnd(*valobj_sp.get()),
75 m_bool_type(),
76 m_exe_ctx_ref(),
77 m_count(0),
78 m_base_data_address(0),
79 m_children()
80 {
81     if (valobj_sp)
82     {
83         Update();
84         m_bool_type = valobj_sp->GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeBool);
85     }
86 }
87
88 size_t
89 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
90 {
91     return m_count;
92 }
93
94 lldb::ValueObjectSP
95 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
96 {
97     auto iter = m_children.find(idx),
98         end = m_children.end();
99     if (iter != end)
100         return iter->second;
101     if (idx >= m_count)
102         return ValueObjectSP();
103     if (m_base_data_address == 0 || m_count == 0)
104         return ValueObjectSP();
105     if (!m_bool_type)
106         return ValueObjectSP();
107     size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
108     size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
109     lldb::addr_t byte_location = m_base_data_address + byte_idx;
110     ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
111     if (!process_sp)
112         return ValueObjectSP();
113     uint8_t byte = 0;
114     uint8_t mask = 0;
115     Error err;
116     size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
117     if (err.Fail() || bytes_read == 0)
118         return ValueObjectSP();
119     switch (bit_index)
120     {
121         case 0:
122             mask = 1; break;
123         case 1:
124             mask = 2; break;
125         case 2:
126             mask = 4; break;
127         case 3:
128             mask = 8; break;
129         case 4:
130             mask = 16; break;
131         case 5:
132             mask = 32; break;
133         case 6:
134             mask = 64; break;
135         case 7:
136             mask = 128; break;
137         default:
138             return ValueObjectSP();
139     }
140     bool bit_set = ((byte & mask) != 0);
141     DataBufferSP buffer_sp(new DataBufferHeap(m_bool_type.GetByteSize(nullptr),0));
142     if (bit_set && buffer_sp && buffer_sp->GetBytes())
143         *(buffer_sp->GetBytes()) = 1; // regardless of endianness, anything non-zero is true
144     StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx);
145     ValueObjectSP retval_sp(CreateValueObjectFromData(name.GetData(), DataExtractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()), m_exe_ctx_ref, m_bool_type));
146     if (retval_sp)
147         m_children[idx] = retval_sp;
148     return retval_sp;
149 }
150
151 /*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
152  __begin_ = 0x00000001001000e0
153  __size_ = 56
154  __cap_alloc_ = {
155  std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = {
156  __first_ = 1
157  }
158  }
159  }*/
160
161 bool
162 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update()
163 {
164     m_children.clear();
165     ValueObjectSP valobj_sp = m_backend.GetSP();
166     if (!valobj_sp)
167         return false;
168     m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
169     ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
170     if (!size_sp)
171         return false;
172     m_count = size_sp->GetValueAsUnsigned(0);
173     if (!m_count)
174         return true;
175     ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
176     if (!begin_sp)
177     {
178         m_count = 0;
179         return false;
180     }
181     m_base_data_address = begin_sp->GetValueAsUnsigned(0);
182     if (!m_base_data_address)
183     {
184         m_count = 0;
185         return false;
186     }
187     return false;
188 }
189
190 bool
191 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren ()
192 {
193     return true;
194 }
195
196 size_t
197 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
198 {
199     if (!m_count || !m_base_data_address)
200         return UINT32_MAX;
201     const char* item_name = name.GetCString();
202     uint32_t idx = ExtractIndexFromString(item_name);
203     if (idx < UINT32_MAX && idx >= CalculateNumChildren())
204         return UINT32_MAX;
205     return idx;
206 }
207
208 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd ()
209 {}
210
211 SyntheticChildrenFrontEnd*
212 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
213 {
214     if (!valobj_sp)
215         return NULL;
216     return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp));
217 }
218
219 /*
220  (lldb) fr var ibeg --raw --ptr-depth 1
221  (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void *> *, long> >) ibeg = {
222  __i_ = {
223  __ptr_ = 0x0000000100103870 {
224  std::__1::__tree_node_base<void *> = {
225  std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
226  __left_ = 0x0000000000000000
227  }
228  __right_ = 0x0000000000000000
229  __parent_ = 0x00000001001038b0
230  __is_black_ = true
231  }
232  __value_ = {
233  first = 0
234  second = { std::string }
235  */
236
237 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
238 SyntheticChildrenFrontEnd(*valobj_sp.get()),
239 m_pair_ptr()
240 {
241     if (valobj_sp)
242         Update();
243 }
244
245 bool
246 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update()
247 {
248     ValueObjectSP valobj_sp = m_backend.GetSP();
249     if (!valobj_sp)
250         return false;
251     
252     TargetSP target_sp(valobj_sp->GetTargetSP());
253     
254     if (!target_sp)
255         return false;
256
257     if (!valobj_sp)
258         return false;
259
260     // this must be a ValueObject* because it is a child of the ValueObject we are producing children for
261     // it if were a ValueObjectSP, we would end up with a loop (iterator -> synthetic -> child -> parent == iterator)
262     // and that would in turn leak memory by never allowing the ValueObjects to die and free their memory
263     m_pair_ptr = valobj_sp->GetValueForExpressionPath(".__i_.__ptr_->__value_",
264                                                      NULL,
265                                                      NULL,
266                                                      NULL,
267                                                      ValueObject::GetValueForExpressionPathOptions().DontCheckDotVsArrowSyntax().SetSyntheticChildrenTraversal(ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None),
268                                                      NULL).get();
269     
270     return false;
271 }
272
273 size_t
274 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::CalculateNumChildren ()
275 {
276     return 2;
277 }
278
279 lldb::ValueObjectSP
280 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
281 {
282     if (!m_pair_ptr)
283         return lldb::ValueObjectSP();
284     return m_pair_ptr->GetChildAtIndex(idx, true);
285 }
286
287 bool
288 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::MightHaveChildren ()
289 {
290     return true;
291 }
292
293 size_t
294 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
295 {
296     if (name == ConstString("first"))
297         return 0;
298     if (name == ConstString("second"))
299         return 1;
300     return UINT32_MAX;
301 }
302
303 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::~LibCxxMapIteratorSyntheticFrontEnd ()
304 {
305     // this will be deleted when its parent dies (since it's a child object)
306     //delete m_pair_ptr;
307 }
308
309 SyntheticChildrenFrontEnd*
310 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
311 {
312     if (!valobj_sp)
313         return NULL;
314     return (new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp));
315 }
316
317 /*
318  (lldb) fr var ibeg --raw --ptr-depth 1 -T
319  (std::__1::__wrap_iter<int *>) ibeg = {
320  (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
321  (int) *__i = 1
322  }
323  }
324 */
325
326 SyntheticChildrenFrontEnd*
327 lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
328 {
329     static ConstString g_item_name;
330     if (!g_item_name)
331         g_item_name.SetCString("__i");
332     if (!valobj_sp)
333         return NULL;
334     return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name));
335 }
336
337 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
338 SyntheticChildrenFrontEnd(*valobj_sp.get()),
339 m_cntrl(NULL),
340 m_count_sp(),
341 m_weak_count_sp(),
342 m_ptr_size(0),
343 m_byte_order(lldb::eByteOrderInvalid)
344 {
345     if (valobj_sp)
346         Update();
347 }
348
349 size_t
350 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::CalculateNumChildren ()
351 {
352     return (m_cntrl ? 1 : 0);
353 }
354
355 lldb::ValueObjectSP
356 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (size_t idx)
357 {
358     if (!m_cntrl)
359         return lldb::ValueObjectSP();
360
361     ValueObjectSP valobj_sp = m_backend.GetSP();
362     if (!valobj_sp)
363         return lldb::ValueObjectSP();
364
365     if (idx == 0)
366         return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
367
368     if (idx > 2)
369         return lldb::ValueObjectSP();
370
371     if (idx == 1)
372     {
373         if (!m_count_sp)
374         {
375             ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_owners_"),true));
376             if (!shared_owners_sp)
377                 return lldb::ValueObjectSP();
378             uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
379             DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
380             m_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetClangType());
381         }
382         return m_count_sp;
383     }
384     else /* if (idx == 2) */
385     {
386         if (!m_weak_count_sp)
387         {
388             ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_weak_owners_"),true));
389             if (!shared_weak_owners_sp)
390                 return lldb::ValueObjectSP();
391             uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
392             DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
393             m_weak_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetClangType());
394         }
395         return m_weak_count_sp;
396     }
397 }
398
399 bool
400 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update()
401 {
402     m_count_sp.reset();
403     m_weak_count_sp.reset();
404     m_cntrl = NULL;
405     
406     ValueObjectSP valobj_sp = m_backend.GetSP();
407     if (!valobj_sp)
408         return false;
409     
410     TargetSP target_sp(valobj_sp->GetTargetSP());
411     if (!target_sp)
412         return false;
413     
414     m_byte_order = target_sp->GetArchitecture().GetByteOrder();
415     m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize();
416     
417     lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"),true));
418     
419     m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular dependency
420     return false;
421 }
422
423 bool
424 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::MightHaveChildren ()
425 {
426     return true;
427 }
428
429 size_t
430 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
431 {
432     if (name == ConstString("__ptr_"))
433         return 0;
434     if (name == ConstString("count"))
435         return 1;
436     if (name == ConstString("weak_count"))
437         return 2;
438     return UINT32_MAX;
439 }
440
441 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::~LibcxxSharedPtrSyntheticFrontEnd ()
442 {}
443
444 SyntheticChildrenFrontEnd*
445 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
446 {
447     if (!valobj_sp)
448         return NULL;
449     return (new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp));
450 }
451
452 bool
453 lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
454 {
455     if (valobj.IsPointerType())
456     {
457         uint64_t value = valobj.GetValueAsUnsigned(0);
458         if (!value)
459             return false;
460         stream.Printf("0x%016" PRIx64 " ", value);
461     }
462     return FormatEntity::FormatStringRef("size=${svar%#}", stream, NULL, NULL, NULL, &valobj, false, false);
463 }