blob: f6d1f18cb596baf840bb927e1ffd166e177e41d3 [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 Granata14b74fd2013-05-06 18:55:52 +000016#include "lldb/Core/Debugger.h"
Greg Clayton554f68d2015-02-04 22:00:53 +000017#include "lldb/Core/FormatEntity.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000018#include "lldb/Core/ValueObject.h"
19#include "lldb/Core/ValueObjectConstResult.h"
Enrico Granata419d7912015-09-04 00:33:51 +000020#include "lldb/DataFormatters/FormattersHelpers.h"
21#include "lldb/DataFormatters/StringPrinter.h"
22#include "lldb/DataFormatters/TypeSummary.h"
23#include "lldb/DataFormatters/VectorIterator.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000024#include "lldb/Symbol/ClangASTContext.h"
Zachary Turner01c32432017-02-14 19:06:07 +000025#include "lldb/Target/ProcessStructReader.h"
Enrico Granataea2bc0f2013-02-21 19:57:10 +000026#include "lldb/Target/Target.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000027#include "lldb/Utility/DataBufferHeap.h"
Zachary Turner01c32432017-02-14 19:06:07 +000028#include "lldb/Utility/Endian.h"
Zachary Turner97206d52017-05-12 04:51:55 +000029#include "lldb/Utility/Status.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000030#include "lldb/Utility/Stream.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;
Zachary Turner97206d52017-05-12 04:51:55 +000056 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +000057 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
Enrico Granataea2bc0f2013-02-21 19:57:10 +000079/*
80 (lldb) fr var ibeg --raw --ptr-depth 1
Kate Stoneb9c1b512016-09-06 20:57:50 +000081 (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int,
82 std::__1::basic_string<char, std::__1::char_traits<char>,
83 std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int,
84 std::__1::basic_string<char, std::__1::char_traits<char>,
85 std::__1::allocator<char> > >, void *> *, long> >) ibeg = {
Enrico Granataea2bc0f2013-02-21 19:57:10 +000086 __i_ = {
87 __ptr_ = 0x0000000100103870 {
88 std::__1::__tree_node_base<void *> = {
89 std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
90 __left_ = 0x0000000000000000
91 }
92 __right_ = 0x0000000000000000
93 __parent_ = 0x00000001001038b0
94 __is_black_ = true
95 }
96 __value_ = {
97 first = 0
98 second = { std::string }
99 */
100
Kate Stoneb9c1b512016-09-06 20:57:50 +0000101lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
102 LibCxxMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Enrico Granataae1ba732016-09-28 22:53:16 +0000103 : SyntheticChildrenFrontEnd(*valobj_sp), m_pair_ptr(), m_pair_sp() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104 if (valobj_sp)
105 Update();
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000106}
107
Kate Stoneb9c1b512016-09-06 20:57:50 +0000108bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
Enrico Granataae1ba732016-09-28 22:53:16 +0000109 m_pair_sp.reset();
110 m_pair_ptr = nullptr;
111
Kate Stoneb9c1b512016-09-06 20:57:50 +0000112 ValueObjectSP valobj_sp = m_backend.GetSP();
113 if (!valobj_sp)
Enrico Granata92373532013-03-19 22:58:48 +0000114 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000115
116 TargetSP target_sp(valobj_sp->GetTargetSP());
117
118 if (!target_sp)
119 return false;
120
121 if (!valobj_sp)
122 return false;
Enrico Granataae1ba732016-09-28 22:53:16 +0000123
124 static ConstString g___i_("__i_");
125
Kate Stoneb9c1b512016-09-06 20:57:50 +0000126 // this must be a ValueObject* because it is a child of the ValueObject we are
127 // producing children for
128 // it if were a ValueObjectSP, we would end up with a loop (iterator ->
129 // synthetic -> child -> parent == iterator)
130 // and that would in turn leak memory by never allowing the ValueObjects to
131 // die and free their memory
132 m_pair_ptr = valobj_sp
133 ->GetValueForExpressionPath(
Zachary Turnerd2daca72016-11-18 17:55:04 +0000134 ".__i_.__ptr_->__value_", nullptr, nullptr,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000135 ValueObject::GetValueForExpressionPathOptions()
136 .DontCheckDotVsArrowSyntax()
137 .SetSyntheticChildrenTraversal(
138 ValueObject::GetValueForExpressionPathOptions::
139 SyntheticChildrenTraversal::None),
140 nullptr)
141 .get();
Zachary Turnerd2daca72016-11-18 17:55:04 +0000142
Enrico Granataae1ba732016-09-28 22:53:16 +0000143 if (!m_pair_ptr) {
Zachary Turnerd2daca72016-11-18 17:55:04 +0000144 m_pair_ptr = valobj_sp
145 ->GetValueForExpressionPath(
146 ".__i_.__ptr_", nullptr, nullptr,
147 ValueObject::GetValueForExpressionPathOptions()
148 .DontCheckDotVsArrowSyntax()
149 .SetSyntheticChildrenTraversal(
150 ValueObject::GetValueForExpressionPathOptions::
151 SyntheticChildrenTraversal::None),
152 nullptr)
153 .get();
Enrico Granataae1ba732016-09-28 22:53:16 +0000154 if (m_pair_ptr) {
155 auto __i_(valobj_sp->GetChildMemberWithName(g___i_, true));
Enrico Granataae1ba732016-09-28 22:53:16 +0000156 if (!__i_) {
157 m_pair_ptr = nullptr;
158 return false;
159 }
Pavel Labath769b21e2017-11-13 14:26:21 +0000160 CompilerType pair_type(__i_->GetCompilerType().GetTypeTemplateArgument(0));
Enrico Granataae1ba732016-09-28 22:53:16 +0000161 std::string name; uint64_t bit_offset_ptr; uint32_t bitfield_bit_size_ptr; bool is_bitfield_ptr;
162 pair_type = pair_type.GetFieldAtIndex(0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
163 if (!pair_type) {
164 m_pair_ptr = nullptr;
165 return false;
166 }
167
168 auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS));
169 m_pair_ptr = nullptr;
170 if (addr && addr!=LLDB_INVALID_ADDRESS) {
171 ClangASTContext *ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(pair_type.GetTypeSystem());
172 if (!ast_ctx)
173 return false;
174 CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(ConstString(), {
175 {"ptr0",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
176 {"ptr1",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
177 {"ptr2",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
178 {"cw",ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
179 {"payload",pair_type}
180 });
181 DataBufferSP buffer_sp(new DataBufferHeap(tree_node_type.GetByteSize(nullptr),0));
182 ProcessSP process_sp(target_sp->GetProcessSP());
Zachary Turner97206d52017-05-12 04:51:55 +0000183 Status error;
Enrico Granataae1ba732016-09-28 22:53:16 +0000184 process_sp->ReadMemory(addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), error);
185 if (error.Fail())
186 return false;
187 DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
188 auto pair_sp = CreateValueObjectFromData("pair", extractor, valobj_sp->GetExecutionContextRef(), tree_node_type);
189 if (pair_sp)
190 m_pair_sp = pair_sp->GetChildAtIndex(4,true);
191 }
192 }
193 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000194
195 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000196}
197
Kate Stoneb9c1b512016-09-06 20:57:50 +0000198size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
199 CalculateNumChildren() {
200 return 2;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000201}
202
203lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000204lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex(
205 size_t idx) {
Enrico Granataae1ba732016-09-28 22:53:16 +0000206 if (m_pair_ptr)
207 return m_pair_ptr->GetChildAtIndex(idx, true);
208 if (m_pair_sp)
209 return m_pair_sp->GetChildAtIndex(idx, true);
210 return lldb::ValueObjectSP();
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000211}
212
Kate Stoneb9c1b512016-09-06 20:57:50 +0000213bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
214 MightHaveChildren() {
215 return true;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000216}
217
Kate Stoneb9c1b512016-09-06 20:57:50 +0000218size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
219 GetIndexOfChildWithName(const ConstString &name) {
220 if (name == ConstString("first"))
221 return 0;
222 if (name == ConstString("second"))
223 return 1;
224 return UINT32_MAX;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000225}
226
Kate Stoneb9c1b512016-09-06 20:57:50 +0000227lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
228 ~LibCxxMapIteratorSyntheticFrontEnd() {
229 // this will be deleted when its parent dies (since it's a child object)
230 // delete m_pair_ptr;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000231}
232
Kate Stoneb9c1b512016-09-06 20:57:50 +0000233SyntheticChildrenFrontEnd *
234lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator(
235 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
236 return (valobj_sp ? new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)
237 : nullptr);
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000238}
239
240/*
241 (lldb) fr var ibeg --raw --ptr-depth 1 -T
242 (std::__1::__wrap_iter<int *>) ibeg = {
243 (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
244 (int) *__i = 1
245 }
246 }
247*/
248
Kate Stoneb9c1b512016-09-06 20:57:50 +0000249SyntheticChildrenFrontEnd *
250lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator(
251 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
252 static ConstString g_item_name;
253 if (!g_item_name)
254 g_item_name.SetCString("__i");
255 return (valobj_sp
256 ? new VectorIteratorSyntheticFrontEnd(valobj_sp, g_item_name)
257 : nullptr);
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000258}
Enrico Granata92373532013-03-19 22:58:48 +0000259
Kate Stoneb9c1b512016-09-06 20:57:50 +0000260lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
261 LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
262 : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr), m_count_sp(),
263 m_weak_count_sp(), m_ptr_size(0), m_byte_order(lldb::eByteOrderInvalid) {
264 if (valobj_sp)
265 Update();
Enrico Granata92373532013-03-19 22:58:48 +0000266}
267
Kate Stoneb9c1b512016-09-06 20:57:50 +0000268size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
269 CalculateNumChildren() {
270 return (m_cntrl ? 1 : 0);
Enrico Granata92373532013-03-19 22:58:48 +0000271}
272
273lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000274lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
275 size_t idx) {
276 if (!m_cntrl)
277 return lldb::ValueObjectSP();
278
279 ValueObjectSP valobj_sp = m_backend.GetSP();
280 if (!valobj_sp)
281 return lldb::ValueObjectSP();
282
283 if (idx == 0)
284 return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
285
286 if (idx > 2)
287 return lldb::ValueObjectSP();
288
289 if (idx == 1) {
290 if (!m_count_sp) {
291 ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(
292 ConstString("__shared_owners_"), true));
293 if (!shared_owners_sp)
Enrico Granata92373532013-03-19 22:58:48 +0000294 return lldb::ValueObjectSP();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295 uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
296 DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
297 m_count_sp = CreateValueObjectFromData(
298 "count", data, valobj_sp->GetExecutionContextRef(),
299 shared_owners_sp->GetCompilerType());
Enrico Granata92373532013-03-19 22:58:48 +0000300 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000301 return m_count_sp;
302 } else /* if (idx == 2) */
303 {
304 if (!m_weak_count_sp) {
305 ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(
306 ConstString("__shared_weak_owners_"), true));
307 if (!shared_weak_owners_sp)
308 return lldb::ValueObjectSP();
309 uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
310 DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
311 m_weak_count_sp = CreateValueObjectFromData(
312 "count", data, valobj_sp->GetExecutionContextRef(),
313 shared_weak_owners_sp->GetCompilerType());
Enrico Granata92373532013-03-19 22:58:48 +0000314 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000315 return m_weak_count_sp;
316 }
Enrico Granata92373532013-03-19 22:58:48 +0000317}
318
Kate Stoneb9c1b512016-09-06 20:57:50 +0000319bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
320 m_count_sp.reset();
321 m_weak_count_sp.reset();
322 m_cntrl = nullptr;
323
324 ValueObjectSP valobj_sp = m_backend.GetSP();
325 if (!valobj_sp)
Enrico Granata92373532013-03-19 22:58:48 +0000326 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000327
328 TargetSP target_sp(valobj_sp->GetTargetSP());
329 if (!target_sp)
330 return false;
331
332 m_byte_order = target_sp->GetArchitecture().GetByteOrder();
333 m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize();
334
335 lldb::ValueObjectSP cntrl_sp(
336 valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"), true));
337
338 m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular
339 // dependency
340 return false;
Enrico Granata92373532013-03-19 22:58:48 +0000341}
342
Kate Stoneb9c1b512016-09-06 20:57:50 +0000343bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
344 MightHaveChildren() {
345 return true;
Enrico Granata92373532013-03-19 22:58:48 +0000346}
347
Kate Stoneb9c1b512016-09-06 20:57:50 +0000348size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
349 GetIndexOfChildWithName(const ConstString &name) {
350 if (name == ConstString("__ptr_"))
351 return 0;
352 if (name == ConstString("count"))
353 return 1;
354 if (name == ConstString("weak_count"))
355 return 2;
356 return UINT32_MAX;
Enrico Granata92373532013-03-19 22:58:48 +0000357}
358
Kate Stoneb9c1b512016-09-06 20:57:50 +0000359lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
360 ~LibcxxSharedPtrSyntheticFrontEnd() = default;
Enrico Granata92373532013-03-19 22:58:48 +0000361
Kate Stoneb9c1b512016-09-06 20:57:50 +0000362SyntheticChildrenFrontEnd *
363lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator(
364 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
365 return (valobj_sp ? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)
366 : nullptr);
Enrico Granata92373532013-03-19 22:58:48 +0000367}
368
Kate Stoneb9c1b512016-09-06 20:57:50 +0000369bool lldb_private::formatters::LibcxxContainerSummaryProvider(
370 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
371 if (valobj.IsPointerType()) {
372 uint64_t value = valobj.GetValueAsUnsigned(0);
373 if (!value)
374 return false;
375 stream.Printf("0x%016" PRIx64 " ", value);
376 }
377 return FormatEntity::FormatStringRef("size=${svar%#}", stream, nullptr,
378 nullptr, nullptr, &valobj, false, false);
Enrico Granata14b74fd2013-05-06 18:55:52 +0000379}
Enrico Granatad87cc312015-09-03 01:29:42 +0000380
381// the field layout in a libc++ string (cap, side, data or data, size, cap)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000382enum LibcxxStringLayoutMode {
383 eLibcxxStringLayoutModeCSD = 0,
384 eLibcxxStringLayoutModeDSC = 1,
385 eLibcxxStringLayoutModeInvalid = 0xffff
Enrico Granatad87cc312015-09-03 01:29:42 +0000386};
387
388// this function abstracts away the layout and mode details of a libc++ string
389// and returns the address of the data and the size ready for callers to consume
Kate Stoneb9c1b512016-09-06 20:57:50 +0000390static bool ExtractLibcxxStringInfo(ValueObject &valobj,
391 ValueObjectSP &location_sp,
392 uint64_t &size) {
393 ValueObjectSP D(valobj.GetChildAtIndexPath({0, 0, 0, 0}));
394 if (!D)
395 return false;
Enrico Granatad87cc312015-09-03 01:29:42 +0000396
Lang Hames088d0012017-04-26 18:15:40 +0000397 ValueObjectSP layout_decider(
398 D->GetChildAtIndexPath(llvm::ArrayRef<size_t>({0, 0})));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000399
400 // this child should exist
401 if (!layout_decider)
402 return false;
403
404 ConstString g_data_name("__data_");
405 ConstString g_size_name("__size_");
406 bool short_mode = false; // this means the string is in short-mode and the
407 // data is stored inline
408 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name)
409 ? eLibcxxStringLayoutModeDSC
410 : eLibcxxStringLayoutModeCSD;
411 uint64_t size_mode_value = 0;
412
413 if (layout == eLibcxxStringLayoutModeDSC) {
414 ValueObjectSP size_mode(D->GetChildAtIndexPath({1, 1, 0}));
415 if (!size_mode)
416 return false;
417
418 if (size_mode->GetName() != g_size_name) {
419 // we are hitting the padding structure, move along
420 size_mode = D->GetChildAtIndexPath({1, 1, 1});
421 if (!size_mode)
Enrico Granatad87cc312015-09-03 01:29:42 +0000422 return false;
Enrico Granatad87cc312015-09-03 01:29:42 +0000423 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000424
425 size_mode_value = (size_mode->GetValueAsUnsigned(0));
426 short_mode = ((size_mode_value & 0x80) == 0);
427 } else {
428 ValueObjectSP size_mode(D->GetChildAtIndexPath({1, 0, 0}));
429 if (!size_mode)
430 return false;
431
432 size_mode_value = (size_mode->GetValueAsUnsigned(0));
433 short_mode = ((size_mode_value & 1) == 0);
434 }
435
436 if (short_mode) {
437 ValueObjectSP s(D->GetChildAtIndex(1, true));
438 if (!s)
439 return false;
440 location_sp = s->GetChildAtIndex(
441 (layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
442 size = (layout == eLibcxxStringLayoutModeDSC)
443 ? size_mode_value
444 : ((size_mode_value >> 1) % 256);
445 return (location_sp.get() != nullptr);
446 } else {
447 ValueObjectSP l(D->GetChildAtIndex(0, true));
448 if (!l)
449 return false;
450 // we can use the layout_decider object as the data pointer
451 location_sp = (layout == eLibcxxStringLayoutModeDSC)
452 ? layout_decider
453 : l->GetChildAtIndex(2, true);
454 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
455 if (!size_vo || !location_sp)
456 return false;
457 size = size_vo->GetValueAsUnsigned(0);
Enrico Granatad87cc312015-09-03 01:29:42 +0000458 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000459 }
Enrico Granatad87cc312015-09-03 01:29:42 +0000460}
461
Kate Stoneb9c1b512016-09-06 20:57:50 +0000462bool lldb_private::formatters::LibcxxWStringSummaryProvider(
463 ValueObject &valobj, Stream &stream,
464 const TypeSummaryOptions &summary_options) {
465 uint64_t size = 0;
466 ValueObjectSP location_sp;
467 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
468 return false;
469 if (size == 0) {
470 stream.Printf("L\"\"");
Enrico Granatad87cc312015-09-03 01:29:42 +0000471 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000472 }
473 if (!location_sp)
474 return false;
475
476 DataExtractor extractor;
477
478 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
479
480 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
481 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
482 if (size > max_size) {
483 size = max_size;
484 options.SetIsTruncated(true);
485 }
486 }
487 location_sp->GetPointeeData(extractor, 0, size);
488
489 // std::wstring::size() is measured in 'characters', not bytes
490 auto wchar_t_size = valobj.GetTargetSP()
491 ->GetScratchClangASTContext()
492 ->GetBasicType(lldb::eBasicTypeWChar)
493 .GetByteSize(nullptr);
494
495 options.SetData(extractor);
496 options.SetStream(&stream);
497 options.SetPrefixToken("L");
498 options.SetQuote('"');
499 options.SetSourceSize(size);
500 options.SetBinaryZeroIsTerminator(false);
501
502 switch (wchar_t_size) {
503 case 1:
504 StringPrinter::ReadBufferAndDumpToStream<
505 lldb_private::formatters::StringPrinter::StringElementType::UTF8>(
506 options);
507 break;
508
509 case 2:
510 lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<
511 lldb_private::formatters::StringPrinter::StringElementType::UTF16>(
512 options);
513 break;
514
515 case 4:
516 lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<
517 lldb_private::formatters::StringPrinter::StringElementType::UTF32>(
518 options);
519 break;
520
521 default:
522 stream.Printf("size for wchar_t is not valid");
523 return true;
524 }
525
526 return true;
Enrico Granatad87cc312015-09-03 01:29:42 +0000527}
Enrico Granata1b54bae2016-08-31 21:46:37 +0000528
Kate Stoneb9c1b512016-09-06 20:57:50 +0000529bool lldb_private::formatters::LibcxxStringSummaryProvider(
530 ValueObject &valobj, Stream &stream,
531 const TypeSummaryOptions &summary_options) {
532 uint64_t size = 0;
533 ValueObjectSP location_sp;
534
535 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
536 return false;
537
538 if (size == 0) {
539 stream.Printf("\"\"");
540 return true;
541 }
542
543 if (!location_sp)
544 return false;
545
546 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
547
548 DataExtractor extractor;
549 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
550 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
551 if (size > max_size) {
552 size = max_size;
553 options.SetIsTruncated(true);
554 }
555 }
556 location_sp->GetPointeeData(extractor, 0, size);
557
558 options.SetData(extractor);
559 options.SetStream(&stream);
560 options.SetPrefixToken(nullptr);
561 options.SetQuote('"');
562 options.SetSourceSize(size);
563 options.SetBinaryZeroIsTerminator(false);
564 StringPrinter::ReadBufferAndDumpToStream<
565 StringPrinter::StringElementType::ASCII>(options);
566
567 return true;
568}
569
570class LibcxxFunctionFrontEnd : public SyntheticValueProviderFrontEnd {
Enrico Granata1b54bae2016-08-31 21:46:37 +0000571public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000572 LibcxxFunctionFrontEnd(ValueObject &backend)
573 : SyntheticValueProviderFrontEnd(backend) {}
574
575 lldb::ValueObjectSP GetSyntheticValue() override {
576 static ConstString g___f_("__f_");
577 return m_backend.GetChildMemberWithName(g___f_, true);
578 }
Enrico Granata1b54bae2016-08-31 21:46:37 +0000579};
580
Kate Stoneb9c1b512016-09-06 20:57:50 +0000581SyntheticChildrenFrontEnd *
582lldb_private::formatters::LibcxxFunctionFrontEndCreator(
583 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
584 if (valobj_sp)
585 return new LibcxxFunctionFrontEnd(*valobj_sp);
586 return nullptr;
Enrico Granata1b54bae2016-08-31 21:46:37 +0000587}