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