blob: 82441a69b1d4f010f01ac25021523410d6326587 [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,
Enrico Granata65d86e42016-11-07 23:32:20 +000062 ValueObject::PrintableRepresentationSpecialCases::eDisable,
63 false))
Kate Stoneb9c1b512016-09-06 20:57:50 +000064 print_pointee = true;
Enrico Granata473316f2013-12-21 08:09:49 +000065 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000066 if (!print_pointee)
67 stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
68 }
69
70 if (count_sp)
71 stream.Printf(" strong=%" PRIu64, 1 + count_sp->GetValueAsUnsigned(0));
72
73 if (weakcount_sp)
74 stream.Printf(" weak=%" PRIu64, 1 + weakcount_sp->GetValueAsUnsigned(0));
75
76 return true;
Enrico Granataea2bc0f2013-02-21 19:57:10 +000077}
78
Kate Stoneb9c1b512016-09-06 20:57:50 +000079lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::
80 LibcxxVectorBoolSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
81 : SyntheticChildrenFrontEnd(*valobj_sp), m_bool_type(), m_exe_ctx_ref(),
82 m_count(0), m_base_data_address(0), m_children() {
83 if (valobj_sp) {
84 Update();
85 m_bool_type =
86 valobj_sp->GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeBool);
87 }
88}
89
90size_t lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::
91 CalculateNumChildren() {
92 return m_count;
Enrico Granataea2bc0f2013-02-21 19:57:10 +000093}
94
95lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +000096lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex(
97 size_t idx) {
98 auto iter = m_children.find(idx), 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 case 0:
121 mask = 1;
122 break;
123 case 1:
124 mask = 2;
125 break;
126 case 2:
127 mask = 4;
128 break;
129 case 3:
130 mask = 8;
131 break;
132 case 4:
133 mask = 16;
134 break;
135 case 5:
136 mask = 32;
137 break;
138 case 6:
139 mask = 64;
140 break;
141 case 7:
142 mask = 128;
143 break;
144 default:
145 return ValueObjectSP();
146 }
147 bool bit_set = ((byte & mask) != 0);
148 DataBufferSP buffer_sp(
149 new DataBufferHeap(m_bool_type.GetByteSize(nullptr), 0));
150 if (bit_set && buffer_sp && buffer_sp->GetBytes())
151 *(buffer_sp->GetBytes()) =
152 1; // regardless of endianness, anything non-zero is true
153 StreamString name;
154 name.Printf("[%" PRIu64 "]", (uint64_t)idx);
155 ValueObjectSP retval_sp(CreateValueObjectFromData(
Zachary Turnerc1564272016-11-16 21:15:24 +0000156 name.GetString(), DataExtractor(buffer_sp, process_sp->GetByteOrder(),
157 process_sp->GetAddressByteSize()),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000158 m_exe_ctx_ref, m_bool_type));
159 if (retval_sp)
160 m_children[idx] = retval_sp;
161 return retval_sp;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000162}
163
164/*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
165 __begin_ = 0x00000001001000e0
166 __size_ = 56
167 __cap_alloc_ = {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000168 std::__1::__libcpp_compressed_pair_imp<unsigned long,
169 std::__1::allocator<unsigned long> > = {
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000170 __first_ = 1
171 }
172 }
173 }*/
174
Kate Stoneb9c1b512016-09-06 20:57:50 +0000175bool lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update() {
176 m_children.clear();
177 ValueObjectSP valobj_sp = m_backend.GetSP();
178 if (!valobj_sp)
Enrico Granata92373532013-03-19 22:58:48 +0000179 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000180 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
181 ValueObjectSP size_sp(
182 valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
183 if (!size_sp)
184 return false;
185 m_count = size_sp->GetValueAsUnsigned(0);
186 if (!m_count)
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000187 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000188 ValueObjectSP begin_sp(
189 valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
190 if (!begin_sp) {
191 m_count = 0;
192 return false;
193 }
194 m_base_data_address = begin_sp->GetValueAsUnsigned(0);
195 if (!m_base_data_address) {
196 m_count = 0;
197 return false;
198 }
199 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000200}
201
Kate Stoneb9c1b512016-09-06 20:57:50 +0000202bool lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::
203 MightHaveChildren() {
204 return true;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000205}
206
Kate Stoneb9c1b512016-09-06 20:57:50 +0000207size_t lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::
208 GetIndexOfChildWithName(const ConstString &name) {
209 if (!m_count || !m_base_data_address)
210 return UINT32_MAX;
211 const char *item_name = name.GetCString();
212 uint32_t idx = ExtractIndexFromString(item_name);
213 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
214 return UINT32_MAX;
215 return idx;
216}
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000217
Kate Stoneb9c1b512016-09-06 20:57:50 +0000218lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::
219 ~LibcxxVectorBoolSyntheticFrontEnd() = default;
220
221SyntheticChildrenFrontEnd *
222lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator(
223 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
224 return (valobj_sp ? new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp)
225 : nullptr);
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000226}
227
228/*
229 (lldb) fr var ibeg --raw --ptr-depth 1
Kate Stoneb9c1b512016-09-06 20:57:50 +0000230 (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int,
231 std::__1::basic_string<char, std::__1::char_traits<char>,
232 std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int,
233 std::__1::basic_string<char, std::__1::char_traits<char>,
234 std::__1::allocator<char> > >, void *> *, long> >) ibeg = {
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000235 __i_ = {
236 __ptr_ = 0x0000000100103870 {
237 std::__1::__tree_node_base<void *> = {
238 std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
239 __left_ = 0x0000000000000000
240 }
241 __right_ = 0x0000000000000000
242 __parent_ = 0x00000001001038b0
243 __is_black_ = true
244 }
245 __value_ = {
246 first = 0
247 second = { std::string }
248 */
249
Kate Stoneb9c1b512016-09-06 20:57:50 +0000250lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
251 LibCxxMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Enrico Granataae1ba732016-09-28 22:53:16 +0000252 : SyntheticChildrenFrontEnd(*valobj_sp), m_pair_ptr(), m_pair_sp() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000253 if (valobj_sp)
254 Update();
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000255}
256
Kate Stoneb9c1b512016-09-06 20:57:50 +0000257bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
Enrico Granataae1ba732016-09-28 22:53:16 +0000258 m_pair_sp.reset();
259 m_pair_ptr = nullptr;
260
Kate Stoneb9c1b512016-09-06 20:57:50 +0000261 ValueObjectSP valobj_sp = m_backend.GetSP();
262 if (!valobj_sp)
Enrico Granata92373532013-03-19 22:58:48 +0000263 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000264
265 TargetSP target_sp(valobj_sp->GetTargetSP());
266
267 if (!target_sp)
268 return false;
269
270 if (!valobj_sp)
271 return false;
Enrico Granataae1ba732016-09-28 22:53:16 +0000272
273 static ConstString g___i_("__i_");
274
Kate Stoneb9c1b512016-09-06 20:57:50 +0000275 // this must be a ValueObject* because it is a child of the ValueObject we are
276 // producing children for
277 // it if were a ValueObjectSP, we would end up with a loop (iterator ->
278 // synthetic -> child -> parent == iterator)
279 // and that would in turn leak memory by never allowing the ValueObjects to
280 // die and free their memory
281 m_pair_ptr = valobj_sp
282 ->GetValueForExpressionPath(
Zachary Turnerd2daca72016-11-18 17:55:04 +0000283 ".__i_.__ptr_->__value_", nullptr, nullptr,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000284 ValueObject::GetValueForExpressionPathOptions()
285 .DontCheckDotVsArrowSyntax()
286 .SetSyntheticChildrenTraversal(
287 ValueObject::GetValueForExpressionPathOptions::
288 SyntheticChildrenTraversal::None),
289 nullptr)
290 .get();
Zachary Turnerd2daca72016-11-18 17:55:04 +0000291
Enrico Granataae1ba732016-09-28 22:53:16 +0000292 if (!m_pair_ptr) {
Zachary Turnerd2daca72016-11-18 17:55:04 +0000293 m_pair_ptr = valobj_sp
294 ->GetValueForExpressionPath(
295 ".__i_.__ptr_", nullptr, nullptr,
296 ValueObject::GetValueForExpressionPathOptions()
297 .DontCheckDotVsArrowSyntax()
298 .SetSyntheticChildrenTraversal(
299 ValueObject::GetValueForExpressionPathOptions::
300 SyntheticChildrenTraversal::None),
301 nullptr)
302 .get();
Enrico Granataae1ba732016-09-28 22:53:16 +0000303 if (m_pair_ptr) {
304 auto __i_(valobj_sp->GetChildMemberWithName(g___i_, true));
305 lldb::TemplateArgumentKind kind;
306 if (!__i_) {
307 m_pair_ptr = nullptr;
308 return false;
309 }
310 CompilerType pair_type(__i_->GetCompilerType().GetTemplateArgument(0, kind));
311 std::string name; uint64_t bit_offset_ptr; uint32_t bitfield_bit_size_ptr; bool is_bitfield_ptr;
312 pair_type = pair_type.GetFieldAtIndex(0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
313 if (!pair_type) {
314 m_pair_ptr = nullptr;
315 return false;
316 }
317
318 auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS));
319 m_pair_ptr = nullptr;
320 if (addr && addr!=LLDB_INVALID_ADDRESS) {
321 ClangASTContext *ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(pair_type.GetTypeSystem());
322 if (!ast_ctx)
323 return false;
324 CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(ConstString(), {
325 {"ptr0",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
326 {"ptr1",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
327 {"ptr2",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
328 {"cw",ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
329 {"payload",pair_type}
330 });
331 DataBufferSP buffer_sp(new DataBufferHeap(tree_node_type.GetByteSize(nullptr),0));
332 ProcessSP process_sp(target_sp->GetProcessSP());
333 Error error;
334 process_sp->ReadMemory(addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), error);
335 if (error.Fail())
336 return false;
337 DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
338 auto pair_sp = CreateValueObjectFromData("pair", extractor, valobj_sp->GetExecutionContextRef(), tree_node_type);
339 if (pair_sp)
340 m_pair_sp = pair_sp->GetChildAtIndex(4,true);
341 }
342 }
343 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000344
345 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000346}
347
Kate Stoneb9c1b512016-09-06 20:57:50 +0000348size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
349 CalculateNumChildren() {
350 return 2;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000351}
352
353lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000354lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex(
355 size_t idx) {
Enrico Granataae1ba732016-09-28 22:53:16 +0000356 if (m_pair_ptr)
357 return m_pair_ptr->GetChildAtIndex(idx, true);
358 if (m_pair_sp)
359 return m_pair_sp->GetChildAtIndex(idx, true);
360 return lldb::ValueObjectSP();
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000361}
362
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
364 MightHaveChildren() {
365 return true;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000366}
367
Kate Stoneb9c1b512016-09-06 20:57:50 +0000368size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
369 GetIndexOfChildWithName(const ConstString &name) {
370 if (name == ConstString("first"))
371 return 0;
372 if (name == ConstString("second"))
373 return 1;
374 return UINT32_MAX;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000375}
376
Kate Stoneb9c1b512016-09-06 20:57:50 +0000377lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
378 ~LibCxxMapIteratorSyntheticFrontEnd() {
379 // this will be deleted when its parent dies (since it's a child object)
380 // delete m_pair_ptr;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000381}
382
Kate Stoneb9c1b512016-09-06 20:57:50 +0000383SyntheticChildrenFrontEnd *
384lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator(
385 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
386 return (valobj_sp ? new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)
387 : nullptr);
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000388}
389
390/*
391 (lldb) fr var ibeg --raw --ptr-depth 1 -T
392 (std::__1::__wrap_iter<int *>) ibeg = {
393 (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
394 (int) *__i = 1
395 }
396 }
397*/
398
Kate Stoneb9c1b512016-09-06 20:57:50 +0000399SyntheticChildrenFrontEnd *
400lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator(
401 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
402 static ConstString g_item_name;
403 if (!g_item_name)
404 g_item_name.SetCString("__i");
405 return (valobj_sp
406 ? new VectorIteratorSyntheticFrontEnd(valobj_sp, g_item_name)
407 : nullptr);
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000408}
Enrico Granata92373532013-03-19 22:58:48 +0000409
Kate Stoneb9c1b512016-09-06 20:57:50 +0000410lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
411 LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
412 : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr), m_count_sp(),
413 m_weak_count_sp(), m_ptr_size(0), m_byte_order(lldb::eByteOrderInvalid) {
414 if (valobj_sp)
415 Update();
Enrico Granata92373532013-03-19 22:58:48 +0000416}
417
Kate Stoneb9c1b512016-09-06 20:57:50 +0000418size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
419 CalculateNumChildren() {
420 return (m_cntrl ? 1 : 0);
Enrico Granata92373532013-03-19 22:58:48 +0000421}
422
423lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000424lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
425 size_t idx) {
426 if (!m_cntrl)
427 return lldb::ValueObjectSP();
428
429 ValueObjectSP valobj_sp = m_backend.GetSP();
430 if (!valobj_sp)
431 return lldb::ValueObjectSP();
432
433 if (idx == 0)
434 return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
435
436 if (idx > 2)
437 return lldb::ValueObjectSP();
438
439 if (idx == 1) {
440 if (!m_count_sp) {
441 ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(
442 ConstString("__shared_owners_"), true));
443 if (!shared_owners_sp)
Enrico Granata92373532013-03-19 22:58:48 +0000444 return lldb::ValueObjectSP();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000445 uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
446 DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
447 m_count_sp = CreateValueObjectFromData(
448 "count", data, valobj_sp->GetExecutionContextRef(),
449 shared_owners_sp->GetCompilerType());
Enrico Granata92373532013-03-19 22:58:48 +0000450 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000451 return m_count_sp;
452 } else /* if (idx == 2) */
453 {
454 if (!m_weak_count_sp) {
455 ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(
456 ConstString("__shared_weak_owners_"), true));
457 if (!shared_weak_owners_sp)
458 return lldb::ValueObjectSP();
459 uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
460 DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
461 m_weak_count_sp = CreateValueObjectFromData(
462 "count", data, valobj_sp->GetExecutionContextRef(),
463 shared_weak_owners_sp->GetCompilerType());
Enrico Granata92373532013-03-19 22:58:48 +0000464 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000465 return m_weak_count_sp;
466 }
Enrico Granata92373532013-03-19 22:58:48 +0000467}
468
Kate Stoneb9c1b512016-09-06 20:57:50 +0000469bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
470 m_count_sp.reset();
471 m_weak_count_sp.reset();
472 m_cntrl = nullptr;
473
474 ValueObjectSP valobj_sp = m_backend.GetSP();
475 if (!valobj_sp)
Enrico Granata92373532013-03-19 22:58:48 +0000476 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000477
478 TargetSP target_sp(valobj_sp->GetTargetSP());
479 if (!target_sp)
480 return false;
481
482 m_byte_order = target_sp->GetArchitecture().GetByteOrder();
483 m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize();
484
485 lldb::ValueObjectSP cntrl_sp(
486 valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"), true));
487
488 m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular
489 // dependency
490 return false;
Enrico Granata92373532013-03-19 22:58:48 +0000491}
492
Kate Stoneb9c1b512016-09-06 20:57:50 +0000493bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
494 MightHaveChildren() {
495 return true;
Enrico Granata92373532013-03-19 22:58:48 +0000496}
497
Kate Stoneb9c1b512016-09-06 20:57:50 +0000498size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
499 GetIndexOfChildWithName(const ConstString &name) {
500 if (name == ConstString("__ptr_"))
501 return 0;
502 if (name == ConstString("count"))
503 return 1;
504 if (name == ConstString("weak_count"))
505 return 2;
506 return UINT32_MAX;
Enrico Granata92373532013-03-19 22:58:48 +0000507}
508
Kate Stoneb9c1b512016-09-06 20:57:50 +0000509lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
510 ~LibcxxSharedPtrSyntheticFrontEnd() = default;
Enrico Granata92373532013-03-19 22:58:48 +0000511
Kate Stoneb9c1b512016-09-06 20:57:50 +0000512SyntheticChildrenFrontEnd *
513lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator(
514 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
515 return (valobj_sp ? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)
516 : nullptr);
Enrico Granata92373532013-03-19 22:58:48 +0000517}
518
Kate Stoneb9c1b512016-09-06 20:57:50 +0000519bool lldb_private::formatters::LibcxxContainerSummaryProvider(
520 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
521 if (valobj.IsPointerType()) {
522 uint64_t value = valobj.GetValueAsUnsigned(0);
523 if (!value)
524 return false;
525 stream.Printf("0x%016" PRIx64 " ", value);
526 }
527 return FormatEntity::FormatStringRef("size=${svar%#}", stream, nullptr,
528 nullptr, nullptr, &valobj, false, false);
Enrico Granata14b74fd2013-05-06 18:55:52 +0000529}
Enrico Granatad87cc312015-09-03 01:29:42 +0000530
531// the field layout in a libc++ string (cap, side, data or data, size, cap)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000532enum LibcxxStringLayoutMode {
533 eLibcxxStringLayoutModeCSD = 0,
534 eLibcxxStringLayoutModeDSC = 1,
535 eLibcxxStringLayoutModeInvalid = 0xffff
Enrico Granatad87cc312015-09-03 01:29:42 +0000536};
537
538// this function abstracts away the layout and mode details of a libc++ string
539// and returns the address of the data and the size ready for callers to consume
Kate Stoneb9c1b512016-09-06 20:57:50 +0000540static bool ExtractLibcxxStringInfo(ValueObject &valobj,
541 ValueObjectSP &location_sp,
542 uint64_t &size) {
543 ValueObjectSP D(valobj.GetChildAtIndexPath({0, 0, 0, 0}));
544 if (!D)
545 return false;
Enrico Granatad87cc312015-09-03 01:29:42 +0000546
Kate Stoneb9c1b512016-09-06 20:57:50 +0000547 ValueObjectSP layout_decider(D->GetChildAtIndexPath({0, 0}));
548
549 // this child should exist
550 if (!layout_decider)
551 return false;
552
553 ConstString g_data_name("__data_");
554 ConstString g_size_name("__size_");
555 bool short_mode = false; // this means the string is in short-mode and the
556 // data is stored inline
557 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name)
558 ? eLibcxxStringLayoutModeDSC
559 : eLibcxxStringLayoutModeCSD;
560 uint64_t size_mode_value = 0;
561
562 if (layout == eLibcxxStringLayoutModeDSC) {
563 ValueObjectSP size_mode(D->GetChildAtIndexPath({1, 1, 0}));
564 if (!size_mode)
565 return false;
566
567 if (size_mode->GetName() != g_size_name) {
568 // we are hitting the padding structure, move along
569 size_mode = D->GetChildAtIndexPath({1, 1, 1});
570 if (!size_mode)
Enrico Granatad87cc312015-09-03 01:29:42 +0000571 return false;
Enrico Granatad87cc312015-09-03 01:29:42 +0000572 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000573
574 size_mode_value = (size_mode->GetValueAsUnsigned(0));
575 short_mode = ((size_mode_value & 0x80) == 0);
576 } else {
577 ValueObjectSP size_mode(D->GetChildAtIndexPath({1, 0, 0}));
578 if (!size_mode)
579 return false;
580
581 size_mode_value = (size_mode->GetValueAsUnsigned(0));
582 short_mode = ((size_mode_value & 1) == 0);
583 }
584
585 if (short_mode) {
586 ValueObjectSP s(D->GetChildAtIndex(1, true));
587 if (!s)
588 return false;
589 location_sp = s->GetChildAtIndex(
590 (layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
591 size = (layout == eLibcxxStringLayoutModeDSC)
592 ? size_mode_value
593 : ((size_mode_value >> 1) % 256);
594 return (location_sp.get() != nullptr);
595 } else {
596 ValueObjectSP l(D->GetChildAtIndex(0, true));
597 if (!l)
598 return false;
599 // we can use the layout_decider object as the data pointer
600 location_sp = (layout == eLibcxxStringLayoutModeDSC)
601 ? layout_decider
602 : l->GetChildAtIndex(2, true);
603 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
604 if (!size_vo || !location_sp)
605 return false;
606 size = size_vo->GetValueAsUnsigned(0);
Enrico Granatad87cc312015-09-03 01:29:42 +0000607 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000608 }
Enrico Granatad87cc312015-09-03 01:29:42 +0000609}
610
Kate Stoneb9c1b512016-09-06 20:57:50 +0000611bool lldb_private::formatters::LibcxxWStringSummaryProvider(
612 ValueObject &valobj, Stream &stream,
613 const TypeSummaryOptions &summary_options) {
614 uint64_t size = 0;
615 ValueObjectSP location_sp;
616 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
617 return false;
618 if (size == 0) {
619 stream.Printf("L\"\"");
Enrico Granatad87cc312015-09-03 01:29:42 +0000620 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000621 }
622 if (!location_sp)
623 return false;
624
625 DataExtractor extractor;
626
627 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
628
629 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
630 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
631 if (size > max_size) {
632 size = max_size;
633 options.SetIsTruncated(true);
634 }
635 }
636 location_sp->GetPointeeData(extractor, 0, size);
637
638 // std::wstring::size() is measured in 'characters', not bytes
639 auto wchar_t_size = valobj.GetTargetSP()
640 ->GetScratchClangASTContext()
641 ->GetBasicType(lldb::eBasicTypeWChar)
642 .GetByteSize(nullptr);
643
644 options.SetData(extractor);
645 options.SetStream(&stream);
646 options.SetPrefixToken("L");
647 options.SetQuote('"');
648 options.SetSourceSize(size);
649 options.SetBinaryZeroIsTerminator(false);
650
651 switch (wchar_t_size) {
652 case 1:
653 StringPrinter::ReadBufferAndDumpToStream<
654 lldb_private::formatters::StringPrinter::StringElementType::UTF8>(
655 options);
656 break;
657
658 case 2:
659 lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<
660 lldb_private::formatters::StringPrinter::StringElementType::UTF16>(
661 options);
662 break;
663
664 case 4:
665 lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<
666 lldb_private::formatters::StringPrinter::StringElementType::UTF32>(
667 options);
668 break;
669
670 default:
671 stream.Printf("size for wchar_t is not valid");
672 return true;
673 }
674
675 return true;
Enrico Granatad87cc312015-09-03 01:29:42 +0000676}
Enrico Granata1b54bae2016-08-31 21:46:37 +0000677
Kate Stoneb9c1b512016-09-06 20:57:50 +0000678bool lldb_private::formatters::LibcxxStringSummaryProvider(
679 ValueObject &valobj, Stream &stream,
680 const TypeSummaryOptions &summary_options) {
681 uint64_t size = 0;
682 ValueObjectSP location_sp;
683
684 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
685 return false;
686
687 if (size == 0) {
688 stream.Printf("\"\"");
689 return true;
690 }
691
692 if (!location_sp)
693 return false;
694
695 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
696
697 DataExtractor extractor;
698 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
699 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
700 if (size > max_size) {
701 size = max_size;
702 options.SetIsTruncated(true);
703 }
704 }
705 location_sp->GetPointeeData(extractor, 0, size);
706
707 options.SetData(extractor);
708 options.SetStream(&stream);
709 options.SetPrefixToken(nullptr);
710 options.SetQuote('"');
711 options.SetSourceSize(size);
712 options.SetBinaryZeroIsTerminator(false);
713 StringPrinter::ReadBufferAndDumpToStream<
714 StringPrinter::StringElementType::ASCII>(options);
715
716 return true;
717}
718
719class LibcxxFunctionFrontEnd : public SyntheticValueProviderFrontEnd {
Enrico Granata1b54bae2016-08-31 21:46:37 +0000720public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000721 LibcxxFunctionFrontEnd(ValueObject &backend)
722 : SyntheticValueProviderFrontEnd(backend) {}
723
724 lldb::ValueObjectSP GetSyntheticValue() override {
725 static ConstString g___f_("__f_");
726 return m_backend.GetChildMemberWithName(g___f_, true);
727 }
Enrico Granata1b54bae2016-08-31 21:46:37 +0000728};
729
Kate Stoneb9c1b512016-09-06 20:57:50 +0000730SyntheticChildrenFrontEnd *
731lldb_private::formatters::LibcxxFunctionFrontEndCreator(
732 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
733 if (valobj_sp)
734 return new LibcxxFunctionFrontEnd(*valobj_sp);
735 return nullptr;
Enrico Granata1b54bae2016-08-31 21:46:37 +0000736}