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.GetNumChildrenIgnoringErrors() > 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 -T
207 (std::__1::__wrap_iter<int *>) ibeg = {
208 (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
209 (int) *__i = 1
210 }
211 }
212*/
213
217 return (valobj_sp ? new VectorIteratorSyntheticFrontEnd(
218 valobj_sp, {ConstString("__i_"), ConstString("__i")})
219 : nullptr);
220}
221
224 : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr) {
225 if (valobj_sp)
226 Update();
227}
228
229llvm::Expected<uint32_t> lldb_private::formatters::
231 return (m_cntrl ? 1 : 0);
232}
233
236 uint32_t idx) {
237 if (!m_cntrl)
238 return lldb::ValueObjectSP();
239
240 ValueObjectSP valobj_sp = m_backend.GetSP();
241 if (!valobj_sp)
242 return lldb::ValueObjectSP();
243
244 if (idx == 0)
245 return valobj_sp->GetChildMemberWithName("__ptr_");
246
247 if (idx == 1) {
248 if (auto ptr_sp = valobj_sp->GetChildMemberWithName("__ptr_")) {
249 Status status;
250 auto value_type_sp =
251 valobj_sp->GetCompilerType()
252 .GetTypeTemplateArgument(0).GetPointerType();
253 ValueObjectSP cast_ptr_sp = ptr_sp->Cast(value_type_sp);
254 ValueObjectSP value_sp = cast_ptr_sp->Dereference(status);
255 if (status.Success()) {
256 return value_sp;
257 }
258 }
259 }
260
261 return lldb::ValueObjectSP();
262}
263
266 m_cntrl = nullptr;
267
268 ValueObjectSP valobj_sp = m_backend.GetSP();
269 if (!valobj_sp)
271
272 TargetSP target_sp(valobj_sp->GetTargetSP());
273 if (!target_sp)
275
276 lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName("__cntrl_"));
277
278 m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular
279 // dependency
281}
282
285 return true;
286}
287
290 if (name == "__ptr_")
291 return 0;
292 if (name == "$$dereference$$")
293 return 1;
294 return UINT32_MAX;
295}
296
299
303 return (valobj_sp ? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)
304 : nullptr);
305}
306
309 : SyntheticChildrenFrontEnd(*valobj_sp) {
310 if (valobj_sp)
311 Update();
312}
313
316
320 return (valobj_sp ? new LibcxxUniquePtrSyntheticFrontEnd(valobj_sp)
321 : nullptr);
322}
323
324llvm::Expected<uint32_t> lldb_private::formatters::
326 if (m_value_ptr_sp)
327 return m_deleter_sp ? 2 : 1;
328 return 0;
329}
330
333 uint32_t idx) {
334 if (!m_value_ptr_sp)
335 return lldb::ValueObjectSP();
336
337 if (idx == 0)
338 return m_value_ptr_sp;
339
340 if (idx == 1)
341 return m_deleter_sp;
342
343 if (idx == 2) {
344 Status status;
345 auto value_sp = m_value_ptr_sp->Dereference(status);
346 if (status.Success()) {
347 return value_sp;
348 }
349 }
350
351 return lldb::ValueObjectSP();
352}
353
356 ValueObjectSP valobj_sp = m_backend.GetSP();
357 if (!valobj_sp)
359
360 ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_"));
361 if (!ptr_sp)
363
364 // Retrieve the actual pointer and the deleter, and clone them to give them
365 // user-friendly names.
366 ValueObjectSP value_pointer_sp = GetFirstValueOfLibCXXCompressedPair(*ptr_sp);
367 if (value_pointer_sp)
368 m_value_ptr_sp = value_pointer_sp->Clone(ConstString("pointer"));
369
371 if (deleter_sp)
372 m_deleter_sp = deleter_sp->Clone(ConstString("deleter"));
373
375}
376
379 return true;
380}
381
384 if (name == "pointer")
385 return 0;
386 if (name == "deleter")
387 return 1;
388 if (name == "$$dereference$$")
389 return 2;
390 return UINT32_MAX;
391}
392
394 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
395 if (valobj.IsPointerType()) {
396 uint64_t value = valobj.GetValueAsUnsigned(0);
397 if (!value)
398 return false;
399 stream.Printf("0x%016" PRIx64 " ", value);
400 }
401 return FormatEntity::FormatStringRef("size=${svar%#}", stream, nullptr,
402 nullptr, nullptr, &valobj, false, false);
403}
404
405/// The field layout in a libc++ string (cap, side, data or data, size, cap).
406namespace {
407enum class StringLayout { CSD, DSC };
408}
409
410/// Determine the size in bytes of \p valobj (a libc++ std::string object) and
411/// extract its data payload. Return the size + payload pair.
412// TODO: Support big-endian architectures.
413static std::optional<std::pair<uint64_t, ValueObjectSP>>
415 ValueObjectSP valobj_r_sp = valobj.GetChildMemberWithName("__r_");
416 if (!valobj_r_sp || !valobj_r_sp->GetError().Success())
417 return {};
418
419 // __r_ is a compressed_pair of the actual data and the allocator. The data we
420 // want is in the first base class.
421 ValueObjectSP valobj_r_base_sp = valobj_r_sp->GetChildAtIndex(0);
422 if (!valobj_r_base_sp)
423 return {};
424
425 ValueObjectSP valobj_rep_sp =
426 valobj_r_base_sp->GetChildMemberWithName("__value_");
427 if (!valobj_rep_sp)
428 return {};
429
430 ValueObjectSP l = valobj_rep_sp->GetChildMemberWithName("__l");
431 if (!l)
432 return {};
433
434 StringLayout layout = l->GetIndexOfChildWithName("__data_") == 0
435 ? StringLayout::DSC
436 : StringLayout::CSD;
437
438 bool short_mode = false; // this means the string is in short-mode and the
439 // data is stored inline
440 bool using_bitmasks = true; // Whether the class uses bitmasks for the mode
441 // flag (pre-D123580).
442 uint64_t size;
443 uint64_t size_mode_value = 0;
444
445 ValueObjectSP short_sp = valobj_rep_sp->GetChildMemberWithName("__s");
446 if (!short_sp)
447 return {};
448
449 ValueObjectSP is_long = short_sp->GetChildMemberWithName("__is_long_");
450 ValueObjectSP size_sp = short_sp->GetChildMemberWithName("__size_");
451 if (!size_sp)
452 return {};
453
454 if (is_long) {
455 using_bitmasks = false;
456 short_mode = !is_long->GetValueAsUnsigned(/*fail_value=*/0);
457 size = size_sp->GetValueAsUnsigned(/*fail_value=*/0);
458 } else {
459 // The string mode is encoded in the size field.
460 size_mode_value = size_sp->GetValueAsUnsigned(0);
461 uint8_t mode_mask = layout == StringLayout::DSC ? 0x80 : 1;
462 short_mode = (size_mode_value & mode_mask) == 0;
463 }
464
465 if (short_mode) {
466 ValueObjectSP location_sp = short_sp->GetChildMemberWithName("__data_");
467 if (using_bitmasks)
468 size = (layout == StringLayout::DSC) ? size_mode_value
469 : ((size_mode_value >> 1) % 256);
470
471 if (!location_sp)
472 return {};
473
474 // When the small-string optimization takes place, the data must fit in the
475 // inline string buffer (23 bytes on x86_64/Darwin). If it doesn't, it's
476 // likely that the string isn't initialized and we're reading garbage.
477 ExecutionContext exe_ctx(location_sp->GetExecutionContextRef());
478 const std::optional<uint64_t> max_bytes =
479 location_sp->GetCompilerType().GetByteSize(
481 if (!max_bytes || size > *max_bytes)
482 return {};
483
484 return std::make_pair(size, location_sp);
485 }
486
487 // we can use the layout_decider object as the data pointer
488 ValueObjectSP location_sp = l->GetChildMemberWithName("__data_");
489 ValueObjectSP size_vo = l->GetChildMemberWithName("__size_");
490 ValueObjectSP capacity_vo = l->GetChildMemberWithName("__cap_");
491 if (!size_vo || !location_sp || !capacity_vo)
492 return {};
493 size = size_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
494 uint64_t capacity = capacity_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
495 if (!using_bitmasks && layout == StringLayout::CSD)
496 capacity *= 2;
497 if (size == LLDB_INVALID_OFFSET || capacity == LLDB_INVALID_OFFSET ||
498 capacity < size)
499 return {};
500 return std::make_pair(size, location_sp);
501}
502
503static bool
505 const TypeSummaryOptions &summary_options,
506 ValueObjectSP location_sp, size_t size) {
507 if (size == 0) {
508 stream.Printf("L\"\"");
509 return true;
510 }
511 if (!location_sp)
512 return false;
513
515 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
516 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
517 if (size > max_size) {
518 size = max_size;
519 options.SetIsTruncated(true);
520 }
521 }
522
523 DataExtractor extractor;
524 const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
525 if (bytes_read < size)
526 return false;
527
528 // std::wstring::size() is measured in 'characters', not bytes
529 TypeSystemClangSP scratch_ts_sp =
531 if (!scratch_ts_sp)
532 return false;
533
534 auto wchar_t_size =
535 scratch_ts_sp->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr);
536 if (!wchar_t_size)
537 return false;
538
539 options.SetData(std::move(extractor));
540 options.SetStream(&stream);
541 options.SetPrefixToken("L");
542 options.SetQuote('"');
543 options.SetSourceSize(size);
544 options.SetBinaryZeroIsTerminator(false);
545
546 switch (*wchar_t_size) {
547 case 1:
549 lldb_private::formatters::StringPrinter::StringElementType::UTF8>(
550 options);
551 break;
552
553 case 2:
555 lldb_private::formatters::StringPrinter::StringElementType::UTF16>(
556 options);
557 break;
558
559 case 4:
561 lldb_private::formatters::StringPrinter::StringElementType::UTF32>(
562 options);
563 }
564 return false;
565}
566
568 ValueObject &valobj, Stream &stream,
569 const TypeSummaryOptions &summary_options) {
570 auto string_info = ExtractLibcxxStringInfo(valobj);
571 if (!string_info)
572 return false;
573 uint64_t size;
574 ValueObjectSP location_sp;
575 std::tie(size, location_sp) = *string_info;
576
577 return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options,
578 location_sp, size);
579}
580
581template <StringPrinter::StringElementType element_type>
582static bool
584 const TypeSummaryOptions &summary_options,
585 std::string prefix_token, ValueObjectSP location_sp,
586 uint64_t size) {
587
588 if (size == 0) {
589 stream.Printf("\"\"");
590 return true;
591 }
592
593 if (!location_sp)
594 return false;
595
597
598 if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) {
599 const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
600 if (size > max_size) {
601 size = max_size;
602 options.SetIsTruncated(true);
603 }
604 }
605
606 {
607 DataExtractor extractor;
608 const size_t bytes_read = location_sp->GetPointeeData(extractor, 0, size);
609 if (bytes_read < size)
610 return false;
611
612 options.SetData(std::move(extractor));
613 }
614 options.SetStream(&stream);
615 if (prefix_token.empty())
616 options.SetPrefixToken(nullptr);
617 else
618 options.SetPrefixToken(prefix_token);
619 options.SetQuote('"');
620 options.SetSourceSize(size);
621 options.SetBinaryZeroIsTerminator(false);
622 return StringPrinter::ReadBufferAndDumpToStream<element_type>(options);
623}
624
625template <StringPrinter::StringElementType element_type>
626static bool
628 const TypeSummaryOptions &summary_options,
629 std::string prefix_token) {
630 auto string_info = ExtractLibcxxStringInfo(valobj);
631 if (!string_info)
632 return false;
633 uint64_t size;
634 ValueObjectSP location_sp;
635 std::tie(size, location_sp) = *string_info;
636
637 return LibcxxStringSummaryProvider<element_type>(
638 valobj, stream, summary_options, prefix_token, location_sp, size);
639}
640template <StringPrinter::StringElementType element_type>
641static bool formatStringImpl(ValueObject &valobj, Stream &stream,
642 const TypeSummaryOptions &summary_options,
643 std::string prefix_token) {
644 StreamString scratch_stream;
645 const bool success = LibcxxStringSummaryProvider<element_type>(
646 valobj, scratch_stream, summary_options, prefix_token);
647 if (success)
648 stream << scratch_stream.GetData();
649 else
650 stream << "Summary Unavailable";
651 return true;
652}
653
655 ValueObject &valobj, Stream &stream,
656 const TypeSummaryOptions &summary_options) {
657 return formatStringImpl<StringPrinter::StringElementType::ASCII>(
658 valobj, stream, summary_options, "");
659}
660
662 ValueObject &valobj, Stream &stream,
663 const TypeSummaryOptions &summary_options) {
664 return formatStringImpl<StringPrinter::StringElementType::UTF16>(
665 valobj, stream, summary_options, "u");
666}
667
669 ValueObject &valobj, Stream &stream,
670 const TypeSummaryOptions &summary_options) {
671 return formatStringImpl<StringPrinter::StringElementType::UTF32>(
672 valobj, stream, summary_options, "U");
673}
674
675static std::tuple<bool, ValueObjectSP, size_t>
677 auto dataobj = GetChildMemberWithName(
678 valobj, {ConstString("__data_"), ConstString("__data")});
679 auto sizeobj = GetChildMemberWithName(
680 valobj, {ConstString("__size_"), ConstString("__size")});
681 if (!dataobj || !sizeobj)
682 return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
683
684 if (!dataobj->GetError().Success() || !sizeobj->GetError().Success())
685 return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
686
687 bool success{false};
688 uint64_t size = sizeobj->GetValueAsUnsigned(0, &success);
689 if (!success)
690 return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
691
692 return std::make_tuple(true,dataobj,size);
693}
694
695template <StringPrinter::StringElementType element_type>
696static bool formatStringViewImpl(ValueObject &valobj, Stream &stream,
697 const TypeSummaryOptions &summary_options,
698 std::string prefix_token) {
699
700 bool success;
701 ValueObjectSP dataobj;
702 size_t size;
703 std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj);
704
705 if (!success) {
706 stream << "Summary Unavailable";
707 return true;
708 }
709
710 return LibcxxStringSummaryProvider<element_type>(
711 valobj, stream, summary_options, prefix_token, dataobj, size);
712}
713
715 ValueObject &valobj, Stream &stream,
716 const TypeSummaryOptions &summary_options) {
717 return formatStringViewImpl<StringPrinter::StringElementType::ASCII>(
718 valobj, stream, summary_options, "");
719}
720
722 ValueObject &valobj, Stream &stream,
723 const TypeSummaryOptions &summary_options) {
724 return formatStringViewImpl<StringPrinter::StringElementType::UTF16>(
725 valobj, stream, summary_options, "u");
726}
727
729 ValueObject &valobj, Stream &stream,
730 const TypeSummaryOptions &summary_options) {
731 return formatStringViewImpl<StringPrinter::StringElementType::UTF32>(
732 valobj, stream, summary_options, "U");
733}
734
736 ValueObject &valobj, Stream &stream,
737 const TypeSummaryOptions &summary_options) {
738
739 bool success;
740 ValueObjectSP dataobj;
741 size_t size;
742 std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj);
743
744 if (!success) {
745 stream << "Summary Unavailable";
746 return true;
747 }
748
749 return ::LibcxxWStringSummaryProvider(valobj, stream, summary_options,
750 dataobj, size);
751}
752
753static bool
755 const TypeSummaryOptions &options,
756 const char *fmt) {
757 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__d_");
758 if (!ptr_sp)
759 return false;
760 ptr_sp = ptr_sp->GetChildMemberWithName("__rep_");
761 if (!ptr_sp)
762 return false;
763
764#ifndef _WIN32
765 // The date time in the chrono library is valid in the range
766 // [-32767-01-01T00:00:00Z, 32767-12-31T23:59:59Z]. A 64-bit time_t has a
767 // larger range, the function strftime is not able to format the entire range
768 // of time_t. The exact point has not been investigated; it's limited to
769 // chrono's range.
770 const std::time_t chrono_timestamp_min =
771 -1'096'193'779'200; // -32767-01-01T00:00:00Z
772 const std::time_t chrono_timestamp_max =
773 971'890'963'199; // 32767-12-31T23:59:59Z
774#else
775 const std::time_t chrono_timestamp_min = -43'200; // 1969-12-31T12:00:00Z
776 const std::time_t chrono_timestamp_max =
777 32'536'850'399; // 3001-01-19T21:59:59
778#endif
779
780 const std::time_t seconds = ptr_sp->GetValueAsSigned(0);
781 if (seconds < chrono_timestamp_min || seconds > chrono_timestamp_max)
782 stream.Printf("timestamp=%" PRId64 " s", static_cast<int64_t>(seconds));
783 else {
784 std::array<char, 128> str;
785 std::size_t size =
786 std::strftime(str.data(), str.size(), fmt, gmtime(&seconds));
787 if (size == 0)
788 return false;
789
790 stream.Printf("date/time=%s timestamp=%" PRId64 " s", str.data(),
791 static_cast<int64_t>(seconds));
792 }
793
794 return true;
795}
796
798 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
799 return LibcxxChronoTimePointSecondsSummaryProvider(valobj, stream, options,
800 "%FT%H:%M:%SZ");
801}
802
804 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
805 return LibcxxChronoTimePointSecondsSummaryProvider(valobj, stream, options,
806 "%FT%H:%M:%S");
807}
808
809static bool
811 const TypeSummaryOptions &options,
812 const char *fmt) {
813 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__d_");
814 if (!ptr_sp)
815 return false;
816 ptr_sp = ptr_sp->GetChildMemberWithName("__rep_");
817 if (!ptr_sp)
818 return false;
819
820#ifndef _WIN32
821 // The date time in the chrono library is valid in the range
822 // [-32767-01-01Z, 32767-12-31Z]. A 32-bit time_t has a larger range, the
823 // function strftime is not able to format the entire range of time_t. The
824 // exact point has not been investigated; it's limited to chrono's range.
825 const int chrono_timestamp_min = -12'687'428; // -32767-01-01Z
826 const int chrono_timestamp_max = 11'248'737; // 32767-12-31Z
827#else
828 const int chrono_timestamp_min = 0; // 1970-01-01Z
829 const int chrono_timestamp_max = 376'583; // 3001-01-19Z
830#endif
831
832 const int days = ptr_sp->GetValueAsSigned(0);
833 if (days < chrono_timestamp_min || days > chrono_timestamp_max)
834 stream.Printf("timestamp=%d days", days);
835
836 else {
837 const std::time_t seconds = std::time_t(86400) * days;
838
839 std::array<char, 128> str;
840 std::size_t size =
841 std::strftime(str.data(), str.size(), fmt, gmtime(&seconds));
842 if (size == 0)
843 return false;
844
845 stream.Printf("date=%s timestamp=%d days", str.data(), days);
846 }
847
848 return true;
849}
850
852 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
853 return LibcxxChronoTimepointDaysSummaryProvider(valobj, stream, options,
854 "%FZ");
855}
856
858 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
859 return LibcxxChronoTimepointDaysSummaryProvider(valobj, stream, options,
860 "%F");
861}
862
864 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
865 // FIXME: These are the names used in the C++20 ostream operator. Since LLVM
866 // uses C++17 it's not possible to use the ostream operator directly.
867 static const std::array<std::string_view, 12> months = {
868 "January", "February", "March", "April", "May", "June",
869 "July", "August", "September", "October", "November", "December"};
870
871 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__m_");
872 if (!ptr_sp)
873 return false;
874
875 const unsigned month = ptr_sp->GetValueAsUnsigned(0);
876 if (month >= 1 && month <= 12)
877 stream << "month=" << months[month - 1];
878 else
879 stream.Printf("month=%u", month);
880
881 return true;
882}
883
885 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
886 // FIXME: These are the names used in the C++20 ostream operator. Since LLVM
887 // uses C++17 it's not possible to use the ostream operator directly.
888 static const std::array<std::string_view, 7> weekdays = {
889 "Sunday", "Monday", "Tuesday", "Wednesday",
890 "Thursday", "Friday", "Saturday"};
891
892 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__wd_");
893 if (!ptr_sp)
894 return false;
895
896 const unsigned weekday = ptr_sp->GetValueAsUnsigned(0);
897 if (weekday < 7)
898 stream << "weekday=" << weekdays[weekday];
899 else
900 stream.Printf("weekday=%u", weekday);
901
902 return true;
903}
904
906 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
907 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__y_");
908 if (!ptr_sp)
909 return false;
910 ptr_sp = ptr_sp->GetChildMemberWithName("__y_");
911 if (!ptr_sp)
912 return false;
913 int year = ptr_sp->GetValueAsSigned(0);
914
915 ptr_sp = valobj.GetChildMemberWithName("__m_");
916 if (!ptr_sp)
917 return false;
918 ptr_sp = ptr_sp->GetChildMemberWithName("__m_");
919 if (!ptr_sp)
920 return false;
921 const unsigned month = ptr_sp->GetValueAsUnsigned(0);
922
923 ptr_sp = valobj.GetChildMemberWithName("__d_");
924 if (!ptr_sp)
925 return false;
926 ptr_sp = ptr_sp->GetChildMemberWithName("__d_");
927 if (!ptr_sp)
928 return false;
929 const unsigned day = ptr_sp->GetValueAsUnsigned(0);
930
931 stream << "date=";
932 if (year < 0) {
933 stream << '-';
934 year = -year;
935 }
936 stream.Printf("%04d-%02u-%02u", year, month, day);
937
938 return true;
939}
static llvm::raw_ostream & error(Stream &strm)
static bool LibcxxChronoTimepointDaysSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options, const char *fmt)
Definition: LibCxx.cpp:810
static bool formatStringImpl(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token)
Definition: LibCxx.cpp:641
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:414
static bool formatStringViewImpl(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token)
Definition: LibCxx.cpp:696
static bool LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token, ValueObjectSP location_sp, uint64_t size)
Definition: LibCxx.cpp:583
static std::tuple< bool, ValueObjectSP, size_t > LibcxxExtractStringViewData(ValueObject &valobj)
Definition: LibCxx.cpp:676
static bool LibcxxChronoTimePointSecondsSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options, const char *fmt)
Definition: LibCxx.cpp:754
LibCppStdFunctionCallableInfo FindLibCppStdFunctionCallableInfo(lldb::ValueObjectSP &valobj_sp)
static CPPLanguageRuntime * Get(Process &process)
A uniqued constant string class.
Definition: ConstString.h:40
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:216
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:240
A plug-in interface definition class for debugging a process.
Definition: Process.h:341
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:278
const char * GetData() const
Definition: StreamString.h:45
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:134
ConstString GetName() const
Definition: Symbol.cpp:548
lldb::TypeSummaryCapping GetCapping() const
Definition: TypeSummary.cpp:33
virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx, bool can_create=true)
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
virtual lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name, bool can_create=true)
lldb::TargetSP GetTargetSP() const
Definition: ValueObject.h:334
virtual lldb::ValueObjectSP GetNonSyntheticValue()
Definition: ValueObject.h:606
uint32_t GetNumChildrenIgnoringErrors(uint32_t max=UINT32_MAX)
Like GetNumChildren but returns 0 on error.
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
Definition: LibCxx.cpp:235
llvm::Expected< uint32_t > CalculateNumChildren() override
Definition: LibCxx.cpp:230
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
Definition: LibCxx.cpp:265
LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Definition: LibCxx.cpp:223
size_t GetIndexOfChildWithName(ConstString name) override
Definition: LibCxx.cpp:289
llvm::Expected< uint32_t > CalculateNumChildren() override
Definition: LibCxx.cpp:325
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
Definition: LibCxx.cpp:355
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
Definition: LibCxx.cpp:332
size_t GetIndexOfChildWithName(ConstString name) override
Definition: LibCxx.cpp:383
LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Definition: LibCxx.cpp:308
static bool ReadBufferAndDumpToStream(const ReadBufferAndDumpToStreamOptions &options)
#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)
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
bool LibcxxChronoSysSecondsSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:797
bool LibcxxChronoMonthSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:863
SyntheticChildrenFrontEnd * LibcxxUniquePtrSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: LibCxx.cpp:318
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:714
bool LibcxxStringViewSummaryProviderUTF16(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition: LibCxx.cpp:721
SyntheticChildrenFrontEnd * LibCxxVectorIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: LibCxx.cpp:215
bool LibcxxStringViewSummaryProviderUTF32(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition: LibCxx.cpp:728
bool LibcxxChronoYearMonthDaySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:905
bool LibcxxWStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:567
bool LibcxxStringSummaryProviderASCII(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition: LibCxx.cpp:654
bool LibcxxChronoLocalSecondsSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:803
bool LibcxxWStringViewSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:735
bool LibcxxChronoWeekdaySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:884
lldb::ValueObjectSP GetFirstValueOfLibCXXCompressedPair(ValueObject &pair)
Definition: LibCxx.cpp:49
bool LibcxxStringSummaryProviderUTF16(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition: LibCxx.cpp:661
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:668
bool LibcxxChronoLocalDaysSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:857
lldb::ValueObjectSP GetSecondValueOfLibCXXCompressedPair(ValueObject &pair)
Definition: LibCxx.cpp:63
bool LibcxxContainerSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:393
SyntheticChildrenFrontEnd * LibcxxSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
Definition: LibCxx.cpp:301
bool LibcxxChronoSysDaysSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition: LibCxx.cpp:851
A class that represents a running process on the host machine.
Definition: SBAddress.h:15
ChildCacheState
Specifies if children need to be re-computed after a call to SyntheticChildrenFrontEnd::Update.
@ eRefetch
Children need to be recomputed dynamically.
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:480
std::shared_ptr< lldb_private::TypeSystemClang > TypeSystemClangSP
Definition: lldb-forward.h:466
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:444
uint32_t line
The source line number, or LLDB_INVALID_LINE_NUMBER if there is no line number information.
Definition: LineEntry.h:147
const FileSpec & GetFile() const
Helper to access the file.
Definition: LineEntry.h:134