]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/DataFormatters/LibCxx.cpp
MFH: r278968-r280640
[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/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, const TypeSummaryOptions& options)
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     DataBufferSP buffer_sp(new DataBufferHeap(m_bool_type.GetByteSize(),0));
143     if (bit_set && buffer_sp && buffer_sp->GetBytes())
144         *(buffer_sp->GetBytes()) = 1; // regardless of endianness, anything non-zero is true
145     StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx);
146     ValueObjectSP retval_sp(CreateValueObjectFromData(name.GetData(), DataExtractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()), m_exe_ctx_ref, m_bool_type));
147     if (retval_sp)
148         m_children[idx] = retval_sp;
149     return retval_sp;
150 }
151
152 /*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
153  __begin_ = 0x00000001001000e0
154  __size_ = 56
155  __cap_alloc_ = {
156  std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = {
157  __first_ = 1
158  }
159  }
160  }*/
161
162 bool
163 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update()
164 {
165     m_children.clear();
166     ValueObjectSP valobj_sp = m_backend.GetSP();
167     if (!valobj_sp)
168         return false;
169     m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
170     ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
171     if (!size_sp)
172         return false;
173     m_count = size_sp->GetValueAsUnsigned(0);
174     if (!m_count)
175         return true;
176     ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
177     if (!begin_sp)
178     {
179         m_count = 0;
180         return false;
181     }
182     m_base_data_address = begin_sp->GetValueAsUnsigned(0);
183     if (!m_base_data_address)
184     {
185         m_count = 0;
186         return false;
187     }
188     return false;
189 }
190
191 bool
192 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren ()
193 {
194     return true;
195 }
196
197 size_t
198 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
199 {
200     if (!m_count || !m_base_data_address)
201         return UINT32_MAX;
202     const char* item_name = name.GetCString();
203     uint32_t idx = ExtractIndexFromString(item_name);
204     if (idx < UINT32_MAX && idx >= CalculateNumChildren())
205         return UINT32_MAX;
206     return idx;
207 }
208
209 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd ()
210 {}
211
212 SyntheticChildrenFrontEnd*
213 lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
214 {
215     if (!valobj_sp)
216         return NULL;
217     return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp));
218 }
219
220 /*
221  (lldb) fr var ibeg --raw --ptr-depth 1
222  (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 = {
223  __i_ = {
224  __ptr_ = 0x0000000100103870 {
225  std::__1::__tree_node_base<void *> = {
226  std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
227  __left_ = 0x0000000000000000
228  }
229  __right_ = 0x0000000000000000
230  __parent_ = 0x00000001001038b0
231  __is_black_ = true
232  }
233  __value_ = {
234  first = 0
235  second = { std::string }
236  */
237
238 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
239 SyntheticChildrenFrontEnd(*valobj_sp.get()),
240 m_pair_ptr()
241 {
242     if (valobj_sp)
243         Update();
244 }
245
246 bool
247 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update()
248 {
249     ValueObjectSP valobj_sp = m_backend.GetSP();
250     if (!valobj_sp)
251         return false;
252     
253     TargetSP target_sp(valobj_sp->GetTargetSP());
254     
255     if (!target_sp)
256         return false;
257
258     if (!valobj_sp)
259         return false;
260
261     // this must be a ValueObject* because it is a child of the ValueObject we are producing children for
262     // it if were a ValueObjectSP, we would end up with a loop (iterator -> synthetic -> child -> parent == iterator)
263     // and that would in turn leak memory by never allowing the ValueObjects to die and free their memory
264     m_pair_ptr = valobj_sp->GetValueForExpressionPath(".__i_.__ptr_->__value_",
265                                                      NULL,
266                                                      NULL,
267                                                      NULL,
268                                                      ValueObject::GetValueForExpressionPathOptions().DontCheckDotVsArrowSyntax().DontAllowSyntheticChildren(),
269                                                      NULL).get();
270     
271     return false;
272 }
273
274 size_t
275 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::CalculateNumChildren ()
276 {
277     return 2;
278 }
279
280 lldb::ValueObjectSP
281 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
282 {
283     if (!m_pair_ptr)
284         return lldb::ValueObjectSP();
285     return m_pair_ptr->GetChildAtIndex(idx, true);
286 }
287
288 bool
289 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::MightHaveChildren ()
290 {
291     return true;
292 }
293
294 size_t
295 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
296 {
297     if (name == ConstString("first"))
298         return 0;
299     if (name == ConstString("second"))
300         return 1;
301     return UINT32_MAX;
302 }
303
304 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::~LibCxxMapIteratorSyntheticFrontEnd ()
305 {
306     // this will be deleted when its parent dies (since it's a child object)
307     //delete m_pair_ptr;
308 }
309
310 SyntheticChildrenFrontEnd*
311 lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
312 {
313     if (!valobj_sp)
314         return NULL;
315     return (new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp));
316 }
317
318 /*
319  (lldb) fr var ibeg --raw --ptr-depth 1 -T
320  (std::__1::__wrap_iter<int *>) ibeg = {
321  (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
322  (int) *__i = 1
323  }
324  }
325 */
326
327 SyntheticChildrenFrontEnd*
328 lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
329 {
330     static ConstString g_item_name;
331     if (!g_item_name)
332         g_item_name.SetCString("__i");
333     if (!valobj_sp)
334         return NULL;
335     return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name));
336 }
337
338 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
339 SyntheticChildrenFrontEnd(*valobj_sp.get()),
340 m_cntrl(NULL),
341 m_count_sp(),
342 m_weak_count_sp(),
343 m_ptr_size(0),
344 m_byte_order(lldb::eByteOrderInvalid)
345 {
346     if (valobj_sp)
347         Update();
348 }
349
350 size_t
351 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::CalculateNumChildren ()
352 {
353     return (m_cntrl ? 1 : 0);
354 }
355
356 lldb::ValueObjectSP
357 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (size_t idx)
358 {
359     if (!m_cntrl)
360         return lldb::ValueObjectSP();
361
362     ValueObjectSP valobj_sp = m_backend.GetSP();
363     if (!valobj_sp)
364         return lldb::ValueObjectSP();
365
366     if (idx == 0)
367         return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
368
369     if (idx > 2)
370         return lldb::ValueObjectSP();
371
372     if (idx == 1)
373     {
374         if (!m_count_sp)
375         {
376             ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_owners_"),true));
377             if (!shared_owners_sp)
378                 return lldb::ValueObjectSP();
379             uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
380             DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
381             m_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetClangType());
382         }
383         return m_count_sp;
384     }
385     else /* if (idx == 2) */
386     {
387         if (!m_weak_count_sp)
388         {
389             ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_weak_owners_"),true));
390             if (!shared_weak_owners_sp)
391                 return lldb::ValueObjectSP();
392             uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
393             DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
394             m_weak_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetClangType());
395         }
396         return m_weak_count_sp;
397     }
398 }
399
400 bool
401 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update()
402 {
403     m_count_sp.reset();
404     m_weak_count_sp.reset();
405     m_cntrl = NULL;
406     
407     ValueObjectSP valobj_sp = m_backend.GetSP();
408     if (!valobj_sp)
409         return false;
410     
411     TargetSP target_sp(valobj_sp->GetTargetSP());
412     if (!target_sp)
413         return false;
414     
415     m_byte_order = target_sp->GetArchitecture().GetByteOrder();
416     m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize();
417     
418     lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"),true));
419     
420     m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular dependency
421     return false;
422 }
423
424 bool
425 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::MightHaveChildren ()
426 {
427     return true;
428 }
429
430 size_t
431 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
432 {
433     if (name == ConstString("__ptr_"))
434         return 0;
435     if (name == ConstString("count"))
436         return 1;
437     if (name == ConstString("weak_count"))
438         return 2;
439     return UINT32_MAX;
440 }
441
442 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::~LibcxxSharedPtrSyntheticFrontEnd ()
443 {}
444
445 SyntheticChildrenFrontEnd*
446 lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
447 {
448     if (!valobj_sp)
449         return NULL;
450     return (new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp));
451 }
452
453 bool
454 lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
455 {
456     if (valobj.IsPointerType())
457     {
458         uint64_t value = valobj.GetValueAsUnsigned(0);
459         if (!value)
460             return false;
461         stream.Printf("0x%016" PRIx64 " ", value);
462     }
463     return Debugger::FormatPrompt("size=${svar%#}", NULL, NULL, NULL, stream, &valobj);
464 }