blob: 7303ae50f5b1520bfbfbeada11b461afb4d0ecda [file] [log] [blame]
Greg Claytonbb1beaa2013-03-26 18:42:13 +00001//===-- LibCxx.cpp ----------------------------------------------*- C++ -*-===//
Enrico Granataea2bc0f2013-02-21 19:57:10 +00002//
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 "LibCxx.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000011
Eugene Zelenkobbd16812016-02-29 19:41:30 +000012// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Enrico Granataea2bc0f2013-02-21 19:57:10 +000016#include "lldb/Core/DataBufferHeap.h"
Enrico Granata14b74fd2013-05-06 18:55:52 +000017#include "lldb/Core/Debugger.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000018#include "lldb/Core/Error.h"
Greg Clayton554f68d2015-02-04 22:00:53 +000019#include "lldb/Core/FormatEntity.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000020#include "lldb/Core/Stream.h"
21#include "lldb/Core/ValueObject.h"
22#include "lldb/Core/ValueObjectConstResult.h"
Enrico Granata419d7912015-09-04 00:33:51 +000023#include "lldb/DataFormatters/FormattersHelpers.h"
24#include "lldb/DataFormatters/StringPrinter.h"
25#include "lldb/DataFormatters/TypeSummary.h"
26#include "lldb/DataFormatters/VectorIterator.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000027#include "lldb/Host/Endian.h"
28#include "lldb/Symbol/ClangASTContext.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000029#include "lldb/Target/Target.h"
Enrico Granataae1ba732016-09-28 22:53:16 +000030#include "lldb/Utility/ProcessStructReader.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000031
32using namespace lldb;
33using namespace lldb_private;
34using namespace lldb_private::formatters;
35
Kate Stoneb9c1b512016-09-06 20:57:50 +000036bool lldb_private::formatters::LibcxxSmartPointerSummaryProvider(
37 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
38 ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
39 if (!valobj_sp)
40 return false;
41 ValueObjectSP ptr_sp(
42 valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
43 ValueObjectSP count_sp(valobj_sp->GetChildAtNamePath(
44 {ConstString("__cntrl_"), ConstString("__shared_owners_")}));
45 ValueObjectSP weakcount_sp(valobj_sp->GetChildAtNamePath(
46 {ConstString("__cntrl_"), ConstString("__shared_weak_owners_")}));
Enrico Granata0dba9b32014-01-08 01:36:59 +000047
Kate Stoneb9c1b512016-09-06 20:57:50 +000048 if (!ptr_sp)
49 return false;
50
51 if (ptr_sp->GetValueAsUnsigned(0) == 0) {
52 stream.Printf("nullptr");
Enrico Granata0dba9b32014-01-08 01:36:59 +000053 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +000054 } else {
55 bool print_pointee = false;
56 Error error;
57 ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
58 if (pointee_sp && error.Success()) {
59 if (pointee_sp->DumpPrintableRepresentation(
60 stream, ValueObject::eValueObjectRepresentationStyleSummary,
61 lldb::eFormatInvalid,
62 ValueObject::ePrintableRepresentationSpecialCasesDisable, false))
63 print_pointee = true;
Enrico Granata473316f2013-12-21 08:09:49 +000064 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000065 if (!print_pointee)
66 stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
67 }
68
69 if (count_sp)
70 stream.Printf(" strong=%" PRIu64, 1 + count_sp->GetValueAsUnsigned(0));
71
72 if (weakcount_sp)
73 stream.Printf(" weak=%" PRIu64, 1 + weakcount_sp->GetValueAsUnsigned(0));
74
75 return true;
Enrico Granataea2bc0f2013-02-21 19:57:10 +000076}
77
Kate Stoneb9c1b512016-09-06 20:57:50 +000078lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::
79 LibcxxVectorBoolSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
80 : SyntheticChildrenFrontEnd(*valobj_sp), m_bool_type(), m_exe_ctx_ref(),
81 m_count(0), m_base_data_address(0), m_children() {
82 if (valobj_sp) {
83 Update();
84 m_bool_type =
85 valobj_sp->GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeBool);
86 }
87}
88
89size_t lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::
90 CalculateNumChildren() {
91 return m_count;
Enrico Granataea2bc0f2013-02-21 19:57:10 +000092}
93
94lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +000095lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex(
96 size_t idx) {
97 auto iter = m_children.find(idx), end = m_children.end();
98 if (iter != end)
99 return iter->second;
100 if (idx >= m_count)
101 return ValueObjectSP();
102 if (m_base_data_address == 0 || m_count == 0)
103 return ValueObjectSP();
104 if (!m_bool_type)
105 return ValueObjectSP();
106 size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
107 size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
108 lldb::addr_t byte_location = m_base_data_address + byte_idx;
109 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
110 if (!process_sp)
111 return ValueObjectSP();
112 uint8_t byte = 0;
113 uint8_t mask = 0;
114 Error err;
115 size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
116 if (err.Fail() || bytes_read == 0)
117 return ValueObjectSP();
118 switch (bit_index) {
119 case 0:
120 mask = 1;
121 break;
122 case 1:
123 mask = 2;
124 break;
125 case 2:
126 mask = 4;
127 break;
128 case 3:
129 mask = 8;
130 break;
131 case 4:
132 mask = 16;
133 break;
134 case 5:
135 mask = 32;
136 break;
137 case 6:
138 mask = 64;
139 break;
140 case 7:
141 mask = 128;
142 break;
143 default:
144 return ValueObjectSP();
145 }
146 bool bit_set = ((byte & mask) != 0);
147 DataBufferSP buffer_sp(
148 new DataBufferHeap(m_bool_type.GetByteSize(nullptr), 0));
149 if (bit_set && buffer_sp && buffer_sp->GetBytes())
150 *(buffer_sp->GetBytes()) =
151 1; // regardless of endianness, anything non-zero is true
152 StreamString name;
153 name.Printf("[%" PRIu64 "]", (uint64_t)idx);
154 ValueObjectSP retval_sp(CreateValueObjectFromData(
155 name.GetData(), DataExtractor(buffer_sp, process_sp->GetByteOrder(),
156 process_sp->GetAddressByteSize()),
157 m_exe_ctx_ref, m_bool_type));
158 if (retval_sp)
159 m_children[idx] = retval_sp;
160 return retval_sp;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000161}
162
163/*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
164 __begin_ = 0x00000001001000e0
165 __size_ = 56
166 __cap_alloc_ = {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000167 std::__1::__libcpp_compressed_pair_imp<unsigned long,
168 std::__1::allocator<unsigned long> > = {
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000169 __first_ = 1
170 }
171 }
172 }*/
173
Kate Stoneb9c1b512016-09-06 20:57:50 +0000174bool lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update() {
175 m_children.clear();
176 ValueObjectSP valobj_sp = m_backend.GetSP();
177 if (!valobj_sp)
Enrico Granata92373532013-03-19 22:58:48 +0000178 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000179 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
180 ValueObjectSP size_sp(
181 valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
182 if (!size_sp)
183 return false;
184 m_count = size_sp->GetValueAsUnsigned(0);
185 if (!m_count)
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000186 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000187 ValueObjectSP begin_sp(
188 valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
189 if (!begin_sp) {
190 m_count = 0;
191 return false;
192 }
193 m_base_data_address = begin_sp->GetValueAsUnsigned(0);
194 if (!m_base_data_address) {
195 m_count = 0;
196 return false;
197 }
198 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000199}
200
Kate Stoneb9c1b512016-09-06 20:57:50 +0000201bool lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::
202 MightHaveChildren() {
203 return true;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000204}
205
Kate Stoneb9c1b512016-09-06 20:57:50 +0000206size_t lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::
207 GetIndexOfChildWithName(const ConstString &name) {
208 if (!m_count || !m_base_data_address)
209 return UINT32_MAX;
210 const char *item_name = name.GetCString();
211 uint32_t idx = ExtractIndexFromString(item_name);
212 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
213 return UINT32_MAX;
214 return idx;
215}
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000216
Kate Stoneb9c1b512016-09-06 20:57:50 +0000217lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::
218 ~LibcxxVectorBoolSyntheticFrontEnd() = default;
219
220SyntheticChildrenFrontEnd *
221lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator(
222 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
223 return (valobj_sp ? new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp)
224 : nullptr);
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000225}
226
227/*
228 (lldb) fr var ibeg --raw --ptr-depth 1
Kate Stoneb9c1b512016-09-06 20:57:50 +0000229 (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int,
230 std::__1::basic_string<char, std::__1::char_traits<char>,
231 std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int,
232 std::__1::basic_string<char, std::__1::char_traits<char>,
233 std::__1::allocator<char> > >, void *> *, long> >) ibeg = {
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000234 __i_ = {
235 __ptr_ = 0x0000000100103870 {
236 std::__1::__tree_node_base<void *> = {
237 std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
238 __left_ = 0x0000000000000000
239 }
240 __right_ = 0x0000000000000000
241 __parent_ = 0x00000001001038b0
242 __is_black_ = true
243 }
244 __value_ = {
245 first = 0
246 second = { std::string }
247 */
248
Kate Stoneb9c1b512016-09-06 20:57:50 +0000249lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
250 LibCxxMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Enrico Granataae1ba732016-09-28 22:53:16 +0000251 : SyntheticChildrenFrontEnd(*valobj_sp), m_pair_ptr(), m_pair_sp() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000252 if (valobj_sp)
253 Update();
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000254}
255
Kate Stoneb9c1b512016-09-06 20:57:50 +0000256bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
Enrico Granataae1ba732016-09-28 22:53:16 +0000257 m_pair_sp.reset();
258 m_pair_ptr = nullptr;
259
Kate Stoneb9c1b512016-09-06 20:57:50 +0000260 ValueObjectSP valobj_sp = m_backend.GetSP();
261 if (!valobj_sp)
Enrico Granata92373532013-03-19 22:58:48 +0000262 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000263
264 TargetSP target_sp(valobj_sp->GetTargetSP());
265
266 if (!target_sp)
267 return false;
268
269 if (!valobj_sp)
270 return false;
Enrico Granataae1ba732016-09-28 22:53:16 +0000271
272 static ConstString g___i_("__i_");
273
Kate Stoneb9c1b512016-09-06 20:57:50 +0000274 // this must be a ValueObject* because it is a child of the ValueObject we are
275 // producing children for
276 // it if were a ValueObjectSP, we would end up with a loop (iterator ->
277 // synthetic -> child -> parent == iterator)
278 // and that would in turn leak memory by never allowing the ValueObjects to
279 // die and free their memory
280 m_pair_ptr = valobj_sp
281 ->GetValueForExpressionPath(
282 ".__i_.__ptr_->__value_", nullptr, nullptr, nullptr,
283 ValueObject::GetValueForExpressionPathOptions()
284 .DontCheckDotVsArrowSyntax()
285 .SetSyntheticChildrenTraversal(
286 ValueObject::GetValueForExpressionPathOptions::
287 SyntheticChildrenTraversal::None),
288 nullptr)
289 .get();
Enrico Granataae1ba732016-09-28 22:53:16 +0000290
291 if (!m_pair_ptr) {
292 m_pair_ptr = valobj_sp->GetValueForExpressionPath(".__i_.__ptr_", nullptr, nullptr, nullptr,
293 ValueObject::GetValueForExpressionPathOptions()
294 .DontCheckDotVsArrowSyntax()
295 .SetSyntheticChildrenTraversal(
296 ValueObject::GetValueForExpressionPathOptions::
297 SyntheticChildrenTraversal::None),
298 nullptr)
299 .get();
300 if (m_pair_ptr) {
301 auto __i_(valobj_sp->GetChildMemberWithName(g___i_, true));
302 lldb::TemplateArgumentKind kind;
303 if (!__i_) {
304 m_pair_ptr = nullptr;
305 return false;
306 }
307 CompilerType pair_type(__i_->GetCompilerType().GetTemplateArgument(0, kind));
308 std::string name; uint64_t bit_offset_ptr; uint32_t bitfield_bit_size_ptr; bool is_bitfield_ptr;
309 pair_type = pair_type.GetFieldAtIndex(0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
310 if (!pair_type) {
311 m_pair_ptr = nullptr;
312 return false;
313 }
314
315 auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS));
316 m_pair_ptr = nullptr;
317 if (addr && addr!=LLDB_INVALID_ADDRESS) {
318 ClangASTContext *ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(pair_type.GetTypeSystem());
319 if (!ast_ctx)
320 return false;
321 CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(ConstString(), {
322 {"ptr0",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
323 {"ptr1",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
324 {"ptr2",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
325 {"cw",ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
326 {"payload",pair_type}
327 });
328 DataBufferSP buffer_sp(new DataBufferHeap(tree_node_type.GetByteSize(nullptr),0));
329 ProcessSP process_sp(target_sp->GetProcessSP());
330 Error error;
331 process_sp->ReadMemory(addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), error);
332 if (error.Fail())
333 return false;
334 DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
335 auto pair_sp = CreateValueObjectFromData("pair", extractor, valobj_sp->GetExecutionContextRef(), tree_node_type);
336 if (pair_sp)
337 m_pair_sp = pair_sp->GetChildAtIndex(4,true);
338 }
339 }
340 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000341
342 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000343}
344
Kate Stoneb9c1b512016-09-06 20:57:50 +0000345size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
346 CalculateNumChildren() {
347 return 2;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000348}
349
350lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000351lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex(
352 size_t idx) {
Enrico Granataae1ba732016-09-28 22:53:16 +0000353 if (m_pair_ptr)
354 return m_pair_ptr->GetChildAtIndex(idx, true);
355 if (m_pair_sp)
356 return m_pair_sp->GetChildAtIndex(idx, true);
357 return lldb::ValueObjectSP();
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000358}
359
Kate Stoneb9c1b512016-09-06 20:57:50 +0000360bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
361 MightHaveChildren() {
362 return true;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000363}
364
Kate Stoneb9c1b512016-09-06 20:57:50 +0000365size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
366 GetIndexOfChildWithName(const ConstString &name) {
367 if (name == ConstString("first"))
368 return 0;
369 if (name == ConstString("second"))
370 return 1;
371 return UINT32_MAX;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000372}
373
Kate Stoneb9c1b512016-09-06 20:57:50 +0000374lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
375 ~LibCxxMapIteratorSyntheticFrontEnd() {
376 // this will be deleted when its parent dies (since it's a child object)
377 // delete m_pair_ptr;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000378}
379
Kate Stoneb9c1b512016-09-06 20:57:50 +0000380SyntheticChildrenFrontEnd *
381lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator(
382 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
383 return (valobj_sp ? new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)
384 : nullptr);
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000385}
386
387/*
388 (lldb) fr var ibeg --raw --ptr-depth 1 -T
389 (std::__1::__wrap_iter<int *>) ibeg = {
390 (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
391 (int) *__i = 1
392 }
393 }
394*/
395
Kate Stoneb9c1b512016-09-06 20:57:50 +0000396SyntheticChildrenFrontEnd *
397lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator(
398 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
399 static ConstString g_item_name;
400 if (!g_item_name)
401 g_item_name.SetCString("__i");
402 return (valobj_sp
403 ? new VectorIteratorSyntheticFrontEnd(valobj_sp, g_item_name)
404 : nullptr);
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000405}
Enrico Granata92373532013-03-19 22:58:48 +0000406
Kate Stoneb9c1b512016-09-06 20:57:50 +0000407lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
408 LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
409 : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr), m_count_sp(),
410 m_weak_count_sp(), m_ptr_size(0), m_byte_order(lldb::eByteOrderInvalid) {
411 if (valobj_sp)
412 Update();
Enrico Granata92373532013-03-19 22:58:48 +0000413}
414
Kate Stoneb9c1b512016-09-06 20:57:50 +0000415size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
416 CalculateNumChildren() {
417 return (m_cntrl ? 1 : 0);
Enrico Granata92373532013-03-19 22:58:48 +0000418}
419
420lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000421lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
422 size_t idx) {
423 if (!m_cntrl)
424 return lldb::ValueObjectSP();
425
426 ValueObjectSP valobj_sp = m_backend.GetSP();
427 if (!valobj_sp)
428 return lldb::ValueObjectSP();
429
430 if (idx == 0)
431 return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
432
433 if (idx > 2)
434 return lldb::ValueObjectSP();
435
436 if (idx == 1) {
437 if (!m_count_sp) {
438 ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(
439 ConstString("__shared_owners_"), true));
440 if (!shared_owners_sp)
Enrico Granata92373532013-03-19 22:58:48 +0000441 return lldb::ValueObjectSP();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000442 uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
443 DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
444 m_count_sp = CreateValueObjectFromData(
445 "count", data, valobj_sp->GetExecutionContextRef(),
446 shared_owners_sp->GetCompilerType());
Enrico Granata92373532013-03-19 22:58:48 +0000447 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000448 return m_count_sp;
449 } else /* if (idx == 2) */
450 {
451 if (!m_weak_count_sp) {
452 ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(
453 ConstString("__shared_weak_owners_"), true));
454 if (!shared_weak_owners_sp)
455 return lldb::ValueObjectSP();
456 uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
457 DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
458 m_weak_count_sp = CreateValueObjectFromData(
459 "count", data, valobj_sp->GetExecutionContextRef(),
460 shared_weak_owners_sp->GetCompilerType());
Enrico Granata92373532013-03-19 22:58:48 +0000461 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000462 return m_weak_count_sp;
463 }
Enrico Granata92373532013-03-19 22:58:48 +0000464}
465
Kate Stoneb9c1b512016-09-06 20:57:50 +0000466bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
467 m_count_sp.reset();
468 m_weak_count_sp.reset();
469 m_cntrl = nullptr;
470
471 ValueObjectSP valobj_sp = m_backend.GetSP();
472 if (!valobj_sp)
Enrico Granata92373532013-03-19 22:58:48 +0000473 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000474
475 TargetSP target_sp(valobj_sp->GetTargetSP());
476 if (!target_sp)
477 return false;
478
479 m_byte_order = target_sp->GetArchitecture().GetByteOrder();
480 m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize();
481
482 lldb::ValueObjectSP cntrl_sp(
483 valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"), true));
484
485 m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular
486 // dependency
487 return false;
Enrico Granata92373532013-03-19 22:58:48 +0000488}
489
Kate Stoneb9c1b512016-09-06 20:57:50 +0000490bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
491 MightHaveChildren() {
492 return true;
Enrico Granata92373532013-03-19 22:58:48 +0000493}
494
Kate Stoneb9c1b512016-09-06 20:57:50 +0000495size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
496 GetIndexOfChildWithName(const ConstString &name) {
497 if (name == ConstString("__ptr_"))
498 return 0;
499 if (name == ConstString("count"))
500 return 1;
501 if (name == ConstString("weak_count"))
502 return 2;
503 return UINT32_MAX;
Enrico Granata92373532013-03-19 22:58:48 +0000504}
505
Kate Stoneb9c1b512016-09-06 20:57:50 +0000506lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
507 ~LibcxxSharedPtrSyntheticFrontEnd() = default;
Enrico Granata92373532013-03-19 22:58:48 +0000508
Kate Stoneb9c1b512016-09-06 20:57:50 +0000509SyntheticChildrenFrontEnd *
510lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator(
511 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
512 return (valobj_sp ? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)
513 : nullptr);
Enrico Granata92373532013-03-19 22:58:48 +0000514}
515
Kate Stoneb9c1b512016-09-06 20:57:50 +0000516bool lldb_private::formatters::LibcxxContainerSummaryProvider(
517 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
518 if (valobj.IsPointerType()) {
519 uint64_t value = valobj.GetValueAsUnsigned(0);
520 if (!value)
521 return false;
522 stream.Printf("0x%016" PRIx64 " ", value);
523 }
524 return FormatEntity::FormatStringRef("size=${svar%#}", stream, nullptr,
525 nullptr, nullptr, &valobj, false, false);
Enrico Granata14b74fd2013-05-06 18:55:52 +0000526}
Enrico Granatad87cc312015-09-03 01:29:42 +0000527
528// the field layout in a libc++ string (cap, side, data or data, size, cap)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000529enum LibcxxStringLayoutMode {
530 eLibcxxStringLayoutModeCSD = 0,
531 eLibcxxStringLayoutModeDSC = 1,
532 eLibcxxStringLayoutModeInvalid = 0xffff
Enrico Granatad87cc312015-09-03 01:29:42 +0000533};
534
535// this function abstracts away the layout and mode details of a libc++ string
536// and returns the address of the data and the size ready for callers to consume
Kate Stoneb9c1b512016-09-06 20:57:50 +0000537static bool ExtractLibcxxStringInfo(ValueObject &valobj,
538 ValueObjectSP &location_sp,
539 uint64_t &size) {
540 ValueObjectSP D(valobj.GetChildAtIndexPath({0, 0, 0, 0}));
541 if (!D)
542 return false;
Enrico Granatad87cc312015-09-03 01:29:42 +0000543
Kate Stoneb9c1b512016-09-06 20:57:50 +0000544 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0, 0}));
545
546 // this child should exist
547 if (!layout_decider)
548 return false;
549
550 ConstString g_data_name("__data_");
551 ConstString g_size_name("__size_");
552 bool short_mode = false; // this means the string is in short-mode and the
553 // data is stored inline
554 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name)
555 ? eLibcxxStringLayoutModeDSC
556 : eLibcxxStringLayoutModeCSD;
557 uint64_t size_mode_value = 0;
558
559 if (layout == eLibcxxStringLayoutModeDSC) {
560 ValueObjectSP size_mode(D->GetChildAtIndexPath({1, 1, 0}));
561 if (!size_mode)
562 return false;
563
564 if (size_mode->GetName() != g_size_name) {
565 // we are hitting the padding structure, move along
566 size_mode = D->GetChildAtIndexPath({1, 1, 1});
567 if (!size_mode)
Enrico Granatad87cc312015-09-03 01:29:42 +0000568 return false;
Enrico Granatad87cc312015-09-03 01:29:42 +0000569 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000570
571 size_mode_value = (size_mode->GetValueAsUnsigned(0));
572 short_mode = ((size_mode_value & 0x80) == 0);
573 } else {
574 ValueObjectSP size_mode(D->GetChildAtIndexPath({1, 0, 0}));
575 if (!size_mode)
576 return false;
577
578 size_mode_value = (size_mode->GetValueAsUnsigned(0));
579 short_mode = ((size_mode_value & 1) == 0);
580 }
581
582 if (short_mode) {
583 ValueObjectSP s(D->GetChildAtIndex(1, true));
584 if (!s)
585 return false;
586 location_sp = s->GetChildAtIndex(
587 (layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
588 size = (layout == eLibcxxStringLayoutModeDSC)
589 ? size_mode_value
590 : ((size_mode_value >> 1) % 256);
591 return (location_sp.get() != nullptr);
592 } else {
593 ValueObjectSP l(D->GetChildAtIndex(0, true));
594 if (!l)
595 return false;
596 // we can use the layout_decider object as the data pointer
597 location_sp = (layout == eLibcxxStringLayoutModeDSC)
598 ? layout_decider
599 : l->GetChildAtIndex(2, true);
600 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
601 if (!size_vo || !location_sp)
602 return false;
603 size = size_vo->GetValueAsUnsigned(0);
Enrico Granatad87cc312015-09-03 01:29:42 +0000604 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000605 }
Enrico Granatad87cc312015-09-03 01:29:42 +0000606}
607
Kate Stoneb9c1b512016-09-06 20:57:50 +0000608bool lldb_private::formatters::LibcxxWStringSummaryProvider(
609 ValueObject &valobj, Stream &stream,
610 const TypeSummaryOptions &summary_options) {
611 uint64_t size = 0;
612 ValueObjectSP location_sp;
613 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
614 return false;
615 if (size == 0) {
616 stream.Printf("L\"\"");
Enrico Granatad87cc312015-09-03 01:29:42 +0000617 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000618 }
619 if (!location_sp)
620 return false;
621
622 DataExtractor extractor;
623
624 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
625
626 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
627 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
628 if (size > max_size) {
629 size = max_size;
630 options.SetIsTruncated(true);
631 }
632 }
633 location_sp->GetPointeeData(extractor, 0, size);
634
635 // std::wstring::size() is measured in 'characters', not bytes
636 auto wchar_t_size = valobj.GetTargetSP()
637 ->GetScratchClangASTContext()
638 ->GetBasicType(lldb::eBasicTypeWChar)
639 .GetByteSize(nullptr);
640
641 options.SetData(extractor);
642 options.SetStream(&stream);
643 options.SetPrefixToken("L");
644 options.SetQuote('"');
645 options.SetSourceSize(size);
646 options.SetBinaryZeroIsTerminator(false);
647
648 switch (wchar_t_size) {
649 case 1:
650 StringPrinter::ReadBufferAndDumpToStream<
651 lldb_private::formatters::StringPrinter::StringElementType::UTF8>(
652 options);
653 break;
654
655 case 2:
656 lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<
657 lldb_private::formatters::StringPrinter::StringElementType::UTF16>(
658 options);
659 break;
660
661 case 4:
662 lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<
663 lldb_private::formatters::StringPrinter::StringElementType::UTF32>(
664 options);
665 break;
666
667 default:
668 stream.Printf("size for wchar_t is not valid");
669 return true;
670 }
671
672 return true;
Enrico Granatad87cc312015-09-03 01:29:42 +0000673}
Enrico Granata1b54bae2016-08-31 21:46:37 +0000674
Kate Stoneb9c1b512016-09-06 20:57:50 +0000675bool lldb_private::formatters::LibcxxStringSummaryProvider(
676 ValueObject &valobj, Stream &stream,
677 const TypeSummaryOptions &summary_options) {
678 uint64_t size = 0;
679 ValueObjectSP location_sp;
680
681 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
682 return false;
683
684 if (size == 0) {
685 stream.Printf("\"\"");
686 return true;
687 }
688
689 if (!location_sp)
690 return false;
691
692 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
693
694 DataExtractor extractor;
695 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
696 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
697 if (size > max_size) {
698 size = max_size;
699 options.SetIsTruncated(true);
700 }
701 }
702 location_sp->GetPointeeData(extractor, 0, size);
703
704 options.SetData(extractor);
705 options.SetStream(&stream);
706 options.SetPrefixToken(nullptr);
707 options.SetQuote('"');
708 options.SetSourceSize(size);
709 options.SetBinaryZeroIsTerminator(false);
710 StringPrinter::ReadBufferAndDumpToStream<
711 StringPrinter::StringElementType::ASCII>(options);
712
713 return true;
714}
715
716class LibcxxFunctionFrontEnd : public SyntheticValueProviderFrontEnd {
Enrico Granata1b54bae2016-08-31 21:46:37 +0000717public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000718 LibcxxFunctionFrontEnd(ValueObject &backend)
719 : SyntheticValueProviderFrontEnd(backend) {}
720
721 lldb::ValueObjectSP GetSyntheticValue() override {
722 static ConstString g___f_("__f_");
723 return m_backend.GetChildMemberWithName(g___f_, true);
724 }
Enrico Granata1b54bae2016-08-31 21:46:37 +0000725};
726
Kate Stoneb9c1b512016-09-06 20:57:50 +0000727SyntheticChildrenFrontEnd *
728lldb_private::formatters::LibcxxFunctionFrontEndCreator(
729 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
730 if (valobj_sp)
731 return new LibcxxFunctionFrontEnd(*valobj_sp);
732 return nullptr;
Enrico Granata1b54bae2016-08-31 21:46:37 +0000733}