blob: 11245e1310b77078a604d0105da9bf0de0fae8b0 [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));
156 lldb::TemplateArgumentKind kind;
157 if (!__i_) {
158 m_pair_ptr = nullptr;
159 return false;
160 }
161 CompilerType pair_type(__i_->GetCompilerType().GetTemplateArgument(0, kind));
162 std::string name; uint64_t bit_offset_ptr; uint32_t bitfield_bit_size_ptr; bool is_bitfield_ptr;
163 pair_type = pair_type.GetFieldAtIndex(0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
164 if (!pair_type) {
165 m_pair_ptr = nullptr;
166 return false;
167 }
168
169 auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS));
170 m_pair_ptr = nullptr;
171 if (addr && addr!=LLDB_INVALID_ADDRESS) {
172 ClangASTContext *ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(pair_type.GetTypeSystem());
173 if (!ast_ctx)
174 return false;
175 CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(ConstString(), {
176 {"ptr0",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
177 {"ptr1",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
178 {"ptr2",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
179 {"cw",ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
180 {"payload",pair_type}
181 });
182 DataBufferSP buffer_sp(new DataBufferHeap(tree_node_type.GetByteSize(nullptr),0));
183 ProcessSP process_sp(target_sp->GetProcessSP());
Zachary Turner97206d52017-05-12 04:51:55 +0000184 Status error;
Enrico Granataae1ba732016-09-28 22:53:16 +0000185 process_sp->ReadMemory(addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), error);
186 if (error.Fail())
187 return false;
188 DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
189 auto pair_sp = CreateValueObjectFromData("pair", extractor, valobj_sp->GetExecutionContextRef(), tree_node_type);
190 if (pair_sp)
191 m_pair_sp = pair_sp->GetChildAtIndex(4,true);
192 }
193 }
194 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000195
196 return false;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000197}
198
Kate Stoneb9c1b512016-09-06 20:57:50 +0000199size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
200 CalculateNumChildren() {
201 return 2;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000202}
203
204lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000205lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex(
206 size_t idx) {
Enrico Granataae1ba732016-09-28 22:53:16 +0000207 if (m_pair_ptr)
208 return m_pair_ptr->GetChildAtIndex(idx, true);
209 if (m_pair_sp)
210 return m_pair_sp->GetChildAtIndex(idx, true);
211 return lldb::ValueObjectSP();
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000212}
213
Kate Stoneb9c1b512016-09-06 20:57:50 +0000214bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
215 MightHaveChildren() {
216 return true;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000217}
218
Kate Stoneb9c1b512016-09-06 20:57:50 +0000219size_t lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
220 GetIndexOfChildWithName(const ConstString &name) {
221 if (name == ConstString("first"))
222 return 0;
223 if (name == ConstString("second"))
224 return 1;
225 return UINT32_MAX;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000226}
227
Kate Stoneb9c1b512016-09-06 20:57:50 +0000228lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::
229 ~LibCxxMapIteratorSyntheticFrontEnd() {
230 // this will be deleted when its parent dies (since it's a child object)
231 // delete m_pair_ptr;
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000232}
233
Kate Stoneb9c1b512016-09-06 20:57:50 +0000234SyntheticChildrenFrontEnd *
235lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator(
236 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
237 return (valobj_sp ? new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)
238 : nullptr);
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000239}
240
241/*
242 (lldb) fr var ibeg --raw --ptr-depth 1 -T
243 (std::__1::__wrap_iter<int *>) ibeg = {
244 (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
245 (int) *__i = 1
246 }
247 }
248*/
249
Kate Stoneb9c1b512016-09-06 20:57:50 +0000250SyntheticChildrenFrontEnd *
251lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator(
252 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
253 static ConstString g_item_name;
254 if (!g_item_name)
255 g_item_name.SetCString("__i");
256 return (valobj_sp
257 ? new VectorIteratorSyntheticFrontEnd(valobj_sp, g_item_name)
258 : nullptr);
Enrico Granataea2bc0f2013-02-21 19:57:10 +0000259}
Enrico Granata92373532013-03-19 22:58:48 +0000260
Kate Stoneb9c1b512016-09-06 20:57:50 +0000261lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
262 LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
263 : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr), m_count_sp(),
264 m_weak_count_sp(), m_ptr_size(0), m_byte_order(lldb::eByteOrderInvalid) {
265 if (valobj_sp)
266 Update();
Enrico Granata92373532013-03-19 22:58:48 +0000267}
268
Kate Stoneb9c1b512016-09-06 20:57:50 +0000269size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
270 CalculateNumChildren() {
271 return (m_cntrl ? 1 : 0);
Enrico Granata92373532013-03-19 22:58:48 +0000272}
273
274lldb::ValueObjectSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000275lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex(
276 size_t idx) {
277 if (!m_cntrl)
278 return lldb::ValueObjectSP();
279
280 ValueObjectSP valobj_sp = m_backend.GetSP();
281 if (!valobj_sp)
282 return lldb::ValueObjectSP();
283
284 if (idx == 0)
285 return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
286
287 if (idx > 2)
288 return lldb::ValueObjectSP();
289
290 if (idx == 1) {
291 if (!m_count_sp) {
292 ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(
293 ConstString("__shared_owners_"), true));
294 if (!shared_owners_sp)
Enrico Granata92373532013-03-19 22:58:48 +0000295 return lldb::ValueObjectSP();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000296 uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
297 DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
298 m_count_sp = CreateValueObjectFromData(
299 "count", data, valobj_sp->GetExecutionContextRef(),
300 shared_owners_sp->GetCompilerType());
Enrico Granata92373532013-03-19 22:58:48 +0000301 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000302 return m_count_sp;
303 } else /* if (idx == 2) */
304 {
305 if (!m_weak_count_sp) {
306 ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(
307 ConstString("__shared_weak_owners_"), true));
308 if (!shared_weak_owners_sp)
309 return lldb::ValueObjectSP();
310 uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
311 DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
312 m_weak_count_sp = CreateValueObjectFromData(
313 "count", data, valobj_sp->GetExecutionContextRef(),
314 shared_weak_owners_sp->GetCompilerType());
Enrico Granata92373532013-03-19 22:58:48 +0000315 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000316 return m_weak_count_sp;
317 }
Enrico Granata92373532013-03-19 22:58:48 +0000318}
319
Kate Stoneb9c1b512016-09-06 20:57:50 +0000320bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() {
321 m_count_sp.reset();
322 m_weak_count_sp.reset();
323 m_cntrl = nullptr;
324
325 ValueObjectSP valobj_sp = m_backend.GetSP();
326 if (!valobj_sp)
Enrico Granata92373532013-03-19 22:58:48 +0000327 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000328
329 TargetSP target_sp(valobj_sp->GetTargetSP());
330 if (!target_sp)
331 return false;
332
333 m_byte_order = target_sp->GetArchitecture().GetByteOrder();
334 m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize();
335
336 lldb::ValueObjectSP cntrl_sp(
337 valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"), true));
338
339 m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular
340 // dependency
341 return false;
Enrico Granata92373532013-03-19 22:58:48 +0000342}
343
Kate Stoneb9c1b512016-09-06 20:57:50 +0000344bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
345 MightHaveChildren() {
346 return true;
Enrico Granata92373532013-03-19 22:58:48 +0000347}
348
Kate Stoneb9c1b512016-09-06 20:57:50 +0000349size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
350 GetIndexOfChildWithName(const ConstString &name) {
351 if (name == ConstString("__ptr_"))
352 return 0;
353 if (name == ConstString("count"))
354 return 1;
355 if (name == ConstString("weak_count"))
356 return 2;
357 return UINT32_MAX;
Enrico Granata92373532013-03-19 22:58:48 +0000358}
359
Kate Stoneb9c1b512016-09-06 20:57:50 +0000360lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::
361 ~LibcxxSharedPtrSyntheticFrontEnd() = default;
Enrico Granata92373532013-03-19 22:58:48 +0000362
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363SyntheticChildrenFrontEnd *
364lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator(
365 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
366 return (valobj_sp ? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)
367 : nullptr);
Enrico Granata92373532013-03-19 22:58:48 +0000368}
369
Kate Stoneb9c1b512016-09-06 20:57:50 +0000370bool lldb_private::formatters::LibcxxContainerSummaryProvider(
371 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
372 if (valobj.IsPointerType()) {
373 uint64_t value = valobj.GetValueAsUnsigned(0);
374 if (!value)
375 return false;
376 stream.Printf("0x%016" PRIx64 " ", value);
377 }
378 return FormatEntity::FormatStringRef("size=${svar%#}", stream, nullptr,
379 nullptr, nullptr, &valobj, false, false);
Enrico Granata14b74fd2013-05-06 18:55:52 +0000380}
Enrico Granatad87cc312015-09-03 01:29:42 +0000381
382// the field layout in a libc++ string (cap, side, data or data, size, cap)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000383enum LibcxxStringLayoutMode {
384 eLibcxxStringLayoutModeCSD = 0,
385 eLibcxxStringLayoutModeDSC = 1,
386 eLibcxxStringLayoutModeInvalid = 0xffff
Enrico Granatad87cc312015-09-03 01:29:42 +0000387};
388
389// this function abstracts away the layout and mode details of a libc++ string
390// and returns the address of the data and the size ready for callers to consume
Kate Stoneb9c1b512016-09-06 20:57:50 +0000391static bool ExtractLibcxxStringInfo(ValueObject &valobj,
392 ValueObjectSP &location_sp,
393 uint64_t &size) {
394 ValueObjectSP D(valobj.GetChildAtIndexPath({0, 0, 0, 0}));
395 if (!D)
396 return false;
Enrico Granatad87cc312015-09-03 01:29:42 +0000397
Lang Hames088d0012017-04-26 18:15:40 +0000398 ValueObjectSP layout_decider(
399 D->GetChildAtIndexPath(llvm::ArrayRef<size_t>({0, 0})));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000400
401 // this child should exist
402 if (!layout_decider)
403 return false;
404
405 ConstString g_data_name("__data_");
406 ConstString g_size_name("__size_");
407 bool short_mode = false; // this means the string is in short-mode and the
408 // data is stored inline
409 LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name)
410 ? eLibcxxStringLayoutModeDSC
411 : eLibcxxStringLayoutModeCSD;
412 uint64_t size_mode_value = 0;
413
414 if (layout == eLibcxxStringLayoutModeDSC) {
415 ValueObjectSP size_mode(D->GetChildAtIndexPath({1, 1, 0}));
416 if (!size_mode)
417 return false;
418
419 if (size_mode->GetName() != g_size_name) {
420 // we are hitting the padding structure, move along
421 size_mode = D->GetChildAtIndexPath({1, 1, 1});
422 if (!size_mode)
Enrico Granatad87cc312015-09-03 01:29:42 +0000423 return false;
Enrico Granatad87cc312015-09-03 01:29:42 +0000424 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000425
426 size_mode_value = (size_mode->GetValueAsUnsigned(0));
427 short_mode = ((size_mode_value & 0x80) == 0);
428 } else {
429 ValueObjectSP size_mode(D->GetChildAtIndexPath({1, 0, 0}));
430 if (!size_mode)
431 return false;
432
433 size_mode_value = (size_mode->GetValueAsUnsigned(0));
434 short_mode = ((size_mode_value & 1) == 0);
435 }
436
437 if (short_mode) {
438 ValueObjectSP s(D->GetChildAtIndex(1, true));
439 if (!s)
440 return false;
441 location_sp = s->GetChildAtIndex(
442 (layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
443 size = (layout == eLibcxxStringLayoutModeDSC)
444 ? size_mode_value
445 : ((size_mode_value >> 1) % 256);
446 return (location_sp.get() != nullptr);
447 } else {
448 ValueObjectSP l(D->GetChildAtIndex(0, true));
449 if (!l)
450 return false;
451 // we can use the layout_decider object as the data pointer
452 location_sp = (layout == eLibcxxStringLayoutModeDSC)
453 ? layout_decider
454 : l->GetChildAtIndex(2, true);
455 ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
456 if (!size_vo || !location_sp)
457 return false;
458 size = size_vo->GetValueAsUnsigned(0);
Enrico Granatad87cc312015-09-03 01:29:42 +0000459 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000460 }
Enrico Granatad87cc312015-09-03 01:29:42 +0000461}
462
Kate Stoneb9c1b512016-09-06 20:57:50 +0000463bool lldb_private::formatters::LibcxxWStringSummaryProvider(
464 ValueObject &valobj, Stream &stream,
465 const TypeSummaryOptions &summary_options) {
466 uint64_t size = 0;
467 ValueObjectSP location_sp;
468 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
469 return false;
470 if (size == 0) {
471 stream.Printf("L\"\"");
Enrico Granatad87cc312015-09-03 01:29:42 +0000472 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000473 }
474 if (!location_sp)
475 return false;
476
477 DataExtractor extractor;
478
479 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
480
481 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
482 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
483 if (size > max_size) {
484 size = max_size;
485 options.SetIsTruncated(true);
486 }
487 }
488 location_sp->GetPointeeData(extractor, 0, size);
489
490 // std::wstring::size() is measured in 'characters', not bytes
491 auto wchar_t_size = valobj.GetTargetSP()
492 ->GetScratchClangASTContext()
493 ->GetBasicType(lldb::eBasicTypeWChar)
494 .GetByteSize(nullptr);
495
496 options.SetData(extractor);
497 options.SetStream(&stream);
498 options.SetPrefixToken("L");
499 options.SetQuote('"');
500 options.SetSourceSize(size);
501 options.SetBinaryZeroIsTerminator(false);
502
503 switch (wchar_t_size) {
504 case 1:
505 StringPrinter::ReadBufferAndDumpToStream<
506 lldb_private::formatters::StringPrinter::StringElementType::UTF8>(
507 options);
508 break;
509
510 case 2:
511 lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<
512 lldb_private::formatters::StringPrinter::StringElementType::UTF16>(
513 options);
514 break;
515
516 case 4:
517 lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<
518 lldb_private::formatters::StringPrinter::StringElementType::UTF32>(
519 options);
520 break;
521
522 default:
523 stream.Printf("size for wchar_t is not valid");
524 return true;
525 }
526
527 return true;
Enrico Granatad87cc312015-09-03 01:29:42 +0000528}
Enrico Granata1b54bae2016-08-31 21:46:37 +0000529
Kate Stoneb9c1b512016-09-06 20:57:50 +0000530bool lldb_private::formatters::LibcxxStringSummaryProvider(
531 ValueObject &valobj, Stream &stream,
532 const TypeSummaryOptions &summary_options) {
533 uint64_t size = 0;
534 ValueObjectSP location_sp;
535
536 if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
537 return false;
538
539 if (size == 0) {
540 stream.Printf("\"\"");
541 return true;
542 }
543
544 if (!location_sp)
545 return false;
546
547 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
548
549 DataExtractor extractor;
550 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
551 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
552 if (size > max_size) {
553 size = max_size;
554 options.SetIsTruncated(true);
555 }
556 }
557 location_sp->GetPointeeData(extractor, 0, size);
558
559 options.SetData(extractor);
560 options.SetStream(&stream);
561 options.SetPrefixToken(nullptr);
562 options.SetQuote('"');
563 options.SetSourceSize(size);
564 options.SetBinaryZeroIsTerminator(false);
565 StringPrinter::ReadBufferAndDumpToStream<
566 StringPrinter::StringElementType::ASCII>(options);
567
568 return true;
569}
570
571class LibcxxFunctionFrontEnd : public SyntheticValueProviderFrontEnd {
Enrico Granata1b54bae2016-08-31 21:46:37 +0000572public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000573 LibcxxFunctionFrontEnd(ValueObject &backend)
574 : SyntheticValueProviderFrontEnd(backend) {}
575
576 lldb::ValueObjectSP GetSyntheticValue() override {
577 static ConstString g___f_("__f_");
578 return m_backend.GetChildMemberWithName(g___f_, true);
579 }
Enrico Granata1b54bae2016-08-31 21:46:37 +0000580};
581
Kate Stoneb9c1b512016-09-06 20:57:50 +0000582SyntheticChildrenFrontEnd *
583lldb_private::formatters::LibcxxFunctionFrontEndCreator(
584 CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
585 if (valobj_sp)
586 return new LibcxxFunctionFrontEnd(*valobj_sp);
587 return nullptr;
Enrico Granata1b54bae2016-08-31 21:46:37 +0000588}