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
15#include "lldb/Core/Debugger.h"
22#include "lldb/Target/Target.h"
25#include "lldb/Utility/Endian.h"
26#include "lldb/Utility/Status.h"
27#include "lldb/Utility/Stream.h"
31#include "lldb/lldb-forward.h"
32#include "llvm/Support/ErrorExtras.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::createStringErrorV("type has no child named '{0}'", name);
420}
421
424
428 return (valobj_sp ? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)
429 : nullptr);
430}
431
438
441
445 return (valobj_sp ? new LibcxxUniquePtrSyntheticFrontEnd(valobj_sp)
446 : nullptr);
447}
448
449llvm::Expected<uint32_t> lldb_private::formatters::
451 if (m_value_ptr_sp)
452 return m_deleter_sp ? 2 : 1;
453 return 0;
454}
455
458 uint32_t idx) {
459 if (!m_value_ptr_sp)
460 return lldb::ValueObjectSP();
461
462 if (idx == 0)
463 return m_value_ptr_sp;
464
465 if (idx == 1)
466 return m_deleter_sp;
467
468 if (idx == 2) {
469 Status status;
470 auto value_sp = m_value_ptr_sp->Dereference(status);
471 if (status.Success()) {
472 return value_sp;
473 }
474 }
475
476 return lldb::ValueObjectSP();
477}
478
481 ValueObjectSP valobj_sp = m_backend.GetSP();
482 if (!valobj_sp)
484
485 auto [ptr_sp, is_compressed_pair] =
486 GetValueOrOldCompressedPair(*valobj_sp, "__ptr_", "__ptr_");
487 if (!ptr_sp)
489
490 // Retrieve the actual pointer and the deleter, and clone them to give them
491 // user-friendly names.
492 if (is_compressed_pair) {
493 if (ValueObjectSP value_pointer_sp =
495 m_value_ptr_sp = value_pointer_sp->Clone(ConstString("pointer"));
496
497 if (ValueObjectSP deleter_sp =
499 m_deleter_sp = deleter_sp->Clone(ConstString("deleter"));
500 } else {
501 m_value_ptr_sp = ptr_sp->Clone(ConstString("pointer"));
502
503 if (ValueObjectSP deleter_sp =
504 valobj_sp->GetChildMemberWithName("__deleter_"))
505 if (deleter_sp->GetNumChildrenIgnoringErrors() > 0)
506 m_deleter_sp = deleter_sp->Clone(ConstString("deleter"));
507 }
508
510}
511
512llvm::Expected<size_t>
515 if (name == "pointer")
516 return 0;
517 if (name == "deleter")
518 return 1;
519 if (name == "obj" || name == "object" || name == "$$dereference$$")
520 return 2;
521 return llvm::createStringErrorV("type has no child named '{0}'", name);
522}
523
524/// The field layout in a libc++ string (cap, side, data or data, size, cap).
525namespace {
526enum class StringLayout { CSD, DSC };
527}
528
530 auto [valobj_r_sp, is_compressed_pair] =
531 GetValueOrOldCompressedPair(valobj, "__rep_", "__r_");
532 if (!valobj_r_sp)
533 return nullptr;
534
535 if (is_compressed_pair)
536 return GetFirstValueOfLibCXXCompressedPair(*valobj_r_sp);
537
538 return valobj_r_sp;
539}
540
541/// Determine the size in bytes of \p valobj (a libc++ std::string object) and
542/// extract its data payload. Return the size + payload pair.
543// TODO: Support big-endian architectures.
544static std::optional<std::pair<uint64_t, ValueObjectSP>>
546 ValueObjectSP valobj_rep_sp = ExtractLibCxxStringData(valobj);
547 if (!valobj_rep_sp || !valobj_rep_sp->GetError().Success())
548 return {};
549
550 ValueObjectSP l = valobj_rep_sp->GetChildMemberWithName("__l");
551 if (!l)
552 return {};
553
554 auto index_or_err = l->GetIndexOfChildWithName("__data_");
555 if (!index_or_err) {
556 LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), index_or_err.takeError(),
557 "{0}");
558 return {};
559 }
560
561 StringLayout layout =
562 *index_or_err == 0 ? StringLayout::DSC : StringLayout::CSD;
563
564 bool short_mode = false; // this means the string is in short-mode and the
565 // data is stored inline
566 bool using_bitmasks = true; // Whether the class uses bitmasks for the mode
567 // flag (pre-D123580).
568 uint64_t size;
569 uint64_t size_mode_value = 0;
570
571 ValueObjectSP short_sp = valobj_rep_sp->GetChildMemberWithName("__s");
572 if (!short_sp)
573 return {};
574
575 ValueObjectSP is_long = short_sp->GetChildMemberWithName("__is_long_");
576 ValueObjectSP size_sp = short_sp->GetChildMemberWithName("__size_");
577 if (!size_sp)
578 return {};
579
580 if (is_long) {
581 using_bitmasks = false;
582 short_mode = !is_long->GetValueAsUnsigned(/*fail_value=*/0);
583 size = size_sp->GetValueAsUnsigned(/*fail_value=*/0);
584 } else {
585 // The string mode is encoded in the size field.
586 size_mode_value = size_sp->GetValueAsUnsigned(0);
587 uint8_t mode_mask = layout == StringLayout::DSC ? 0x80 : 1;
588 short_mode = (size_mode_value & mode_mask) == 0;
589 }
590
591 if (short_mode) {
592 ValueObjectSP location_sp = short_sp->GetChildMemberWithName("__data_");
593 if (using_bitmasks)
594 size = (layout == StringLayout::DSC) ? size_mode_value
595 : ((size_mode_value >> 1) % 256);
596
597 if (!location_sp)
598 return {};
599
600 // When the small-string optimization takes place, the data must fit in the
601 // inline string buffer (23 bytes on x86_64/Darwin). If it doesn't, it's
602 // likely that the string isn't initialized and we're reading garbage.
603 ExecutionContext exe_ctx(location_sp->GetExecutionContextRef());
604 const std::optional<uint64_t> max_bytes =
605 llvm::expectedToOptional(location_sp->GetCompilerType().GetByteSize(
607 if (!max_bytes || size > *max_bytes)
608 return {};
609
610 return std::make_pair(size, location_sp);
611 }
612
613 // we can use the layout_decider object as the data pointer
614 ValueObjectSP location_sp = l->GetChildMemberWithName("__data_");
615 ValueObjectSP size_vo = l->GetChildMemberWithName("__size_");
616 ValueObjectSP capacity_vo = l->GetChildMemberWithName("__cap_");
617 if (!size_vo || !location_sp || !capacity_vo)
618 return {};
619 size = size_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
620 uint64_t capacity = capacity_vo->GetValueAsUnsigned(LLDB_INVALID_OFFSET);
621 if (!using_bitmasks && layout == StringLayout::CSD)
622 capacity *= 2;
623 if (size == LLDB_INVALID_OFFSET || capacity == LLDB_INVALID_OFFSET ||
624 capacity < size)
625 return {};
626 return std::make_pair(size, location_sp);
627}
628
630 ValueObject &valobj, Stream &stream,
631 const TypeSummaryOptions &summary_options) {
632 auto string_info = ExtractLibcxxStringInfo(valobj);
633 if (!string_info)
634 return false;
635 uint64_t size;
636 ValueObjectSP location_sp;
637 std::tie(size, location_sp) = *string_info;
638
639 auto wchar_t_size = GetWCharByteSize(valobj);
640 if (!wchar_t_size)
641 return false;
642
643 switch (*wchar_t_size) {
644 case 1:
646 stream, summary_options, location_sp, size, "L");
647 case 2:
649 stream, summary_options, location_sp, size, "L");
650 case 4:
652 stream, summary_options, location_sp, size, "L");
653 }
654 return false;
655}
656
657template <StringPrinter::StringElementType element_type>
658static bool
660 const TypeSummaryOptions &summary_options,
661 std::string prefix_token) {
662 auto string_info = ExtractLibcxxStringInfo(valobj);
663 if (!string_info)
664 return false;
665 uint64_t size;
666 ValueObjectSP location_sp;
667 std::tie(size, location_sp) = *string_info;
668
670 stream, summary_options, location_sp, size, prefix_token);
671}
672template <StringPrinter::StringElementType element_type>
673static bool formatStringImpl(ValueObject &valobj, Stream &stream,
674 const TypeSummaryOptions &summary_options,
675 std::string prefix_token) {
676 StreamString scratch_stream;
678 valobj, scratch_stream, summary_options, prefix_token);
679 if (success)
680 stream << scratch_stream.GetData();
681 else
682 stream << "Summary Unavailable";
683 return true;
684}
685
687 ValueObject &valobj, Stream &stream,
688 const TypeSummaryOptions &summary_options) {
690 valobj, stream, summary_options, "");
691}
692
694 ValueObject &valobj, Stream &stream,
695 const TypeSummaryOptions &summary_options) {
697 valobj, stream, summary_options, "u");
698}
699
701 ValueObject &valobj, Stream &stream,
702 const TypeSummaryOptions &summary_options) {
704 valobj, stream, summary_options, "U");
705}
706
707static std::tuple<bool, ValueObjectSP, size_t>
709 auto dataobj = GetChildMemberWithName(
710 valobj, {ConstString("__data_"), ConstString("__data")});
711 auto sizeobj = GetChildMemberWithName(
712 valobj, {ConstString("__size_"), ConstString("__size")});
713 if (!dataobj || !sizeobj)
714 return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
715
716 if (!dataobj->GetError().Success() || !sizeobj->GetError().Success())
717 return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
718
719 bool success{false};
720 uint64_t size = sizeobj->GetValueAsUnsigned(0, &success);
721 if (!success)
722 return std::make_tuple<bool,ValueObjectSP,size_t>(false, {}, {});
723
724 return std::make_tuple(true,dataobj,size);
725}
726
727template <StringPrinter::StringElementType element_type>
728static bool formatStringViewImpl(ValueObject &valobj, Stream &stream,
729 const TypeSummaryOptions &summary_options,
730 std::string prefix_token) {
731
732 bool success;
733 ValueObjectSP dataobj;
734 size_t size;
735 std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj);
736
737 if (!success) {
738 stream << "Summary Unavailable";
739 return true;
740 }
741
742 return StringBufferSummaryProvider<element_type>(stream, summary_options,
743 dataobj, size, prefix_token);
744}
745
747 ValueObject &valobj, Stream &stream,
748 const TypeSummaryOptions &summary_options) {
750 valobj, stream, summary_options, "");
751}
752
754 ValueObject &valobj, Stream &stream,
755 const TypeSummaryOptions &summary_options) {
757 valobj, stream, summary_options, "u");
758}
759
761 ValueObject &valobj, Stream &stream,
762 const TypeSummaryOptions &summary_options) {
764 valobj, stream, summary_options, "U");
765}
766
768 ValueObject &valobj, Stream &stream,
769 const TypeSummaryOptions &summary_options) {
770
771 bool success;
772 ValueObjectSP dataobj;
773 size_t size;
774 std::tie(success, dataobj, size) = LibcxxExtractStringViewData(valobj);
775
776 if (!success) {
777 stream << "Summary Unavailable";
778 return true;
779 }
780
781 auto wchar_t_size = GetWCharByteSize(valobj);
782 if (!wchar_t_size)
783 return false;
784
785 switch (*wchar_t_size) {
786 case 1:
788 stream, summary_options, dataobj, size, "L");
789 case 2:
791 stream, summary_options, dataobj, size, "L");
792 case 4:
794 stream, summary_options, dataobj, size, "L");
795 }
796 return false;
797}
798
799static bool
801 const TypeSummaryOptions &options,
802 const char *fmt) {
803 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__d_");
804 if (!ptr_sp)
805 return false;
806 ptr_sp = ptr_sp->GetChildMemberWithName("__rep_");
807 if (!ptr_sp)
808 return false;
809
810#ifndef _WIN32
811 // The date time in the chrono library is valid in the range
812 // [-32767-01-01T00:00:00Z, 32767-12-31T23:59:59Z]. A 64-bit time_t has a
813 // larger range, the function strftime is not able to format the entire range
814 // of time_t. The exact point has not been investigated; it's limited to
815 // chrono's range.
816 const std::time_t chrono_timestamp_min =
817 -1'096'193'779'200; // -32767-01-01T00:00:00Z
818 const std::time_t chrono_timestamp_max =
819 971'890'963'199; // 32767-12-31T23:59:59Z
820#else
821 const std::time_t chrono_timestamp_min = -43'200; // 1969-12-31T12:00:00Z
822 const std::time_t chrono_timestamp_max =
823 32'536'850'399; // 3001-01-19T21:59:59
824#endif
825
826 const std::time_t seconds = ptr_sp->GetValueAsSigned(0);
827 if (seconds < chrono_timestamp_min || seconds > chrono_timestamp_max)
828 stream.Printf("timestamp=%" PRId64 " s", static_cast<int64_t>(seconds));
829 else {
830 std::array<char, 128> str;
831 std::size_t size =
832 std::strftime(str.data(), str.size(), fmt, gmtime(&seconds));
833 if (size == 0)
834 return false;
835
836 stream.Printf("date/time=%s timestamp=%" PRId64 " s", str.data(),
837 static_cast<int64_t>(seconds));
838 }
839
840 return true;
841}
842
844 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
845 return LibcxxChronoTimePointSecondsSummaryProvider(valobj, stream, options,
846 "%FT%H:%M:%SZ");
847}
848
850 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
851 return LibcxxChronoTimePointSecondsSummaryProvider(valobj, stream, options,
852 "%FT%H:%M:%S");
853}
854
855static bool
857 const TypeSummaryOptions &options,
858 const char *fmt) {
859 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__d_");
860 if (!ptr_sp)
861 return false;
862 ptr_sp = ptr_sp->GetChildMemberWithName("__rep_");
863 if (!ptr_sp)
864 return false;
865
866#ifndef _WIN32
867 // The date time in the chrono library is valid in the range
868 // [-32767-01-01Z, 32767-12-31Z]. A 32-bit time_t has a larger range, the
869 // function strftime is not able to format the entire range of time_t. The
870 // exact point has not been investigated; it's limited to chrono's range.
871 const int chrono_timestamp_min = -12'687'428; // -32767-01-01Z
872 const int chrono_timestamp_max = 11'248'737; // 32767-12-31Z
873#else
874 const int chrono_timestamp_min = 0; // 1970-01-01Z
875 const int chrono_timestamp_max = 376'583; // 3001-01-19Z
876#endif
877
878 const int days = ptr_sp->GetValueAsSigned(0);
879 if (days < chrono_timestamp_min || days > chrono_timestamp_max)
880 stream.Printf("timestamp=%d days", days);
881
882 else {
883 const std::time_t seconds = std::time_t(86400) * days;
884
885 std::array<char, 128> str;
886 std::size_t size =
887 std::strftime(str.data(), str.size(), fmt, gmtime(&seconds));
888 if (size == 0)
889 return false;
890
891 stream.Printf("date=%s timestamp=%d days", str.data(), days);
892 }
893
894 return true;
895}
896
898 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
899 return LibcxxChronoTimepointDaysSummaryProvider(valobj, stream, options,
900 "%FZ");
901}
902
904 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
905 return LibcxxChronoTimepointDaysSummaryProvider(valobj, stream, options,
906 "%F");
907}
908
910 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
911 // FIXME: These are the names used in the C++20 ostream operator. Since LLVM
912 // uses C++17 it's not possible to use the ostream operator directly.
913 static const std::array<std::string_view, 12> months = {
914 "January", "February", "March", "April", "May", "June",
915 "July", "August", "September", "October", "November", "December"};
916
917 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__m_");
918 if (!ptr_sp)
919 return false;
920
921 const unsigned month = ptr_sp->GetValueAsUnsigned(0);
922 if (month >= 1 && month <= 12)
923 stream << "month=" << months[month - 1];
924 else
925 stream.Printf("month=%u", month);
926
927 return true;
928}
929
931 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
932 // FIXME: These are the names used in the C++20 ostream operator. Since LLVM
933 // uses C++17 it's not possible to use the ostream operator directly.
934 static const std::array<std::string_view, 7> weekdays = {
935 "Sunday", "Monday", "Tuesday", "Wednesday",
936 "Thursday", "Friday", "Saturday"};
937
938 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__wd_");
939 if (!ptr_sp)
940 return false;
941
942 const unsigned weekday = ptr_sp->GetValueAsUnsigned(0);
943 if (weekday < 7)
944 stream << "weekday=" << weekdays[weekday];
945 else
946 stream.Printf("weekday=%u", weekday);
947
948 return true;
949}
950
952 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
953 ValueObjectSP ptr_sp = valobj.GetChildMemberWithName("__y_");
954 if (!ptr_sp)
955 return false;
956 ptr_sp = ptr_sp->GetChildMemberWithName("__y_");
957 if (!ptr_sp)
958 return false;
959 int year = ptr_sp->GetValueAsSigned(0);
960
961 ptr_sp = valobj.GetChildMemberWithName("__m_");
962 if (!ptr_sp)
963 return false;
964 ptr_sp = ptr_sp->GetChildMemberWithName("__m_");
965 if (!ptr_sp)
966 return false;
967 const unsigned month = ptr_sp->GetValueAsUnsigned(0);
968
969 ptr_sp = valobj.GetChildMemberWithName("__d_");
970 if (!ptr_sp)
971 return false;
972 ptr_sp = ptr_sp->GetChildMemberWithName("__d_");
973 if (!ptr_sp)
974 return false;
975 const unsigned day = ptr_sp->GetValueAsUnsigned(0);
976
977 stream << "date=";
978 if (year < 0) {
979 stream << '-';
980 year = -year;
981 }
982 stream.Printf("%04d-%02u-%02u", year, month, day);
983
984 return true;
985}
static bool LibcxxChronoTimepointDaysSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options, const char *fmt)
Definition LibCxx.cpp:856
static ValueObjectSP ExtractLibCxxStringData(ValueObject &valobj)
Definition LibCxx.cpp:529
static bool formatStringImpl(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token)
Definition LibCxx.cpp:673
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:545
static bool formatStringViewImpl(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token)
Definition LibCxx.cpp:728
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:708
static bool LibcxxChronoTimePointSecondsSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options, const char *fmt)
Definition LibCxx.cpp:800
static bool LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options, std::string prefix_token)
Definition LibCxx.cpp:659
static void consumeInlineNamespace(llvm::StringRef &name)
Definition LibCxx.cpp:40
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:394
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.
const ConstString & GetFilename() const
Filename string const get accessor.
Definition FileSpec.h:250
A plug-in interface definition class for debugging a process.
Definition Process.h:355
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
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:132
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
Determine the index of a named child.
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:450
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:480
llvm::Expected< size_t > GetIndexOfChildWithName(ConstString name) override
Determine the index of a named child.
Definition LibCxx.cpp:514
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
Definition LibCxx.cpp:457
LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
Definition LibCxx.cpp:433
#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:843
bool LibcxxChronoMonthSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:909
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:746
bool LibcxxStringViewSummaryProviderUTF16(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition LibCxx.cpp:753
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:760
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:951
bool LibcxxWStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:629
bool LibcxxStringSummaryProviderASCII(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &summary_options)
Definition LibCxx.cpp:686
bool LibcxxChronoLocalSecondsSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:849
bool LibcxxWStringViewSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:767
bool LibcxxChronoWeekdaySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
Definition LibCxx.cpp:930
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:693
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:700
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:903
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:897
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:327
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