LLDB mainline
LibCxx.cpp
Go to the documentation of this file.
1//===-- LibCxx.cpp --------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "LibCxx.h"
10
11#include "lldb/Core/Debugger.h"
20#include "lldb/Target/Target.h"
23#include "lldb/Utility/Endian.h"
24#include "lldb/Utility/Status.h"
25#include "lldb/Utility/Stream.h"
26
30#include <optional>
31#include <tuple>
32
33using namespace lldb;
34using namespace lldb_private;
35using namespace lldb_private::formatters;
36
38 ValueObject &obj, llvm::ArrayRef<ConstString> alternative_names) {
39 for (ConstString name : alternative_names) {
41
42 if (child_sp)
43 return child_sp;
44 }
45 return {};
46}
47
50 ValueObject &pair) {
51 ValueObjectSP value;
52 ValueObjectSP first_child = pair.GetChildAtIndex(0);
53 if (first_child)
54 value = first_child->GetChildMemberWithName("__value_");
55 if (!value) {
56 // pre-r300140 member name
57 value = pair.GetChildMemberWithName("__first_");
58 }
59 return value;
60}
61
64 ValueObject &pair) {
65 ValueObjectSP value;
66 if (pair.GetNumChildren() > 1) {
67 ValueObjectSP second_child = pair.GetChildAtIndex(1);
68 if (second_child) {
69 value = second_child->GetChildMemberWithName("__value_");
70 }
71 }
72 if (!value) {
73 // pre-r300140 member name
74 value = pair.GetChildMemberWithName("__second_");
75 }
76 return value;
77}
78
80 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
81
82 ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
83
84 if (!valobj_sp)
85 return false;
86
87 ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
88 Process *process = exe_ctx.GetProcessPtr();
89
90 if (process == nullptr)
91 return false;
92
93 CPPLanguageRuntime *cpp_runtime = CPPLanguageRuntime::Get(*process);
94
95 if (!cpp_runtime)
96 return false;
97
99 cpp_runtime->FindLibCppStdFunctionCallableInfo(valobj_sp);
100
101 switch (callable_info.callable_case) {
102 case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Invalid:
103 stream.Printf(" __f_ = %" PRIu64, callable_info.member_f_pointer_value);
104 return false;
105 break;
106 case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Lambda:
107 stream.Printf(
108 " Lambda in File %s at Line %u",
110 callable_info.callable_line_entry.line);
111 break;
112 case CPPLanguageRuntime::LibCppStdFunctionCallableCase::CallableObject:
113 stream.Printf(
114 " Function in File %s at Line %u",
116 callable_info.callable_line_entry.line);
117 break;
118 case CPPLanguageRuntime::LibCppStdFunctionCallableCase::FreeOrMemberFunction:
119 stream.Printf(" Function = %s ",
120 callable_info.callable_symbol.GetName().GetCString());
121 break;
122 }
123
124 return true;
125}
126
128 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
129 ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
130 if (!valobj_sp)
131 return false;
132 ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_"));
133 ValueObjectSP count_sp(
134 valobj_sp->GetChildAtNamePath({"__cntrl_", "__shared_owners_"}));
135 ValueObjectSP weakcount_sp(
136 valobj_sp->GetChildAtNamePath({"__cntrl_", "__shared_weak_owners_"}));
137
138 if (!ptr_sp)
139 return false;
140
141 if (ptr_sp->GetValueAsUnsigned(0) == 0) {
142 stream.Printf("nullptr");
143 return true;
144 } else {
145 bool print_pointee = false;
147 ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
148 if (pointee_sp && error.Success()) {
149 if (pointee_sp->DumpPrintableRepresentation(
152 ValueObject::PrintableRepresentationSpecialCases::eDisable,
153 false))
154 print_pointee = true;
155 }
156 if (!print_pointee)
157 stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
158 }
159
160 if (count_sp)
161 stream.Printf(" strong=%" PRIu64, 1 + count_sp->GetValueAsUnsigned(0));
162
163 if (weakcount_sp)
164 stream.Printf(" weak=%" PRIu64, 1 + weakcount_sp->GetValueAsUnsigned(0));
165
166 return true;
167}
168
170 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
171 ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
172 if (!valobj_sp)
173 return false;
174
175 ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_"));
176 if (!ptr_sp)
177 return false;
178
179 ptr_sp = GetFirstValueOfLibCXXCompressedPair(*ptr_sp);
180 if (!ptr_sp)
181 return false;
182
183 if (ptr_sp->GetValueAsUnsigned(0) == 0) {
184 stream.Printf("nullptr");
185 return true;
186 } else {
187 bool print_pointee = false;
189 ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
190 if (pointee_sp && error.Success()) {
191 if (pointee_sp->DumpPrintableRepresentation(
194 ValueObject::PrintableRepresentationSpecialCases::eDisable,
195 false))
196 print_pointee = true;
197 }
198 if (!print_pointee)
199 stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
200 }
201
202 return true;
203}
204
205/*
206 (lldb) fr var ibeg --raw --ptr-depth 1
207 (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int,
208 std::__1::basic_string<char, std::__1::char_traits<char>,
209 std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int,
210 std::__1::basic_string<char, std::__1::char_traits<char>,
211 std::__1::allocator<char> > >, void *> *, long> >) ibeg = {
212 __i_ = {
213 __ptr_ = 0x0000000100103870 {
214 std::__1::__tree_node_base<void *> = {
215 std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
216 __left_ = 0x0000000000000000
217 }
218 __right_ = 0x0000000000000000
219 __parent_ = 0x00000001001038b0
220 __is_black_ = true
221 }
222 __value_ = {
223 first = 0
224 second = { std::string }
225 */
226
229 : SyntheticChildrenFrontEnd(*valobj_sp), m_pair_ptr(), m_pair_sp() {
230 if (valobj_sp)
231 Update();
232}
233
235 m_pair_sp.reset();
236 m_pair_ptr = nullptr;
237
238 ValueObjectSP valobj_sp = m_backend.GetSP();
239 if (!valobj_sp)
240 return false;
241
242 TargetSP target_sp(valobj_sp->GetTargetSP());
243
244 if (!target_sp)
245 return false;
246
247 if (!valobj_sp)
248 return false;
249
250 // this must be a ValueObject* because it is a child of the ValueObject we
251 // are producing children for it if were a ValueObjectSP, we would end up
252 // with a loop (iterator -> synthetic -> child -> parent == iterator) and
253 // that would in turn leak memory by never allowing the ValueObjects to die
254 // and free their memory
255 m_pair_ptr = valobj_sp
256 ->GetValueForExpressionPath(
257 ".__i_.__ptr_->__value_", nullptr, nullptr,
259 .DontCheckDotVsArrowSyntax()
260 .SetSyntheticChildrenTraversal(
262 SyntheticChildrenTraversal::None),
263 nullptr)
264 .get();
265
266 if (!m_pair_ptr) {
267 m_pair_ptr = valobj_sp
268 ->GetValueForExpressionPath(
269 ".__i_.__ptr_", nullptr, nullptr,
271 .DontCheckDotVsArrowSyntax()
272 .SetSyntheticChildrenTraversal(
274 SyntheticChildrenTraversal::None),
275 nullptr)
276 .get();
277 if (m_pair_ptr) {
278 auto __i_(valobj_sp->GetChildMemberWithName("__i_"));
279 if (!__i_) {
280 m_pair_ptr = nullptr;
281 return false;
282 }
283 CompilerType pair_type(
284 __i_->GetCompilerType().GetTypeTemplateArgument(0));
285 std::string name;
286 uint64_t bit_offset_ptr;
287 uint32_t bitfield_bit_size_ptr;
288 bool is_bitfield_ptr;
289 pair_type = pair_type.GetFieldAtIndex(
290 0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
291 if (!pair_type) {
292 m_pair_ptr = nullptr;
293 return false;
294 }
295
296 auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS));
297 m_pair_ptr = nullptr;
298 if (addr && addr != LLDB_INVALID_ADDRESS) {
299 auto ts = pair_type.GetTypeSystem();
300 auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>();
301 if (!ast_ctx)
302 return false;
303
304 // Mimick layout of std::__tree_iterator::__ptr_ and read it in
305 // from process memory.
306 //
307 // The following shows the contiguous block of memory:
308 //
309 // +-----------------------------+ class __tree_end_node
310 // __ptr_ | pointer __left_; |
311 // +-----------------------------+ class __tree_node_base
312 // | pointer __right_; |
313 // | __parent_pointer __parent_; |
314 // | bool __is_black_; |
315 // +-----------------------------+ class __tree_node
316 // | __node_value_type __value_; | <<< our key/value pair
317 // +-----------------------------+
318 //
319 CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
320 llvm::StringRef(),
321 {{"ptr0",
322 ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
323 {"ptr1",
324 ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
325 {"ptr2",
326 ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
327 {"cw", ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
328 {"payload", pair_type}});
329 std::optional<uint64_t> size = tree_node_type.GetByteSize(nullptr);
330 if (!size)
331 return false;
332 WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
333 ProcessSP process_sp(target_sp->GetProcessSP());
335 process_sp->ReadMemory(addr, buffer_sp->GetBytes(),
336 buffer_sp->GetByteSize(), error);
337 if (error.Fail())
338 return false;
339 DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(),
340 process_sp->GetAddressByteSize());
341 auto pair_sp = CreateValueObjectFromData(
342 "pair", extractor, valobj_sp->GetExecutionContextRef(),
343 tree_node_type);
344 if (pair_sp)
345 m_pair_sp = pair_sp->GetChildAtIndex(4);
346 }
347 }
348 }
349
350 return false;
351}
352
355 return 2;
356}
357
360 size_t idx) {
361 if (m_pair_ptr)
362 return m_pair_ptr->GetChildAtIndex(idx);
363 if (m_pair_sp)
364 return m_pair_sp->GetChildAtIndex(idx);
365 return lldb::ValueObjectSP();
366}
367
370 return true;
371}
372
375 if (name == "first")
376 return 0;
377 if (name == "second")
378 return 1;
379 return UINT32_MAX;
380}
381
384 // this will be deleted when its parent dies (since it's a child object)
385 // delete m_pair_ptr;
386}
387
391 return (valobj_sp ? new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)
392 : nullptr);
393}
394
397 : SyntheticChildrenFrontEnd(*valobj_sp) {
398 if (valobj_sp)
399 Update();
400}
401
403 Update() {
404 m_pair_sp.reset();
405 m_iter_ptr = nullptr;
406
407 ValueObjectSP valobj_sp = m_backend.GetSP();
408 if (!valobj_sp)
409 return false;
410
411 TargetSP target_sp(valobj_sp->GetTargetSP());
412
413 if (!target_sp)
414 return false;
415
416 if (!valobj_sp)
417 return false;
418
419 auto exprPathOptions = ValueObject::GetValueForExpressionPathOptions()
423 SyntheticChildrenTraversal::None);
424
425 // This must be a ValueObject* because it is a child of the ValueObject we
426 // are producing children for it if were a ValueObjectSP, we would end up
427 // with a loop (iterator -> synthetic -> child -> parent == iterator) and
428 // that would in turn leak memory by never allowing the ValueObjects to die
429 // and free their memory.
430 m_iter_ptr =
431 valobj_sp
432 ->GetValueForExpressionPath(".__i_.__node_", nullptr, nullptr,
433 exprPathOptions, nullptr)
434 .get();
435
436 if (m_iter_ptr) {
437 auto iter_child(valobj_sp->GetChildMemberWithName("__i_"));
438 if (!iter_child) {
439 m_iter_ptr = nullptr;
440 return false;
441 }
442
443 CompilerType node_type(iter_child->GetCompilerType()
444 .GetTypeTemplateArgument(0)
445 .GetPointeeType());
446
447 CompilerType pair_type(node_type.GetTypeTemplateArgument(0));
448
449 std::string name;
450 uint64_t bit_offset_ptr;
451 uint32_t bitfield_bit_size_ptr;
452 bool is_bitfield_ptr;
453
454 pair_type = pair_type.GetFieldAtIndex(
455 0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
456 if (!pair_type) {
457 m_iter_ptr = nullptr;
458 return false;
459 }
460
461 uint64_t addr = m_iter_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
462 m_iter_ptr = nullptr;
463
464 if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
465 return false;
466
467 auto ts = pair_type.GetTypeSystem();
468 auto ast_ctx = ts.dyn_cast_or_null<TypeSystemClang>();
469 if (!ast_ctx)
470 return false;
471
472 // Mimick layout of std::__hash_iterator::__node_ and read it in
473 // from process memory.
474 //
475 // The following shows the contiguous block of memory:
476 //
477 // +-----------------------------+ class __hash_node_base
478 // __node_ | __next_pointer __next_; |
479 // +-----------------------------+ class __hash_node
480 // | size_t __hash_; |
481 // | __node_value_type __value_; | <<< our key/value pair
482 // +-----------------------------+
483 //
484 CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
485 llvm::StringRef(),
486 {{"__next_",
487 ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
488 {"__hash_", ast_ctx->GetBasicType(lldb::eBasicTypeUnsignedLongLong)},
489 {"__value_", pair_type}});
490 std::optional<uint64_t> size = tree_node_type.GetByteSize(nullptr);
491 if (!size)
492 return false;
493 WritableDataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
494 ProcessSP process_sp(target_sp->GetProcessSP());
496 process_sp->ReadMemory(addr, buffer_sp->GetBytes(),
497 buffer_sp->GetByteSize(), error);
498 if (error.Fail())
499 return false;
500 DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(),
501 process_sp->GetAddressByteSize());
502 auto pair_sp = CreateValueObjectFromData(
503 "pair", extractor, valobj_sp->GetExecutionContextRef(), tree_node_type);
504 if (pair_sp)
505 m_pair_sp = pair_sp->GetChildAtIndex(2);
506 }
507
508 return false;
509}
510
513 return 2;
514}
515
518 if (m_pair_sp)
519 return m_pair_sp->GetChildAtIndex(idx);
520 return lldb::ValueObjectSP();
521}
522
525 return true;
526}
527
530 if (name == "first")
531 return 0;
532 if (name == "second")
533 return 1;
534 return UINT32_MAX;
535}
536
540 return (valobj_sp ? new LibCxxUnorderedMapIteratorSyntheticFrontEnd(valobj_sp)
541 : nullptr);
542}
543
544/*
545 (lldb) fr var ibeg --raw --ptr-depth 1 -T
546 (std::__1::__wrap_iter<int *>) ibeg = {
547 (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
548 (int) *__i = 1
549 }
550 }
551*/
552
556 return (valobj_sp ? new VectorIteratorSyntheticFrontEnd(
557 valobj_sp, {ConstString("__i_"), ConstString("__i")})
558 : nullptr);
559}
560
563 : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr) {
564 if (valobj_sp)
565 Update();
566}
567
570 return (m_cntrl ? 1 : 0);
571}
572
575 size_t idx) {
576 if (!m_cntrl)
577 return lldb::ValueObjectSP();
578
579 ValueObjectSP valobj_sp = m_backend.GetSP();
580 if (!valobj_sp)
581 return lldb::ValueObjectSP();
582
583 if (idx == 0)
584 return valobj_sp->GetChildMemberWithName("__ptr_");
585
586 if (idx == 1) {
587 if (auto ptr_sp = valobj_sp->GetChildMemberWithName("__ptr_")) {
588 Status status;
589 auto value_type_sp =
590 valobj_sp->GetCompilerType()
591 .GetTypeTemplateArgument(0).GetPointerType();
592 ValueObjectSP cast_ptr_sp = ptr_sp->Cast(value_type_sp);
593 ValueObjectSP value_sp = cast_ptr_sp->Dereference(status);
594 if (status.Success()) {
595 return value_sp;
596 }
597 }
598 }
599
600 return lldb::ValueObjectSP();
601}
602
604 m_cntrl = nullptr;
605
606 ValueObjectSP valobj_sp = m_backend.GetSP();
607 if (!valobj_sp)
608 return false;
609
610 TargetSP target_sp(valobj_sp->GetTargetSP());
611 if (!target_sp)
612 return false;
613
614 lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName("__cntrl_"));
615
616 m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular
617 // dependency
618 return false;
619}
620
623 return true;
624}
625
628 if (name == "__ptr_")
629 return 0;
630 if (name == "$$dereference$$")
631 return 1;
632 return UINT32_MAX;
633}
634
637
641 return (valobj_sp ? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)
642 : nullptr);
643}
644
647 : SyntheticChildrenFrontEnd(*valobj_sp) {
648 if (valobj_sp)
649 Update();
650}
651
654
658 return (valobj_sp ? new LibcxxUniquePtrSyntheticFrontEnd(valobj_sp)
659 : nullptr);
660}
661
664 if (m_value_ptr_sp)
665 return m_deleter_sp ? 2 : 1;
666 return 0;
667}
668
671 size_t idx) {
672 if (!m_value_ptr_sp)
673 return lldb::ValueObjectSP();
674
675 if (idx == 0)
676 return m_value_ptr_sp;
677
678 if (idx == 1)
679 return m_deleter_sp;
680
681 if (idx == 2) {
682 Status status;
683 auto value_sp = m_value_ptr_sp->Dereference(status);
684 if (status.Success()) {
685 return value_sp;
686 }
687 }
688
689 return lldb::ValueObjectSP();
690}
691
693 ValueObjectSP valobj_sp = m_backend.GetSP();
694 if (!valobj_sp)
695 return false;
696
697 ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_"));
698 if (!ptr_sp)
699 return false;
700
701 // Retrieve the actual pointer and the deleter, and clone them to give them
702 // user-friendly names.
703 ValueObjectSP value_pointer_sp = GetFirstValueOfLibCXXCompressedPair(*ptr_sp);
704 if (value_pointer_sp)
705 m_value_ptr_sp = value_pointer_sp->Clone(ConstString("pointer"));
706
708 if (deleter_sp)
709 m_deleter_sp = deleter_sp->Clone(ConstString("deleter"));
710
711 return false;
712}
713
716 return true;
717}
718
721 if (name == "pointer")
722 return 0;
723 if (name == "deleter")
724 return 1;
725 if (name == "$$dereference$$")
726 return 2;
727 return UINT32_MAX;
728}
729
731 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
732 if (valobj.IsPointerType()) {
733 uint64_t value = valobj.GetValueAsUnsigned(0);
734 if (!value)
735 return false;
736 stream.Printf("0x%016" PRIx64 " ", value);
737 }
738 return FormatEntity::FormatStringRef("size=${svar%#}", stream, nullptr,
739 nullptr, nullptr, &valobj, false, false);
740}
741
742/// The field layout in a libc++ string (cap, side, data or data, size, cap).
743namespace {
744enum class StringLayout { CSD, DSC };
745}
746
747/// Determine the size in bytes of \p valobj (a libc++ std::string object) and
748/// extract its data payload. Return the size + payload pair.
749// TODO: Support big-endian architectures.
750static std::optional<std::pair<uint64_t, ValueObjectSP>>
752 ValueObjectSP valobj_r_sp = valobj.GetChildMemberWithName("__r_");
753 if (!valobj_r_sp || !valobj_r_sp->GetError().Success())
754 return {};
755
756 // __r_ is a compressed_pair of the actual data and the allocator. The data we
757 // want is in the first base class.
758 ValueObjectSP valobj_r_base_sp = valobj_r_sp->GetChildAtIndex(0);
759 if (!valobj_r_base_sp)
760 return {};
761
762 ValueObjectSP valobj_rep_sp =
763 valobj_r_base_sp->GetChildMemberWithName("__value_");
764 if (!valobj_rep_sp)
765 return {};
766
767 ValueObjectSP l = valobj_rep_sp->GetChildMemberWithName("__l");
768 if (!l)
769 return {};
770
771 StringLayout layout = l->GetIndexOfChildWithName("__data_") == 0
772 ? StringLayout::DSC
773 : StringLayout::CSD;
774
775 bool short_mode = false; // this means the string is in short-mode and the
776 // data is stored inline
777 bool using_bitmasks = true; // Whether the class uses bitmasks for the mode
778 // flag (pre-D123580).
779 uint64_t size;
780 uint64_t size_mode_value = 0;
781
782 ValueObjectSP short_sp = valobj_rep_sp->GetChildMemberWithName("__s");
783 if (!short_sp)
784 return {};
785
786 ValueObjectSP is_long = short_sp->GetChildMemberWithName("__is_long_");
787 ValueObjectSP size_sp = short_sp->GetChildMemberWithName("__size_");
788 if (!size_sp)
789 return {};
790
791 if (is_long) {
792 using_bitmasks = false;
793 short_mode = !is_long->GetValueAsUnsigned(/*fail_value=*/0);
794 size = size_sp->GetValueAsUnsigned(/*fail_value=*/0);
795 } else {
796 // The string mode is encoded in the size field.
797 size_mode_value = size_sp->GetValueAsUnsigned(0);
798 uint8_t mode_mask = layout == StringLayout::DSC ? 0x80 : 1;
799 short_mode = (size_mode_value & mode_mask) == 0;
800 }
801
802 if (short_mode) {
803 ValueObjectSP location_sp = short_sp->GetChildMemberWithName("__data_");
804 if (using_bitmasks)
805 size = (layout == StringLayout::DSC) ? size_mode_value
806 : ((size_mode_value >> 1) % 256);
807
808 // When the small-string optimization takes place, the data must fit in the
809 // inline string buffer (23 bytes on x86_64/Darwin). If it doesn't, it's
810 // likely that the string isn't initialized and we're reading garbage.
811 ExecutionContext exe_ctx(location_sp->GetExecutionContextRef());
812 const std::optional<uint64_t> max_bytes =
813 location_sp->GetCompilerType().GetByteSize(
815 if (!max_bytes || size > *max_bytes || !location_sp)
816 return {};
817
818 return std::make_pair(size, location_sp);
819 }
820
821 // we can use the layout_decider object as the data pointer
822 ValueObjectSP location_sp = l->GetChildMemberWithName("__data_");
823 ValueObjectSP size_vo = l->GetChildMemberWithName("__size_");
824 ValueObjectSP capacity_vo = l->GetChildMemberWithName("__cap_");
825 if (!size_vo || !location_sp || !capacity_vo)
826 return {};
827 size = size_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
828 uint64_t capacity = capacity_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
829 if (!using_bitmasks && layout == StringLayout::CSD)
830 capacity *= 2;
831 if (size == LLDB_INVALID_OFFSET || capacity == LLDB_INVALID_OFFSET ||
832 capacity < size)
833 return {};
834 return std::make_pair(size, location_sp);
835}
836
837static bool
839 const TypeSummaryOptions &summary_options,
840 ValueObjectSP location_sp, size_t size) {
841 if (size == 0) {
842 stream.Printf("L\"\"");
843 return true;
844 }
845 if (!location_sp)
846 return false;
847
849 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
850 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
851 if (size > max_size) {
852 size = max_size;
853 options.SetIsTruncated(true);
854 }
855 }
856
857 DataExtractor extractor;
858 const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
859 if (bytes_read < size)
860 return false;
861
862 // std::wstring::size() is measured in 'characters', not bytes
863 TypeSystemClangSP scratch_ts_sp =
865 if (!scratch_ts_sp)
866 return false;
867
868 auto wchar_t_size =
869 scratch_ts_sp->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr);
870 if (!wchar_t_size)
871 return false;
872
873 options.SetData(std::move(extractor));
874 options.SetStream(&stream);
875 options.SetPrefixToken("L");
876 options.SetQuote('"');
877 options.SetSourceSize(size);
878 options.SetBinaryZeroIsTerminator(false);
879
880 switch (*wchar_t_size) {
881 case 1:
883 lldb_private::formatters::StringPrinter::StringElementType::UTF8>(
884 options);
885 break;
886
887 case 2:
889 lldb_private::formatters::StringPrinter::StringElementType::UTF16>(
890 options);
891 break;
892
893 case 4:
895 lldb_private::formatters::StringPrinter::StringElementType::UTF32>(
896 options);
897 }
898 return false;
899}
900
902 ValueObject &valobj, Stream &stream,
903 const TypeSummaryOptions &summary_options) {
904 auto string_info = ExtractLibcxxStringInfo(valobj);
905 if (!string_info)
906 return false;
907 uint64_t size;
908 ValueObjectSP location_sp;
909 std::tie(size, location_sp) = *string_info;
910
911 return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options,
912 location_sp, size);
913}
914
915template <StringPrinter::StringElementType element_type>
916static bool
918 const TypeSummaryOptions &summary_options,
919 std::string prefix_token, ValueObjectSP location_sp,
920 uint64_t size) {
921
922 if (size == 0) {
923 stream.Printf("\"\"");
924 return true;
925 }
926
927 if (!location_sp)
928 return false;
929
931
932 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
933 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
934 if (size > max_size) {
935 size = max_size;
936 options.SetIsTruncated(true);
937 }
938 }
939
940 {
941 DataExtractor extractor;
942 const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
943 if (bytes_read < size)
944 return false;
945
946 options.SetData(std::move(extractor));
947 }
948 options.SetStream(&stream);
949 if (prefix_token.empty())
950 options.SetPrefixToken(nullptr);
951 else
952 options.SetPrefixToken(prefix_token);
953 options.SetQuote('"');
954 options.SetSourceSize(size);
955 options.SetBinaryZeroIsTerminator(false);
956 return StringPrinter::ReadBufferAndDumpToStream<element_type>(options);
957}
958
959template <StringPrinter::StringElementType element_type>
960static bool
962 const TypeSummaryOptions &summary_options,
963 std::string prefix_token) {
964 auto string_info = ExtractLibcxxStringInfo(valobj);
965 if (!string_info)
966 return false;
967 uint64_t size;
968 ValueObjectSP location_sp;
969 std::tie(size, location_sp) = *string_info;
970
971 return LibcxxStringSummaryProvider<element_type>(
972 valobj, stream, summary_options, prefix_token, location_sp, size);
973}
974template <StringPrinter::StringElementType element_type>
975static bool formatStringImpl(ValueObject &valobj, Stream &stream,
976 const TypeSummaryOptions &summary_options,
977 std::string prefix_token) {
978 StreamString scratch_stream;
979 const bool success = LibcxxStringSummaryProvider<element_type>(
980 valobj, scratch_stream, summary_options, prefix_token);
981 if (success)
982 stream << scratch_stream.GetData();
983 else
984 stream << "Summary Unavailable";
985 return true;
986}
987
989 ValueObject &valobj, Stream &stream,
990 const TypeSummaryOptions &summary_options) {
991 return formatStringImpl<StringPrinter::StringElementType::ASCII>(
992 valobj, stream, summary_options, "");
993}
994
996 ValueObject &valobj, Stream &stream,
997 const TypeSummaryOptions &summary_options) {
998 return formatStringImpl<StringPrinter::StringElementType::UTF16>(
999 valobj, stream, summary_options, "u");
1000}
1001
1003 ValueObject &valobj, Stream &stream,
1004 const TypeSummaryOptions &summary_options) {
1005 return formatStringImpl<StringPrinter::StringElementType::UTF32>(
1006 valobj, stream, summary_options, "U");
1007}
1008
1009static std::tuple<bool, ValueObjectSP, size_t>
1011 auto dataobj = GetChildMemberWithName(
1012 valobj, {ConstString("__data_"), ConstString("__data")});
1013 auto sizeobj = GetChildMemberWithName(
1014 valobj, {ConstString("__size_"), ConstString("__size")});
1015 if (!dataobj || !sizeobj)
1016 return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
1017
1018 if (!dataobj->GetError().Success() || !sizeobj->GetError().Success())
1019 return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
1020
1021 bool success{false};
1022 uint64_t size = sizeobj->GetValueAsUnsigned(0, &success);
1023 if (!success)
1024 return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
1025
1026 return std::make_tuple(true,dataobj,size);
1027}
1028
1029template <StringPrinter::StringElementType element_type>
1030static bool formatStringViewImpl(ValueObject &valobj, Stream &stream,
1031 const TypeSummaryOptions &summary_options,
1032 std::string prefix_token) {
1033
1034 bool success;
1035 ValueObjectSP dataobj;
1036 size_t size;
1037 std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj);
1038
1039 if (!success) {
1040 stream << "Summary Unavailable";
1041 return true;
1042 }
1043
1044 return LibcxxStringSummaryProvider<element_type>(
1045 valobj, stream, summary_options, prefix_token, dataobj, size);
1046}
1047
1049 ValueObject &valobj, Stream &stream,
1050 const TypeSummaryOptions &summary_options) {
1051 return formatStringViewImpl<StringPrinter::StringElementType::ASCII>(
1052 valobj, stream, summary_options, "");
1053}
1054
1056 ValueObject &valobj, Stream &stream,
1057 const TypeSummaryOptions &summary_options) {
1058 return formatStringViewImpl<StringPrinter::StringElementType::UTF16>(
1059 valobj, stream, summary_options, "u");
1060}
1061
1063 ValueObject &valobj, Stream &stream,
1064 const TypeSummaryOptions &summary_options) {
1065 return formatStringViewImpl<StringPrinter::StringElementType::UTF32>(
1066 valobj, stream, summary_options, "U");
1067}
1068
1070 ValueObject &valobj, Stream &stream,
1071 const TypeSummaryOptions &summary_options) {
1072
1073 bool success;
1074 ValueObjectSP dataobj;
1075 size_t size;
1076 std::tie( success, dataobj, size ) = LibcxxExtractStringViewData(valobj);
1077
1078 if (!success) {
1079 stream << "Summary Unavailable";
1080 return true;
1081 }
1082
1083
1084 return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options,
1085 dataobj, size);
1086}
static llvm::raw_ostream & error(Stream &strm)
static bool formatStringImpl(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token)
Definition: LibCxx.cpp:975
static std::optional< std::pair< uint64_t, ValueObjectSP > > ExtractLibcxxStringInfo(ValueObject &valobj)
Determine the size in bytes of valobj (a libc++ std::string object) and extract its data payload.
Definition: LibCxx.cpp:751
static bool formatStringViewImpl(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token)
Definition: LibCxx.cpp:1030
static bool LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token, ValueObjectSP location_sp, uint64_t size)
Definition: LibCxx.cpp:917
static std::tuple< bool, ValueObjectSP, size_t > LibcxxExtractStringViewData(ValueObject &valobj)
Definition: LibCxx.cpp:1010
LibCppStdFunctionCallableInfo FindLibCppStdFunctionCallableInfo(lldb::ValueObjectSP &valobj_sp)
static CPPLanguageRuntime * Get(Process &process)
std::shared_ptr< TypeSystemType > dyn_cast_or_null()
Return a shared_ptr<TypeSystemType> if dyn_cast succeeds.
Definition: CompilerType.h:65
Generic representation of a type in a programming language.
Definition: CompilerType.h:36
CompilerType GetTypeTemplateArgument(size_t idx, bool expand_pack=false) const
TypeSystemSPWrapper GetTypeSystem() const
Accessors.
std::optional< uint64_t > GetByteSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bytes.
CompilerType GetFieldAtIndex(size_t idx, std::string &name, uint64_t *bit_offset_ptr, uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) const
A uniqued constant string class.
Definition: ConstString.h:40
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:205
A subclass of DataBuffer that stores a data buffer on the heap.
An data extractor class.
Definition: DataExtractor.h:48
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
ExecutionContextScope * GetBestExecutionContextScope() const
Process * GetProcessPtr() const
Returns a pointer to the process object.
const ConstString & GetFilename() const
Filename string const get accessor.
Definition: FileSpec.h:245
A plug-in interface definition class for debugging a process.
Definition: Process.h:339
static lldb::TypeSystemClangSP GetForTarget(Target &target, std::optional< IsolatedASTKind > ast_kind=DefaultAST, bool create_on_demand=true)
Returns the scratch TypeSystemClang for the given target.
An error handling class.
Definition: Status.h:44
bool Success() const
Test for success condition.
Definition: Status.cpp:279
const char * GetData() const
Definition: StreamString.h:43
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
ConstString GetName() const
Definition: Symbol.cpp:544
lldb::TypeSummaryCapping GetCapping() const
Definition: TypeSummary.cpp:33
A TypeSystem implementation based on Clang.
size_t GetNumChildren(uint32_t max=UINT32_MAX)
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
virtual lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name, bool can_create=true)
virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx, bool can_create=true)
lldb::TargetSP GetTargetSP() const
Definition: ValueObject.h:334
virtual lldb::ValueObjectSP GetNonSyntheticValue()
Definition: ValueObject.h:584
size_t GetIndexOfChildWithName(ConstString name) override
Definition: LibCxx.cpp:374
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
Definition: LibCxx.cpp:359
LibCxxMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Definition: LibCxx.cpp:228
Formats libcxx's std::unordered_map iterators.
Definition: LibCxx.h:132
LibCxxUnorderedMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Definition: LibCxx.cpp:396
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
Definition: LibCxx.cpp:517
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
Definition: LibCxx.cpp:574
LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Definition: LibCxx.cpp:562
size_t GetIndexOfChildWithName(ConstString name) override
Definition: LibCxx.cpp:627
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
Definition: LibCxx.cpp:670
size_t GetIndexOfChildWithName(ConstString name) override
Definition: LibCxx.cpp:720
LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Definition: LibCxx.cpp:646
static bool ReadBufferAndDumpToStream(const ReadBufferAndDumpToStreamOptions &options)
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
#define LLDB_INVALID_OFFSET
Definition: lldb-defines.h:93
#define UINT32_MAX
Definition: lldb-defines.h:19
bool FormatStringRef(const llvm::StringRef &format, Stream &s, const SymbolContext *sc, const ExecutionContext *exe_ctx, const Address *addr, ValueObject *valobj, bool function_changed, bool initial_function)
SyntheticChildrenFrontEnd * LibCxxUnorderedMapIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: LibCxx.cpp:538
lldb::ValueObjectSP GetChildMemberWithName(ValueObject &obj, llvm::ArrayRef< ConstString > alternative_names)
Find a child member of obj_sp, trying all alternative names in order.
Definition: LibCxx.cpp:37
SyntheticChildrenFrontEnd * LibcxxUniquePtrSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: LibCxx.cpp:656
bool LibcxxUniquePointerSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:169
bool LibcxxSmartPointerSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:127
bool LibcxxStringViewSummaryProviderASCII(ValueObject &valueObj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition: LibCxx.cpp:1048
bool LibcxxStringViewSummaryProviderUTF16(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition: LibCxx.cpp:1055
SyntheticChildrenFrontEnd * LibCxxVectorIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: LibCxx.cpp:554
bool LibcxxStringViewSummaryProviderUTF32(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition: LibCxx.cpp:1062
bool LibcxxWStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:901
bool LibcxxStringSummaryProviderASCII(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition: LibCxx.cpp:988
bool LibcxxWStringViewSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:1069
lldb::ValueObjectSP GetFirstValueOfLibCXXCompressedPair(ValueObject &pair)
Definition: LibCxx.cpp:49
bool LibcxxStringSummaryProviderUTF16(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition: LibCxx.cpp:995
bool LibcxxFunctionSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:79
bool LibcxxStringSummaryProviderUTF32(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition: LibCxx.cpp:1002
lldb::ValueObjectSP GetSecondValueOfLibCXXCompressedPair(ValueObject &pair)
Definition: LibCxx.cpp:63
bool LibcxxContainerSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:730
SyntheticChildrenFrontEnd * LibcxxSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: LibCxx.cpp:639
SyntheticChildrenFrontEnd * LibCxxMapIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: LibCxx.cpp:389
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
Definition: SBAddress.h:15
@ eBasicTypeUnsignedLongLong
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:467
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:377
std::shared_ptr< lldb_private::TypeSystemClang > TypeSystemClangSP
Definition: lldb-forward.h:454
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
Definition: lldb-forward.h:325
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:432
FileSpec file
The source file, possibly mapped by the target.source-map setting.
Definition: LineEntry.h:140
uint32_t line
The source line number, or zero if there is no line number information.
Definition: LineEntry.h:143
GetValueForExpressionPathOptions & SetSyntheticChildrenTraversal(SyntheticChildrenTraversal traverse)
Definition: ValueObject.h:248
GetValueForExpressionPathOptions & DontCheckDotVsArrowSyntax()
Definition: ValueObject.h:222