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