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"
18#include "lldb/Target/Target.h"
21#include "lldb/Utility/Endian.h"
22#include "lldb/Utility/Status.h"
23#include "lldb/Utility/Stream.h"
26
32#include "lldb/lldb-forward.h"
33#include <optional>
34#include <tuple>
35
36using namespace lldb;
37using namespace lldb_private;
38using namespace lldb_private::formatters;
39
40static void consumeInlineNamespace(llvm::StringRef &name) {
41 // Delete past an inline namespace, if any: __[a-zA-Z0-9_]+::
42 auto scratch = name;
43 if (scratch.consume_front("__") &&
44 std::isalnum(static_cast<unsigned char>(scratch[0]))) {
45 scratch = scratch.drop_while(
46 [](char c) { return std::isalnum(static_cast<unsigned char>(c)); });
47 if (scratch.consume_front("::")) {
48 // Successfully consumed a namespace.
49 name = scratch;
50 }
51 }
52}
53
55 llvm::StringRef type) {
56 llvm::StringRef name = type_name.GetStringRef();
57 // The type name may be prefixed with `std::__<inline-namespace>::`.
58 if (name.consume_front("std::"))
60 return name.consume_front(type) && name.starts_with("<");
61}
62
64 ValueObject &obj, llvm::ArrayRef<ConstString> alternative_names) {
65 for (ConstString name : alternative_names) {
67
68 if (child_sp)
69 return child_sp;
70 }
71 return {};
72}
73
76 ValueObject &pair) {
77 ValueObjectSP value;
78 ValueObjectSP first_child = pair.GetChildAtIndex(0);
79 if (first_child)
80 value = first_child->GetChildMemberWithName("__value_");
81 if (!value) {
82 // pre-c88580c member name
83 value = pair.GetChildMemberWithName("__first_");
84 }
85 return value;
86}
87
90 ValueObject &pair) {
91 ValueObjectSP value;
92 if (pair.GetNumChildrenIgnoringErrors() > 1) {
93 ValueObjectSP second_child = pair.GetChildAtIndex(1);
94 if (second_child) {
95 value = second_child->GetChildMemberWithName("__value_");
96 }
97 }
98 if (!value) {
99 // pre-c88580c member name
100 value = pair.GetChildMemberWithName("__second_");
101 }
102 return value;
103}
104
105std::pair<lldb::ValueObjectSP, bool>
107 ValueObject &obj, llvm::StringRef child_name,
108 llvm::StringRef compressed_pair_name) {
109 auto is_old_compressed_pair = [](ValueObject &pair_obj) -> bool {
110 return isStdTemplate(pair_obj.GetTypeName(), "__compressed_pair");
111 };
112
113 ValueObjectSP node_sp(obj.GetChildMemberWithName(child_name));
114 if (node_sp)
115 return {node_sp, is_old_compressed_pair(*node_sp)};
116
117 // Try the even older __compressed_pair layout.
118
119 assert(!compressed_pair_name.empty());
120
121 node_sp = obj.GetChildMemberWithName(compressed_pair_name);
122
123 // Unrecognized layout (possibly older than LLDB supports).
124 if (!node_sp)
125 return {nullptr, false};
126
127 // Expected old compressed_pair layout, but got something else.
128 if (!is_old_compressed_pair(*node_sp))
129 return {nullptr, false};
130
131 return {node_sp, true};
132}
133
135 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
136
137 ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
138
139 if (!valobj_sp)
140 return false;
141
142 ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
143 Process *process = exe_ctx.GetProcessPtr();
144
145 if (process == nullptr)
146 return false;
147
148 CPPLanguageRuntime *cpp_runtime = CPPLanguageRuntime::Get(*process);
149
150 if (!cpp_runtime)
151 return false;
152
154 cpp_runtime->FindLibCppStdFunctionCallableInfo(valobj_sp);
155
156 switch (callable_info.callable_case) {
158 stream.Printf(" __f_ = %" PRIu64, callable_info.member_f_pointer_value);
159 return false;
160 break;
162 stream.Printf(
163 " Lambda in File %s at Line %u",
165 callable_info.callable_line_entry.line);
166 break;
168 stream.Printf(
169 " Function in File %s at Line %u",
171 callable_info.callable_line_entry.line);
172 break;
174 stream.Printf(" Function = %s ",
175 callable_info.callable_symbol.GetName().GetCString());
176 break;
177 }
178
179 return true;
180}
181
183 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
184 ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
185 if (!valobj_sp)
186 return false;
187
188 ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName("__ptr_"));
189 ValueObjectSP ctrl_sp(valobj_sp->GetChildMemberWithName("__cntrl_"));
190 if (!ctrl_sp || !ptr_sp)
191 return false;
192
193 DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options);
194
195 bool success;
196 uint64_t ctrl_addr = ctrl_sp->GetValueAsUnsigned(0, &success);
197 // Empty control field. We're done.
198 if (!success || ctrl_addr == 0)
199 return true;
200
201 if (auto count_sp = ctrl_sp->GetChildMemberWithName("__shared_owners_")) {
202 bool success;
203 uint64_t count = count_sp->GetValueAsUnsigned(0, &success);
204 if (!success)
205 return false;
206
207 // std::shared_ptr releases the underlying resource when the
208 // __shared_owners_ count hits -1. So `__shared_owners_ == 0` indicates 1
209 // owner. Hence add +1 here.
210 stream.Printf(" strong=%" PRIu64, count + 1);
211 }
212
213 if (auto weak_count_sp =
214 ctrl_sp->GetChildMemberWithName("__shared_weak_owners_")) {
215 bool success;
216 uint64_t count = weak_count_sp->GetValueAsUnsigned(0, &success);
217 if (!success)
218 return false;
219
220 // Unlike __shared_owners_, __shared_weak_owners_ indicates the exact
221 // std::weak_ptr reference count.
222 stream.Printf(" weak=%" PRIu64, count);
223 }
224
225 return true;
226}
227
229 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
230 ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
231 if (!valobj_sp)
232 return false;
233
234 auto [ptr_sp, is_compressed_pair] =
235 GetValueOrOldCompressedPair(*valobj_sp, "__ptr_", "__ptr_");
236 if (!ptr_sp)
237 return false;
238
239 if (is_compressed_pair)
240 ptr_sp = GetFirstValueOfLibCXXCompressedPair(*ptr_sp);
241
242 if (!ptr_sp)
243 return false;
244
245 DumpCxxSmartPtrPointerSummary(stream, *ptr_sp, options);
246
247 return true;
248}
249
250static std::optional<int64_t> LibcxxExtractOrderingValue(ValueObject &valobj) {
251 lldb::ValueObjectSP value_sp = valobj.GetChildMemberWithName("__value_");
252 if (!value_sp)
253 return std::nullopt;
254 bool success;
255 int64_t value = value_sp->GetValueAsSigned(0, &success);
256 if (!success)
257 return std::nullopt;
258 return value;
259}
260
262 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
263 std::optional<int64_t> value = LibcxxExtractOrderingValue(valobj);
264 if (!value)
265 return false;
266 switch (*value) {
267 case -1:
268 stream << "less";
269 break;
270 case 0:
271 stream << "equivalent";
272 break;
273 case 1:
274 stream << "greater";
275 break;
276 case -127:
277 stream << "unordered";
278 break;
279 default:
280 return false;
281 }
282 return true;
283}
284
286 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
287 std::optional<int64_t> value = LibcxxExtractOrderingValue(valobj);
288 if (!value)
289 return false;
290 switch (*value) {
291 case -1:
292 stream << "less";
293 break;
294 case 0:
295 stream << "equivalent";
296 break;
297 case 1:
298 stream << "greater";
299 break;
300 default:
301 return false;
302 }
303 return true;
304}
305
307 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
308 std::optional<int64_t> value = LibcxxExtractOrderingValue(valobj);
309 if (!value)
310 return false;
311 switch (*value) {
312 case -1:
313 stream << "less";
314 break;
315 case 0:
316 stream << "equal";
317 break;
318 case 1:
319 stream << "greater";
320 break;
321 default:
322 return false;
323 }
324 return true;
325}
326
327/*
328 (lldb) fr var ibeg --raw --ptr-depth 1 -T
329 (std::__1::__wrap_iter<int *>) ibeg = {
330 (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
331 (int) *__i = 1
332 }
333 }
334*/
335
339 return (valobj_sp ? new VectorIteratorSyntheticFrontEnd(
340 valobj_sp, {ConstString("__i_"), ConstString("__i")})
341 : nullptr);
342}
343
351
352llvm::Expected<uint32_t> lldb_private::formatters::
354 return (m_cntrl ? 1 : 0);
355}
356
359 uint32_t idx) {
360 if (!m_cntrl || !m_ptr_obj)
361 return lldb::ValueObjectSP();
362
363 ValueObjectSP valobj_sp = m_backend.GetSP();
364 if (!valobj_sp)
365 return lldb::ValueObjectSP();
366
367 if (idx == 0)
368 return m_ptr_obj->GetSP();
369
370 if (idx == 1) {
371 Status status;
372 ValueObjectSP value_sp = m_ptr_obj->Dereference(status);
373 if (status.Success())
374 return value_sp;
375 }
376
377 return lldb::ValueObjectSP();
378}
379
382 m_cntrl = nullptr;
383 m_ptr_obj = nullptr;
384
385 ValueObjectSP valobj_sp = m_backend.GetSP();
386 if (!valobj_sp)
388
389 TargetSP target_sp(valobj_sp->GetTargetSP());
390 if (!target_sp)
392
393 auto ptr_obj_sp = valobj_sp->GetChildMemberWithName("__ptr_");
394 if (!ptr_obj_sp)
396
397 auto cast_ptr_sp = GetDesugaredSmartPointerValue(*ptr_obj_sp, *valobj_sp);
398 if (!cast_ptr_sp)
400
401 m_ptr_obj = cast_ptr_sp->Clone(ConstString("pointer")).get();
402
403 lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName("__cntrl_"));
404
405 m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular
406 // dependency
408}
409
410llvm::Expected<size_t>
413 if (name == "pointer")
414 return 0;
415
416 if (name == "object" || name == "$$dereference$$")
417 return 1;
418
419 return llvm::createStringError("Type has no child named '%s'",
420 name.AsCString());
421}
422
425
429 return (valobj_sp ? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)
430 : nullptr);
431}
432
439
442
446 return (valobj_sp ? new LibcxxUniquePtrSyntheticFrontEnd(valobj_sp)
447 : nullptr);
448}
449
450llvm::Expected<uint32_t> lldb_private::formatters::
452 if (m_value_ptr_sp)
453 return m_deleter_sp ? 2 : 1;
454 return 0;
455}
456
459 uint32_t idx) {
460 if (!m_value_ptr_sp)
461 return lldb::ValueObjectSP();
462
463 if (idx == 0)
464 return m_value_ptr_sp;
465
466 if (idx == 1)
467 return m_deleter_sp;
468
469 if (idx == 2) {
470 Status status;
471 auto value_sp = m_value_ptr_sp->Dereference(status);
472 if (status.Success()) {
473 return value_sp;
474 }
475 }
476
477 return lldb::ValueObjectSP();
478}
479
482 ValueObjectSP valobj_sp = m_backend.GetSP();
483 if (!valobj_sp)
485
486 auto [ptr_sp, is_compressed_pair] =
487 GetValueOrOldCompressedPair(*valobj_sp, "__ptr_", "__ptr_");
488 if (!ptr_sp)
490
491 // Retrieve the actual pointer and the deleter, and clone them to give them
492 // user-friendly names.
493 if (is_compressed_pair) {
494 if (ValueObjectSP value_pointer_sp =
496 m_value_ptr_sp = value_pointer_sp->Clone(ConstString("pointer"));
497
498 if (ValueObjectSP deleter_sp =
500 m_deleter_sp = deleter_sp->Clone(ConstString("deleter"));
501 } else {
502 m_value_ptr_sp = ptr_sp->Clone(ConstString("pointer"));
503
504 if (ValueObjectSP deleter_sp =
505 valobj_sp->GetChildMemberWithName("__deleter_"))
506 if (deleter_sp->GetNumChildrenIgnoringErrors() > 0)
507 m_deleter_sp = deleter_sp->Clone(ConstString("deleter"));
508 }
509
511}
512
513llvm::Expected<size_t>
516 if (name == "pointer")
517 return 0;
518 if (name == "deleter")
519 return 1;
520 if (name == "obj" || name == "object" || name == "$$dereference$$")
521 return 2;
522 return llvm::createStringError("Type has no child named '%s'",
523 name.AsCString());
524}
525
526/// The field layout in a libc++ string (cap, side, data or data, size, cap).
527namespace {
528enum class StringLayout { CSD, DSC };
529}
530
532 auto [valobj_r_sp, is_compressed_pair] =
533 GetValueOrOldCompressedPair(valobj, "__rep_", "__r_");
534 if (!valobj_r_sp)
535 return nullptr;
536
537 if (is_compressed_pair)
538 return GetFirstValueOfLibCXXCompressedPair(*valobj_r_sp);
539
540 return valobj_r_sp;
541}
542
543/// Determine the size in bytes of \p valobj (a libc++ std::string object) and
544/// extract its data payload. Return the size + payload pair.
545// TODO: Support big-endian architectures.
546static std::optional<std::pair<uint64_t, ValueObjectSP>>
548 ValueObjectSP valobj_rep_sp = ExtractLibCxxStringData(valobj);
549 if (!valobj_rep_sp || !valobj_rep_sp->GetError().Success())
550 return {};
551
552 ValueObjectSP l = valobj_rep_sp->GetChildMemberWithName("__l");
553 if (!l)
554 return {};
555
556 auto index_or_err = l->GetIndexOfChildWithName("__data_");
557 if (!index_or_err) {
558 LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), index_or_err.takeError(),
559 "{0}");
560 return {};
561 }
562
563 StringLayout layout =
564 *index_or_err == 0 ? StringLayout::DSC : StringLayout::CSD;
565
566 bool short_mode = false; // this means the string is in short-mode and the
567 // data is stored inline
568 bool using_bitmasks = true; // Whether the class uses bitmasks for the mode
569 // flag (pre-D123580).
570 uint64_t size;
571 uint64_t size_mode_value = 0;
572
573 ValueObjectSP short_sp = valobj_rep_sp->GetChildMemberWithName("__s");
574 if (!short_sp)
575 return {};
576
577 ValueObjectSP is_long = short_sp->GetChildMemberWithName("__is_long_");
578 ValueObjectSP size_sp = short_sp->GetChildMemberWithName("__size_");
579 if (!size_sp)
580 return {};
581
582 if (is_long) {
583 using_bitmasks = false;
584 short_mode = !is_long->GetValueAsUnsigned(/*fail_value=*/0);
585 size = size_sp->GetValueAsUnsigned(/*fail_value=*/0);
586 } else {
587 // The string mode is encoded in the size field.
588 size_mode_value = size_sp->GetValueAsUnsigned(0);
589 uint8_t mode_mask = layout == StringLayout::DSC ? 0x80 : 1;
590 short_mode = (size_mode_value & mode_mask) == 0;
591 }
592
593 if (short_mode) {
594 ValueObjectSP location_sp = short_sp->GetChildMemberWithName("__data_");
595 if (using_bitmasks)
596 size = (layout == StringLayout::DSC) ? size_mode_value
597 : ((size_mode_value >> 1) % 256);
598
599 if (!location_sp)
600 return {};
601
602 // When the small-string optimization takes place, the data must fit in the
603 // inline string buffer (23 bytes on x86_64/Darwin). If it doesn't, it's
604 // likely that the string isn't initialized and we're reading garbage.
605 ExecutionContext exe_ctx(location_sp->GetExecutionContextRef());
606 const std::optional<uint64_t> max_bytes =
607 llvm::expectedToOptional(location_sp->GetCompilerType().GetByteSize(
609 if (!max_bytes || size > *max_bytes)
610 return {};
611
612 return std::make_pair(size, location_sp);
613 }
614
615 // we can use the layout_decider object as the data pointer
616 ValueObjectSP location_sp = l->GetChildMemberWithName("__data_");
617 ValueObjectSP size_vo = l->GetChildMemberWithName("__size_");
618 ValueObjectSP capacity_vo = l->GetChildMemberWithName("__cap_");
619 if (!size_vo || !location_sp || !capacity_vo)
620 return {};
621 size = size_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
622 uint64_t capacity = capacity_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
623 if (!using_bitmasks && layout == StringLayout::CSD)
624 capacity *= 2;
625 if (size == LLDB_INVALID_OFFSET || capacity == LLDB_INVALID_OFFSET ||
626 capacity < size)
627 return {};
628 return std::make_pair(size, location_sp);
629}
630
632 ValueObject &valobj, Stream &stream,
633 const TypeSummaryOptions &summary_options) {
634 auto string_info = ExtractLibcxxStringInfo(valobj);
635 if (!string_info)
636 return false;
637 uint64_t size;
638 ValueObjectSP location_sp;
639 std::tie(size, location_sp) = *string_info;
640
641 auto wchar_t_size = GetWCharByteSize(valobj);
642 if (!wchar_t_size)
643 return false;
644
645 switch (*wchar_t_size) {
646 case 1:
648 stream, summary_options, location_sp, size, "L");
649 case 2:
651 stream, summary_options, location_sp, size, "L");
652 case 4:
654 stream, summary_options, location_sp, size, "L");
655 }
656 return false;
657}
658
659template <StringPrinter::StringElementType element_type>
660static bool
662 const TypeSummaryOptions &summary_options,
663 std::string prefix_token) {
664 auto string_info = ExtractLibcxxStringInfo(valobj);
665 if (!string_info)
666 return false;
667 uint64_t size;
668 ValueObjectSP location_sp;
669 std::tie(size, location_sp) = *string_info;
670
672 stream, summary_options, location_sp, size, prefix_token);
673}
674template <StringPrinter::StringElementType element_type>
675static bool formatStringImpl(ValueObject &valobj, Stream &stream,
676 const TypeSummaryOptions &summary_options,
677 std::string prefix_token) {
678 StreamString scratch_stream;
680 valobj, scratch_stream, summary_options, prefix_token);
681 if (success)
682 stream << scratch_stream.GetData();
683 else
684 stream << "Summary Unavailable";
685 return true;
686}
687
689 ValueObject &valobj, Stream &stream,
690 const TypeSummaryOptions &summary_options) {
692 valobj, stream, summary_options, "");
693}
694
696 ValueObject &valobj, Stream &stream,
697 const TypeSummaryOptions &summary_options) {
699 valobj, stream, summary_options, "u");
700}
701
703 ValueObject &valobj, Stream &stream,
704 const TypeSummaryOptions &summary_options) {
706 valobj, stream, summary_options, "U");
707}
708
709static std::tuple<bool, ValueObjectSP, size_t>
711 auto dataobj = GetChildMemberWithName(
712 valobj, {ConstString("__data_"), ConstString("__data")});
713 auto sizeobj = GetChildMemberWithName(
714 valobj, {ConstString("__size_"), ConstString("__size")});
715 if (!dataobj || !sizeobj)
716 return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
717
718 if (!dataobj->GetError().Success() || !sizeobj->GetError().Success())
719 return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
720
721 bool success{false};
722 uint64_t size = sizeobj->GetValueAsUnsigned(0, &success);
723 if (!success)
724 return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
725
726 return std::make_tuple(true,dataobj,size);
727}
728
729template <StringPrinter::StringElementType element_type>
730static bool formatStringViewImpl(ValueObject &valobj, Stream &stream,
731 const TypeSummaryOptions &summary_options,
732 std::string prefix_token) {
733
734 bool success;
735 ValueObjectSP dataobj;
736 size_t size;
737 std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj);
738
739 if (!success) {
740 stream << "Summary Unavailable";
741 return true;
742 }
743
744 return StringBufferSummaryProvider<element_type>(stream, summary_options,
745 dataobj, size, prefix_token);
746}
747
749 ValueObject &valobj, Stream &stream,
750 const TypeSummaryOptions &summary_options) {
752 valobj, stream, summary_options, "");
753}
754
756 ValueObject &valobj, Stream &stream,
757 const TypeSummaryOptions &summary_options) {
759 valobj, stream, summary_options, "u");
760}
761
763 ValueObject &valobj, Stream &stream,
764 const TypeSummaryOptions &summary_options) {
766 valobj, stream, summary_options, "U");
767}
768
770 ValueObject &valobj, Stream &stream,
771 const TypeSummaryOptions &summary_options) {
772
773 bool success;
774 ValueObjectSP dataobj;
775 size_t size;
776 std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj);
777
778 if (!success) {
779 stream << "Summary Unavailable";
780 return true;
781 }
782
783 auto wchar_t_size = GetWCharByteSize(valobj);
784 if (!wchar_t_size)
785 return false;
786
787 switch (*wchar_t_size) {
788 case 1:
790 stream, summary_options, dataobj, size, "L");
791 case 2:
793 stream, summary_options, dataobj, size, "L");
794 case 4:
796 stream, summary_options, dataobj, size, "L");
797 }
798 return false;
799}
800
801static bool
803 const TypeSummaryOptions &options,
804 const char *fmt) {
805 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__d_");
806 if (!ptr_sp)
807 return false;
808 ptr_sp = ptr_sp->GetChildMemberWithName("__rep_");
809 if (!ptr_sp)
810 return false;
811
812#ifndef _WIN32
813 // The date time in the chrono library is valid in the range
814 // [-32767-01-01T00:00:00Z, 32767-12-31T23:59:59Z]. A 64-bit time_t has a
815 // larger range, the function strftime is not able to format the entire range
816 // of time_t. The exact point has not been investigated; it's limited to
817 // chrono's range.
818 const std::time_t chrono_timestamp_min =
819 -1'096'193'779'200; // -32767-01-01T00:00:00Z
820 const std::time_t chrono_timestamp_max =
821 971'890'963'199; // 32767-12-31T23:59:59Z
822#else
823 const std::time_t chrono_timestamp_min = -43'200; // 1969-12-31T12:00:00Z
824 const std::time_t chrono_timestamp_max =
825 32'536'850'399; // 3001-01-19T21:59:59
826#endif
827
828 const std::time_t seconds = ptr_sp->GetValueAsSigned(0);
829 if (seconds < chrono_timestamp_min || seconds > chrono_timestamp_max)
830 stream.Printf("timestamp=%" PRId64 " s", static_cast<int64_t>(seconds));
831 else {
832 std::array<char, 128> str;
833 std::size_t size =
834 std::strftime(str.data(), str.size(), fmt, gmtime(&seconds));
835 if (size == 0)
836 return false;
837
838 stream.Printf("date/time=%s timestamp=%" PRId64 " s", str.data(),
839 static_cast<int64_t>(seconds));
840 }
841
842 return true;
843}
844
846 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
847 return LibcxxChronoTimePointSecondsSummaryProvider(valobj, stream, options,
848 "%FT%H:%M:%SZ");
849}
850
852 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
853 return LibcxxChronoTimePointSecondsSummaryProvider(valobj, stream, options,
854 "%FT%H:%M:%S");
855}
856
857static bool
859 const TypeSummaryOptions &options,
860 const char *fmt) {
861 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__d_");
862 if (!ptr_sp)
863 return false;
864 ptr_sp = ptr_sp->GetChildMemberWithName("__rep_");
865 if (!ptr_sp)
866 return false;
867
868#ifndef _WIN32
869 // The date time in the chrono library is valid in the range
870 // [-32767-01-01Z, 32767-12-31Z]. A 32-bit time_t has a larger range, the
871 // function strftime is not able to format the entire range of time_t. The
872 // exact point has not been investigated; it's limited to chrono's range.
873 const int chrono_timestamp_min = -12'687'428; // -32767-01-01Z
874 const int chrono_timestamp_max = 11'248'737; // 32767-12-31Z
875#else
876 const int chrono_timestamp_min = 0; // 1970-01-01Z
877 const int chrono_timestamp_max = 376'583; // 3001-01-19Z
878#endif
879
880 const int days = ptr_sp->GetValueAsSigned(0);
881 if (days < chrono_timestamp_min || days > chrono_timestamp_max)
882 stream.Printf("timestamp=%d days", days);
883
884 else {
885 const std::time_t seconds = std::time_t(86400) * days;
886
887 std::array<char, 128> str;
888 std::size_t size =
889 std::strftime(str.data(), str.size(), fmt, gmtime(&seconds));
890 if (size == 0)
891 return false;
892
893 stream.Printf("date=%s timestamp=%d days", str.data(), days);
894 }
895
896 return true;
897}
898
900 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
901 return LibcxxChronoTimepointDaysSummaryProvider(valobj, stream, options,
902 "%FZ");
903}
904
906 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
907 return LibcxxChronoTimepointDaysSummaryProvider(valobj, stream, options,
908 "%F");
909}
910
912 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
913 // FIXME: These are the names used in the C++20 ostream operator. Since LLVM
914 // uses C++17 it's not possible to use the ostream operator directly.
915 static const std::array<std::string_view, 12> months = {
916 "January", "February", "March", "April", "May", "June",
917 "July", "August", "September", "October", "November", "December"};
918
919 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__m_");
920 if (!ptr_sp)
921 return false;
922
923 const unsigned month = ptr_sp->GetValueAsUnsigned(0);
924 if (month >= 1 && month <= 12)
925 stream << "month=" << months[month - 1];
926 else
927 stream.Printf("month=%u", month);
928
929 return true;
930}
931
933 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
934 // FIXME: These are the names used in the C++20 ostream operator. Since LLVM
935 // uses C++17 it's not possible to use the ostream operator directly.
936 static const std::array<std::string_view, 7> weekdays = {
937 "Sunday", "Monday", "Tuesday", "Wednesday",
938 "Thursday", "Friday", "Saturday"};
939
940 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__wd_");
941 if (!ptr_sp)
942 return false;
943
944 const unsigned weekday = ptr_sp->GetValueAsUnsigned(0);
945 if (weekday < 7)
946 stream << "weekday=" << weekdays[weekday];
947 else
948 stream.Printf("weekday=%u", weekday);
949
950 return true;
951}
952
954 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
955 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__y_");
956 if (!ptr_sp)
957 return false;
958 ptr_sp = ptr_sp->GetChildMemberWithName("__y_");
959 if (!ptr_sp)
960 return false;
961 int year = ptr_sp->GetValueAsSigned(0);
962
963 ptr_sp = valobj.GetChildMemberWithName("__m_");
964 if (!ptr_sp)
965 return false;
966 ptr_sp = ptr_sp->GetChildMemberWithName("__m_");
967 if (!ptr_sp)
968 return false;
969 const unsigned month = ptr_sp->GetValueAsUnsigned(0);
970
971 ptr_sp = valobj.GetChildMemberWithName("__d_");
972 if (!ptr_sp)
973 return false;
974 ptr_sp = ptr_sp->GetChildMemberWithName("__d_");
975 if (!ptr_sp)
976 return false;
977 const unsigned day = ptr_sp->GetValueAsUnsigned(0);
978
979 stream << "date=";
980 if (year < 0) {
981 stream << '-';
982 year = -year;
983 }
984 stream.Printf("%04d-%02u-%02u", year, month, day);
985
986 return true;
987}
static bool LibcxxChronoTimepointDaysSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options, const char *fmt)
Definition LibCxx.cpp:858
static ValueObjectSP ExtractLibCxxStringData(ValueObject &valobj)
Definition LibCxx.cpp:531
static bool formatStringImpl(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token)
Definition LibCxx.cpp:675
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:547
static bool formatStringViewImpl(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token)
Definition LibCxx.cpp:730
static std::optional< int64_t > LibcxxExtractOrderingValue(ValueObject &valobj)
Definition LibCxx.cpp:250
static std::tuple< bool, ValueObjectSP, size_t > LibcxxExtractStringViewData(ValueObject &valobj)
Definition LibCxx.cpp:710
static bool LibcxxChronoTimePointSecondsSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options, const char *fmt)
Definition LibCxx.cpp:802
static bool LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token)
Definition LibCxx.cpp:661
static void consumeInlineNamespace(llvm::StringRef &name)
Definition LibCxx.cpp:40
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:392
LibCppStdFunctionCallableInfo FindLibCppStdFunctionCallableInfo(lldb::ValueObjectSP &valobj_sp)
static CPPLanguageRuntime * Get(Process &process)
A uniqued constant string class.
Definition ConstString.h:40
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
const char * GetCString() const
Get the string value as a C string.
"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:251
A plug-in interface definition class for debugging a process.
Definition Process.h:354
An error handling class.
Definition Status.h:118
bool Success() const
Test for success condition.
Definition Status.cpp:304
const char * GetData() const
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:511
SyntheticChildrenFrontEnd(ValueObject &backend)
virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx, bool can_create=true)
virtual lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name, bool can_create=true)
virtual lldb::ValueObjectSP GetNonSyntheticValue()
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:358
llvm::Expected< uint32_t > CalculateNumChildren() override
Definition LibCxx.cpp:353
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
Definition LibCxx.cpp:412
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:381
LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Definition LibCxx.cpp:345
llvm::Expected< uint32_t > CalculateNumChildren() override
Definition LibCxx.cpp:451
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:481
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
Definition LibCxx.cpp:515
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
Definition LibCxx.cpp:458
LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Definition LibCxx.cpp:434
#define LLDB_INVALID_OFFSET
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:63
bool LibcxxChronoSysSecondsSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:845
bool LibcxxChronoMonthSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:911
SyntheticChildrenFrontEnd * LibcxxUniquePtrSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
bool LibcxxUniquePointerSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:228
lldb::ValueObjectSP GetDesugaredSmartPointerValue(ValueObject &ptr, ValueObject &container)
Return the ValueObjectSP of the underlying pointer member whose type is a desugared 'std::shared_ptr:...
Definition Generic.cpp:13
bool LibcxxPartialOrderingSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:261
bool LibcxxSmartPointerSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:182
bool LibcxxStringViewSummaryProviderASCII(ValueObject &valueObj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition LibCxx.cpp:748
bool LibcxxStringViewSummaryProviderUTF16(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition LibCxx.cpp:755
std::optional< uint64_t > GetWCharByteSize(ValueObject &valobj)
SyntheticChildrenFrontEnd * LibCxxVectorIteratorSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
bool LibcxxStringViewSummaryProviderUTF32(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition LibCxx.cpp:762
bool StringBufferSummaryProvider(Stream &stream, const TypeSummaryOptions &summary_options, lldb::ValueObjectSP location_sp, uint64_t size, std::string prefix_token)
Print a summary for a string buffer to stream.
bool LibcxxWeakOrderingSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:285
bool LibcxxChronoYearMonthDaySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:953
bool LibcxxWStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:631
bool LibcxxStringSummaryProviderASCII(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition LibCxx.cpp:688
bool LibcxxChronoLocalSecondsSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:851
bool LibcxxWStringViewSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:769
bool LibcxxChronoWeekdaySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:932
bool isStdTemplate(ConstString type_name, llvm::StringRef type)
Definition LibCxx.cpp:54
lldb::ValueObjectSP GetFirstValueOfLibCXXCompressedPair(ValueObject &pair)
Definition LibCxx.cpp:75
bool LibcxxStringSummaryProviderUTF16(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition LibCxx.cpp:695
bool LibcxxFunctionSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:134
bool LibcxxStringSummaryProviderUTF32(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition LibCxx.cpp:702
std::pair< lldb::ValueObjectSP, bool > GetValueOrOldCompressedPair(ValueObject &obj, llvm::StringRef child_name, llvm::StringRef compressed_pair_name)
Returns the ValueObjectSP of the child of obj.
Definition LibCxx.cpp:106
bool LibcxxStrongOrderingSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:306
bool LibcxxChronoLocalDaysSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:905
lldb::ValueObjectSP GetSecondValueOfLibCXXCompressedPair(ValueObject &pair)
Definition LibCxx.cpp:89
SyntheticChildrenFrontEnd * LibcxxSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
bool LibcxxChronoSysDaysSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:899
void DumpCxxSmartPtrPointerSummary(Stream &stream, ValueObject &ptr, const TypeSummaryOptions &options)
Prints the summary for the pointer value of a C++ std::unique_ptr/stdshared_ptr/stdweak_ptr.
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:332
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
std::shared_ptr< lldb_private::Target > TargetSP
uint32_t line
The source line number, or LLDB_INVALID_LINE_NUMBER if there is no line number information.
Definition LineEntry.h:151
const FileSpec & GetFile() const
Helper to access the file.
Definition LineEntry.h:134