LLDB mainline
NSDictionary.cpp
Go to the documentation of this file.
1//===-- NSDictionary.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 <mutex>
10
11#include "clang/AST/DeclCXX.h"
12
13#include "CFBasicHash.h"
14#include "NSDictionary.h"
15
18
24#include "lldb/Target/Target.h"
26#include "lldb/Utility/Endian.h"
27#include "lldb/Utility/Status.h"
28#include "lldb/Utility/Stream.h"
29
30using namespace lldb;
31using namespace lldb_private;
32using namespace lldb_private::formatters;
33
36 : m_prefix(p) {}
37
39 ConstString class_name) {
40 return class_name.GetStringRef().starts_with(m_prefix.GetStringRef());
41}
42
44 : m_name(n) {}
45
47 ConstString class_name) {
48 return (class_name == m_name);
49}
50
55 return g_map;
56}
57
62 g_map;
63 return g_map;
64}
65
67 CompilerType compiler_type;
68 TypeSystemClangSP scratch_ts_sp =
70
71 if (!scratch_ts_sp)
72 return compiler_type;
73
74 static constexpr llvm::StringLiteral g_lldb_autogen_nspair("__lldb_autogen_nspair");
75
76 compiler_type = scratch_ts_sp->GetTypeForIdentifier<clang::CXXRecordDecl>(g_lldb_autogen_nspair);
77
78 if (!compiler_type) {
79 compiler_type = scratch_ts_sp->CreateRecordType(
81 g_lldb_autogen_nspair, llvm::to_underlying(clang::TagTypeKind::Struct),
83
84 if (compiler_type) {
86 CompilerType id_compiler_type =
87 scratch_ts_sp->GetBasicType(eBasicTypeObjCID);
89 compiler_type, "key", id_compiler_type, lldb::eAccessPublic, 0);
91 compiler_type, "value", id_compiler_type, lldb::eAccessPublic, 0);
93 }
94 }
95 return compiler_type;
96}
97
98namespace lldb_private {
99namespace formatters {
101public:
103
105
106 llvm::Expected<uint32_t> CalculateNumChildren() override;
107
108 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
109
110 lldb::ChildCacheState Update() override;
111
112 bool MightHaveChildren() override;
113
114 size_t GetIndexOfChildWithName(ConstString name) override;
115
116private:
118 uint32_t _used : 26;
119 uint32_t _szidx : 6;
120 };
121
123 uint64_t _used : 58;
124 uint32_t _szidx : 6;
125 };
126
131 };
132
134 uint8_t m_ptr_size = 8;
136 DataDescriptor_32 *m_data_32 = nullptr;
137 DataDescriptor_64 *m_data_64 = nullptr;
140 std::vector<DictionaryItemDescriptor> m_children;
141};
142
144public:
146
147 llvm::Expected<uint32_t> CalculateNumChildren() override;
148
149 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
150
151 lldb::ChildCacheState Update() override;
152
153 bool MightHaveChildren() override;
154
155 size_t GetIndexOfChildWithName(ConstString name) override;
156
157private:
160 uint8_t m_ptr_size = 8;
162 unsigned int m_size = 0;
165
170 };
171
172 std::vector<DictionaryItemDescriptor> m_children;
173};
174
176public:
178
179 llvm::Expected<uint32_t> CalculateNumChildren() override;
180
181 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
182
183 lldb::ChildCacheState Update() override;
184
185 bool MightHaveChildren() override;
186
187 size_t GetIndexOfChildWithName(ConstString name) override;
188
189private:
194 };
195
197 uint8_t m_ptr_size = 8;
199
201
203 std::vector<DictionaryItemDescriptor> m_children;
204};
205
207public:
209
211
212 llvm::Expected<uint32_t> CalculateNumChildren() override;
213
214 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
215
216 lldb::ChildCacheState Update() override;
217
218 bool MightHaveChildren() override;
219
220 size_t GetIndexOfChildWithName(ConstString name) override;
221
222private:
224};
225
226template <typename D32, typename D64>
228public:
230
232
233 llvm::Expected<uint32_t> CalculateNumChildren() override;
234
235 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
236
237 lldb::ChildCacheState Update() override;
238
239 bool MightHaveChildren() override;
240
241 size_t GetIndexOfChildWithName(ConstString name) override;
242
243private:
248 };
249
251 uint8_t m_ptr_size = 8;
256 std::vector<DictionaryItemDescriptor> m_children;
257};
258
259namespace Foundation1100 {
261 public:
263
265
266 llvm::Expected<uint32_t> CalculateNumChildren() override;
267
268 lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
269
270 lldb::ChildCacheState Update() override;
271
272 bool MightHaveChildren() override;
273
274 size_t GetIndexOfChildWithName(ConstString name) override;
275
276 private:
278 uint32_t _used : 26;
279 uint32_t _kvo : 1;
280 uint32_t _size;
281 uint32_t _mutations;
282 uint32_t _objs_addr;
283 uint32_t _keys_addr;
284 };
285
287 uint64_t _used : 58;
288 uint32_t _kvo : 1;
289 uint64_t _size;
290 uint64_t _mutations;
291 uint64_t _objs_addr;
292 uint64_t _keys_addr;
293 };
294
299 };
300
302 uint8_t m_ptr_size = 8;
304 DataDescriptor_32 *m_data_32 = nullptr;
305 DataDescriptor_64 *m_data_64 = nullptr;
307 std::vector<DictionaryItemDescriptor> m_children;
308 };
309}
310
311namespace Foundation1428 {
312 namespace {
313 struct DataDescriptor_32 {
314 uint32_t _used : 26;
315 uint32_t _kvo : 1;
316 uint32_t _size;
317 uint32_t _buffer;
318 uint64_t GetSize() { return _size; }
319 };
320
321 struct DataDescriptor_64 {
322 uint64_t _used : 58;
323 uint32_t _kvo : 1;
324 uint64_t _size;
325 uint64_t _buffer;
326 uint64_t GetSize() { return _size; }
327 };
328 }
329
332}
333
334namespace Foundation1437 {
335 static const uint64_t NSDictionaryCapacities[] = {
336 0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723,
337 2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607,
338 214519, 346607, 561109, 907759, 1468927, 2376191, 3845119,
339 6221311, 10066421, 16287743, 26354171, 42641881, 68996069,
340 111638519, 180634607, 292272623, 472907251
341 };
342
343 static const size_t NSDictionaryNumSizeBuckets =
344 sizeof(NSDictionaryCapacities) / sizeof(uint64_t);
345
346 namespace {
347 struct DataDescriptor_32 {
348 uint32_t _buffer;
349 uint32_t _muts;
350 uint32_t _used : 25;
351 uint32_t _kvo : 1;
352 uint32_t _szidx : 6;
353
354 uint64_t GetSize() {
355 return (_szidx) >= NSDictionaryNumSizeBuckets ?
356 0 : NSDictionaryCapacities[_szidx];
357 }
358 };
359
360 struct DataDescriptor_64 {
361 uint64_t _buffer;
362 uint32_t _muts;
363 uint32_t _used : 25;
364 uint32_t _kvo : 1;
365 uint32_t _szidx : 6;
366
367 uint64_t GetSize() {
370 }
371 };
372 } // namespace
373
376
377 template <typename DD>
378 uint64_t
380 lldb::addr_t valobj_addr, Status &error) {
381 const lldb::addr_t start_of_descriptor =
382 valobj_addr + process.GetAddressByteSize();
383 DD descriptor = DD();
384 process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor),
385 error);
386 if (error.Fail()) {
387 return 0;
388 }
389 return descriptor._used;
390 }
391
392 uint64_t
394 Status &error) {
395 if (process.GetAddressByteSize() == 4) {
396 return __NSDictionaryMSize_Impl<DataDescriptor_32>(process, valobj_addr,
397 error);
398 } else {
399 return __NSDictionaryMSize_Impl<DataDescriptor_64>(process, valobj_addr,
400 error);
401 }
402 }
403
404}
405} // namespace formatters
406} // namespace lldb_private
407
408template <bool name_entries>
410 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
411 static constexpr llvm::StringLiteral g_TypeHint("NSDictionary");
412 ProcessSP process_sp = valobj.GetProcessSP();
413 if (!process_sp)
414 return false;
415
416 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
417
418 if (!runtime)
419 return false;
420
422 runtime->GetNonKVOClassDescriptor(valobj));
423
424 if (!descriptor || !descriptor->IsValid())
425 return false;
426
427 uint32_t ptr_size = process_sp->GetAddressByteSize();
428 bool is_64bit = (ptr_size == 8);
429
430 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
431
432 if (!valobj_addr)
433 return false;
434
435 uint64_t value = 0;
436
437 ConstString class_name(descriptor->GetClassName());
438
439 static const ConstString g_DictionaryI("__NSDictionaryI");
440 static const ConstString g_DictionaryM("__NSDictionaryM");
441 static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
442 static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable");
443 static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");
444 static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
445 static const ConstString g_Dictionary0("__NSDictionary0");
446 static const ConstString g_DictionaryCF("__CFDictionary");
447 static const ConstString g_DictionaryNSCF("__NSCFDictionary");
448 static const ConstString g_DictionaryCFRef("CFDictionaryRef");
449 static const ConstString g_ConstantDictionary("NSConstantDictionary");
450
451 if (class_name.IsEmpty())
452 return false;
453
454 if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) {
456 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
457 ptr_size, 0, error);
458 if (error.Fail())
459 return false;
460
461 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
462 } else if (class_name == g_ConstantDictionary) {
464 value = process_sp->ReadUnsignedIntegerFromMemory(
465 valobj_addr + 2 * ptr_size, ptr_size, 0, error);
466 if (error.Fail())
467 return false;
468 } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy ||
469 class_name == g_DictionaryMFrozen) {
470 AppleObjCRuntime *apple_runtime =
471 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
473 if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) {
474 value = Foundation1437::__NSDictionaryMSize(*process_sp, valobj_addr,
475 error);
476 } else {
477 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
478 ptr_size, 0, error);
479 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
480 }
481 if (error.Fail())
482 return false;
483 } else if (class_name == g_Dictionary1) {
484 value = 1;
485 } else if (class_name == g_Dictionary0) {
486 value = 0;
487 } else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
488 class_name == g_DictionaryCFRef) {
489 ExecutionContext exe_ctx(process_sp);
490 CFBasicHash cfbh;
491 if (!cfbh.Update(valobj_addr, exe_ctx))
492 return false;
493 value = cfbh.GetCount();
494 } else {
496 for (auto &candidate : map) {
497 if (candidate.first && candidate.first->Match(class_name))
498 return candidate.second(valobj, stream, options);
499 }
500 return false;
501 }
502
503 llvm::StringRef prefix, suffix;
504 if (Language *language = Language::FindPlugin(options.GetLanguage()))
505 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
506
507 stream << prefix;
508 stream.Printf("%" PRIu64 " %s%s", value, "key/value pair",
509 value == 1 ? "" : "s");
510 stream << suffix;
511 return true;
512}
513
516 CXXSyntheticChildren *synth, lldb::ValueObjectSP valobj_sp) {
517 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
518 if (!process_sp)
519 return nullptr;
520 AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
521 ObjCLanguageRuntime::Get(*process_sp));
522 if (!runtime)
523 return nullptr;
524
525 CompilerType valobj_type(valobj_sp->GetCompilerType());
526 Flags flags(valobj_type.GetTypeInfo());
527
528 if (flags.IsClear(eTypeIsPointer)) {
530 valobj_sp = valobj_sp->AddressOf(error);
531 if (error.Fail() || !valobj_sp)
532 return nullptr;
533 }
534
536 runtime->GetClassDescriptor(*valobj_sp));
537
538 if (!descriptor || !descriptor->IsValid())
539 return nullptr;
540
541 ConstString class_name(descriptor->GetClassName());
542
543 static const ConstString g_DictionaryI("__NSDictionaryI");
544 static const ConstString g_DictionaryM("__NSDictionaryM");
545 static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
546 static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable");
547 static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");
548 static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
549 static const ConstString g_Dictionary0("__NSDictionary0");
550 static const ConstString g_DictionaryCF("__CFDictionary");
551 static const ConstString g_DictionaryNSCF("__NSCFDictionary");
552 static const ConstString g_DictionaryCFRef("CFDictionaryRef");
553 static const ConstString g_ConstantDictionary("NSConstantDictionary");
554
555 if (class_name.IsEmpty())
556 return nullptr;
557
558 if (class_name == g_DictionaryI) {
559 return (new NSDictionaryISyntheticFrontEnd(valobj_sp));
560 } else if (class_name == g_ConstantDictionary) {
561 return (new NSConstantDictionarySyntheticFrontEnd(valobj_sp));
562 } else if (class_name == g_DictionaryM || class_name == g_DictionaryMFrozen) {
563 if (runtime->GetFoundationVersion() >= 1437) {
565 } else if (runtime->GetFoundationVersion() >= 1428) {
567 } else {
569 }
570 } else if (class_name == g_DictionaryMLegacy) {
572 } else if (class_name == g_Dictionary1) {
573 return (new NSDictionary1SyntheticFrontEnd(valobj_sp));
574 } else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
575 class_name == g_DictionaryCFRef) {
576 return (new NSCFDictionarySyntheticFrontEnd(valobj_sp));
577 } else {
579 for (auto &candidate : map) {
580 if (candidate.first && candidate.first->Match((class_name)))
581 return candidate.second(synth, valobj_sp);
582 }
583 }
584
585 return nullptr;
586}
587
590 : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_type() {}
591
594 delete m_data_32;
595 m_data_32 = nullptr;
596 delete m_data_64;
597 m_data_64 = nullptr;
598}
599
602 const char *item_name = name.GetCString();
603 uint32_t idx = ExtractIndexFromString(item_name);
604 if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())
605 return UINT32_MAX;
606 return idx;
607}
608
609llvm::Expected<uint32_t> lldb_private::formatters::
611 if (!m_data_32 && !m_data_64)
612 return 0;
613 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
614}
615
618 m_children.clear();
619 delete m_data_32;
620 m_data_32 = nullptr;
621 delete m_data_64;
622 m_data_64 = nullptr;
623 m_ptr_size = 0;
624 ValueObjectSP valobj_sp = m_backend.GetSP();
625 if (!valobj_sp)
627 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
629 error.Clear();
630 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
631 if (!process_sp)
633 m_ptr_size = process_sp->GetAddressByteSize();
634 m_order = process_sp->GetByteOrder();
635 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
636 if (m_ptr_size == 4) {
637 m_data_32 = new DataDescriptor_32();
638 process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
639 error);
640 } else {
641 m_data_64 = new DataDescriptor_64();
642 process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
643 error);
644 }
645 if (error.Fail())
647 m_data_ptr = data_location + m_ptr_size;
649}
650
653 return true;
654}
655
658 uint32_t idx) {
659 uint32_t num_children = CalculateNumChildrenIgnoringErrors();
660
661 if (idx >= num_children)
662 return lldb::ValueObjectSP();
663
664 if (m_children.empty()) {
665 // do the scan phase
666 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
667
668 uint32_t tries = 0;
669 uint32_t test_idx = 0;
670
671 while (tries < num_children) {
672 key_at_idx = m_data_ptr + (2 * test_idx * m_ptr_size);
673 val_at_idx = key_at_idx + m_ptr_size;
674 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
675 if (!process_sp)
676 return lldb::ValueObjectSP();
678 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
679 if (error.Fail())
680 return lldb::ValueObjectSP();
681 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
682 if (error.Fail())
683 return lldb::ValueObjectSP();
684
685 test_idx++;
686
687 if (!key_at_idx || !val_at_idx)
688 continue;
689 tries++;
690
691 DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
693
694 m_children.push_back(descriptor);
695 }
696 }
697
698 if (idx >= m_children.size()) // should never happen
699 return lldb::ValueObjectSP();
700
701 DictionaryItemDescriptor &dict_item = m_children[idx];
702 if (!dict_item.valobj_sp) {
703 if (!m_pair_type.IsValid()) {
704 TargetSP target_sp(m_backend.GetTargetSP());
705 if (!target_sp)
706 return ValueObjectSP();
707 m_pair_type = GetLLDBNSPairType(target_sp);
708 }
709 if (!m_pair_type.IsValid())
710 return ValueObjectSP();
711
712 WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
713
714 if (m_ptr_size == 8) {
715 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
716 *data_ptr = dict_item.key_ptr;
717 *(data_ptr + 1) = dict_item.val_ptr;
718 } else {
719 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
720 *data_ptr = dict_item.key_ptr;
721 *(data_ptr + 1) = dict_item.val_ptr;
722 }
723
724 StreamString idx_name;
725 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
726 DataExtractor data(buffer_sp, m_order, m_ptr_size);
727 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
728 m_exe_ctx_ref, m_pair_type);
729 }
730 return dict_item.valobj_sp;
731}
732
735 : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_hashtable(),
736 m_pair_type() {}
737
740 const char *item_name = name.GetCString();
741 const uint32_t idx = ExtractIndexFromString(item_name);
742 if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())
743 return UINT32_MAX;
744 return idx;
745}
746
747llvm::Expected<uint32_t> lldb_private::formatters::
749 if (!m_hashtable.IsValid())
750 return 0;
751 return m_hashtable.GetCount();
752}
753
756 m_children.clear();
757 ValueObjectSP valobj_sp = m_backend.GetSP();
758 m_ptr_size = 0;
759 if (!valobj_sp)
761 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
762
763 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
764 if (!process_sp)
766 m_ptr_size = process_sp->GetAddressByteSize();
767 m_order = process_sp->GetByteOrder();
768 return m_hashtable.Update(valobj_sp->GetValueAsUnsigned(0), m_exe_ctx_ref)
771}
772
775 return true;
776}
777
780 uint32_t idx) {
781 lldb::addr_t m_keys_ptr = m_hashtable.GetKeyPointer();
782 lldb::addr_t m_values_ptr = m_hashtable.GetValuePointer();
783
784 const uint32_t num_children = CalculateNumChildrenIgnoringErrors();
785
786 if (idx >= num_children)
787 return lldb::ValueObjectSP();
788
789 if (m_children.empty()) {
790 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
791 if (!process_sp)
792 return lldb::ValueObjectSP();
793
795 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
796
797 uint32_t tries = 0;
798 uint32_t test_idx = 0;
799
800 // Iterate over inferior memory, reading key/value pointers by shifting each
801 // cursor by test_index * m_ptr_size. Returns an empty ValueObject if a read
802 // fails, otherwise, continue until the number of tries matches the number
803 // of childen.
804 while (tries < num_children) {
805 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
806 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
807
808 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
809 if (error.Fail())
810 return lldb::ValueObjectSP();
811 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
812 if (error.Fail())
813 return lldb::ValueObjectSP();
814
815 test_idx++;
816
817 if (!key_at_idx || !val_at_idx)
818 continue;
819 tries++;
820
821 DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
823
824 m_children.push_back(descriptor);
825 }
826 }
827
828 if (idx >= m_children.size()) // should never happen
829 return lldb::ValueObjectSP();
830
831 DictionaryItemDescriptor &dict_item = m_children[idx];
832 if (!dict_item.valobj_sp) {
833 if (!m_pair_type.IsValid()) {
834 TargetSP target_sp(m_backend.GetTargetSP());
835 if (!target_sp)
836 return ValueObjectSP();
837 m_pair_type = GetLLDBNSPairType(target_sp);
838 }
839 if (!m_pair_type.IsValid())
840 return ValueObjectSP();
841
842 WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
843
844 switch (m_ptr_size) {
845 case 0: // architecture has no clue - fail
846 return lldb::ValueObjectSP();
847 case 4: {
848 uint32_t *data_ptr = reinterpret_cast<uint32_t *>(buffer_sp->GetBytes());
849 *data_ptr = dict_item.key_ptr;
850 *(data_ptr + 1) = dict_item.val_ptr;
851 } break;
852 case 8: {
853 uint64_t *data_ptr = reinterpret_cast<uint64_t *>(buffer_sp->GetBytes());
854 *data_ptr = dict_item.key_ptr;
855 *(data_ptr + 1) = dict_item.val_ptr;
856 } break;
857 default:
858 lldbassert(false && "pointer size is not 4 nor 8");
859 }
860
861 StreamString idx_name;
862 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
863 DataExtractor data(buffer_sp, m_order, m_ptr_size);
864 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
865 m_exe_ctx_ref, m_pair_type);
866 }
867 return dict_item.valobj_sp;
868}
869
872 : SyntheticChildrenFrontEnd(*valobj_sp) {}
873
876 const char *item_name = name.GetCString();
877 uint32_t idx = ExtractIndexFromString(item_name);
878 if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())
879 return UINT32_MAX;
880 return idx;
881}
882
883llvm::Expected<uint32_t> lldb_private::formatters::
885 return m_size;
886}
887
890 ValueObjectSP valobj_sp = m_backend.GetSP();
891 if (!valobj_sp)
893 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
895 error.Clear();
896 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
897 if (!process_sp)
899 m_ptr_size = process_sp->GetAddressByteSize();
900 m_order = process_sp->GetByteOrder();
901 uint64_t valobj_addr = valobj_sp->GetValueAsUnsigned(0);
902 m_size = process_sp->ReadUnsignedIntegerFromMemory(
903 valobj_addr + 2 * m_ptr_size, m_ptr_size, 0, error);
904 if (error.Fail())
906 m_keys_ptr =
907 process_sp->ReadPointerFromMemory(valobj_addr + 3 * m_ptr_size, error);
908 if (error.Fail())
910 m_objects_ptr =
911 process_sp->ReadPointerFromMemory(valobj_addr + 4 * m_ptr_size, error);
912
913 return error.Success() ? lldb::ChildCacheState::eReuse
915}
916
919 return true;
920}
921
924 uint32_t num_children = CalculateNumChildrenIgnoringErrors();
925
926 if (idx >= num_children)
927 return lldb::ValueObjectSP();
928
929 if (m_children.empty()) {
930 // do the scan phase
931 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
932 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
933 if (!process_sp)
934 return lldb::ValueObjectSP();
935
936 for (unsigned int child = 0; child < num_children; ++child) {
938 key_at_idx = process_sp->ReadPointerFromMemory(
939 m_keys_ptr + child * m_ptr_size, error);
940 if (error.Fail())
941 return lldb::ValueObjectSP();
942 val_at_idx = process_sp->ReadPointerFromMemory(
943 m_objects_ptr + child * m_ptr_size, error);
944 if (error.Fail())
945 return lldb::ValueObjectSP();
946 DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
948 m_children.push_back(descriptor);
949 }
950 }
951
952 if (idx >= m_children.size()) // should never happen
953 return lldb::ValueObjectSP();
954
955 DictionaryItemDescriptor &dict_item = m_children[idx];
956 if (!dict_item.valobj_sp) {
957 if (!m_pair_type.IsValid()) {
958 TargetSP target_sp(m_backend.GetTargetSP());
959 if (!target_sp)
960 return ValueObjectSP();
961 m_pair_type = GetLLDBNSPairType(target_sp);
962 }
963 if (!m_pair_type.IsValid())
964 return ValueObjectSP();
965
966 WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
967
968 if (m_ptr_size == 8) {
969 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
970 *data_ptr = dict_item.key_ptr;
971 *(data_ptr + 1) = dict_item.val_ptr;
972 } else {
973 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
974 *data_ptr = dict_item.key_ptr;
975 *(data_ptr + 1) = dict_item.val_ptr;
976 }
977
978 StreamString idx_name;
979 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
980 DataExtractor data(buffer_sp, m_order, m_ptr_size);
981 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
982 m_exe_ctx_ref, m_pair_type);
983 }
984 return dict_item.valobj_sp;
985}
986
989 : SyntheticChildrenFrontEnd(*valobj_sp.get()), m_pair(nullptr) {}
990
993 static const ConstString g_zero("[0]");
994 return name == g_zero ? 0 : UINT32_MAX;
995}
996
997llvm::Expected<uint32_t> lldb_private::formatters::
999 return 1;
1000}
1001
1004 m_pair.reset();
1006}
1007
1010 return true;
1011}
1012
1015 uint32_t idx) {
1016 if (idx != 0)
1017 return lldb::ValueObjectSP();
1018
1019 if (m_pair.get())
1020 return m_pair;
1021
1022 auto process_sp(m_backend.GetProcessSP());
1023 if (!process_sp)
1024 return nullptr;
1025
1026 auto ptr_size = process_sp->GetAddressByteSize();
1027
1028 lldb::addr_t key_ptr =
1029 m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS) + ptr_size;
1030 lldb::addr_t value_ptr = key_ptr + ptr_size;
1031
1032 Status error;
1033
1034 lldb::addr_t value_at_idx = process_sp->ReadPointerFromMemory(key_ptr, error);
1035 if (error.Fail())
1036 return nullptr;
1037 lldb::addr_t key_at_idx = process_sp->ReadPointerFromMemory(value_ptr, error);
1038 if (error.Fail())
1039 return nullptr;
1040
1041 auto pair_type =
1042 GetLLDBNSPairType(process_sp->GetTarget().shared_from_this());
1043
1044 WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * ptr_size, 0));
1045
1046 if (ptr_size == 8) {
1047 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1048 *data_ptr = key_at_idx;
1049 *(data_ptr + 1) = value_at_idx;
1050 } else {
1051 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1052 *data_ptr = key_at_idx;
1053 *(data_ptr + 1) = value_at_idx;
1054 }
1055
1056 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size);
1057 m_pair = CreateValueObjectFromData(
1058 "[0]", data, m_backend.GetExecutionContextRef(), pair_type);
1059
1060 return m_pair;
1061}
1062
1063template <typename D32, typename D64>
1066 : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(),
1067 m_data_32(nullptr), m_data_64(nullptr), m_pair_type() {}
1068
1069template <typename D32, typename D64>
1073 delete m_data_32;
1074 m_data_32 = nullptr;
1075 delete m_data_64;
1076 m_data_64 = nullptr;
1077}
1078
1079template <typename D32, typename D64>
1081 D32, D64>::GetIndexOfChildWithName(ConstString name) {
1082 const char *item_name = name.GetCString();
1083 uint32_t idx = ExtractIndexFromString(item_name);
1084 if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())
1085 return UINT32_MAX;
1086 return idx;
1087}
1088
1089template <typename D32, typename D64>
1090llvm::Expected<uint32_t>
1093 if (!m_data_32 && !m_data_64)
1094 return 0;
1095 return (m_data_32 ? (uint32_t)m_data_32->_used : (uint32_t)m_data_64->_used);
1096}
1097
1098template <typename D32, typename D64>
1101 D64>::Update() {
1102 m_children.clear();
1103 ValueObjectSP valobj_sp = m_backend.GetSP();
1104 m_ptr_size = 0;
1105 delete m_data_32;
1106 m_data_32 = nullptr;
1107 delete m_data_64;
1108 m_data_64 = nullptr;
1109 if (!valobj_sp)
1111 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1112 Status error;
1113 error.Clear();
1114 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1115 if (!process_sp)
1117 m_ptr_size = process_sp->GetAddressByteSize();
1118 m_order = process_sp->GetByteOrder();
1119 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
1120 if (m_ptr_size == 4) {
1121 m_data_32 = new D32();
1122 process_sp->ReadMemory(data_location, m_data_32, sizeof(D32),
1123 error);
1124 } else {
1125 m_data_64 = new D64();
1126 process_sp->ReadMemory(data_location, m_data_64, sizeof(D64),
1127 error);
1128 }
1129
1130 return error.Success() ? lldb::ChildCacheState::eReuse
1132}
1133
1134template <typename D32, typename D64>
1135bool
1138 return true;
1139}
1140
1141template <typename D32, typename D64>
1144 D32, D64>::GetChildAtIndex(uint32_t idx) {
1145 lldb::addr_t m_keys_ptr;
1146 lldb::addr_t m_values_ptr;
1147 if (m_data_32) {
1148 uint32_t size = m_data_32->GetSize();
1149 m_keys_ptr = m_data_32->_buffer;
1150 m_values_ptr = m_data_32->_buffer + (m_ptr_size * size);
1151 } else {
1152 uint32_t size = m_data_64->GetSize();
1153 m_keys_ptr = m_data_64->_buffer;
1154 m_values_ptr = m_data_64->_buffer + (m_ptr_size * size);
1155 }
1156
1157 uint32_t num_children = CalculateNumChildrenIgnoringErrors();
1158
1159 if (idx >= num_children)
1160 return lldb::ValueObjectSP();
1161
1162 if (m_children.empty()) {
1163 // do the scan phase
1164 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1165
1166 uint32_t tries = 0;
1167 uint32_t test_idx = 0;
1168
1169 while (tries < num_children) {
1170 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
1171 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
1172 ;
1173 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1174 if (!process_sp)
1175 return lldb::ValueObjectSP();
1176 Status error;
1177 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1178 if (error.Fail())
1179 return lldb::ValueObjectSP();
1180 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1181 if (error.Fail())
1182 return lldb::ValueObjectSP();
1183
1184 test_idx++;
1185
1186 if (!key_at_idx || !val_at_idx)
1187 continue;
1188 tries++;
1189
1190 DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
1192
1193 m_children.push_back(descriptor);
1194 }
1195 }
1196
1197 if (idx >= m_children.size()) // should never happen
1198 return lldb::ValueObjectSP();
1199
1200 DictionaryItemDescriptor &dict_item = m_children[idx];
1201 if (!dict_item.valobj_sp) {
1202 if (!m_pair_type.IsValid()) {
1203 TargetSP target_sp(m_backend.GetTargetSP());
1204 if (!target_sp)
1205 return ValueObjectSP();
1206 m_pair_type = GetLLDBNSPairType(target_sp);
1207 }
1208 if (!m_pair_type.IsValid())
1209 return ValueObjectSP();
1210
1211 WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
1212
1213 if (m_ptr_size == 8) {
1214 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1215 *data_ptr = dict_item.key_ptr;
1216 *(data_ptr + 1) = dict_item.val_ptr;
1217 } else {
1218 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1219 *data_ptr = dict_item.key_ptr;
1220 *(data_ptr + 1) = dict_item.val_ptr;
1221 }
1222
1223 StreamString idx_name;
1224 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
1225 DataExtractor data(buffer_sp, m_order, m_ptr_size);
1226 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
1227 m_exe_ctx_ref, m_pair_type);
1228 }
1229 return dict_item.valobj_sp;
1230}
1231
1234 : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_type() {}
1235
1238 delete m_data_32;
1239 m_data_32 = nullptr;
1240 delete m_data_64;
1241 m_data_64 = nullptr;
1242}
1243
1244size_t
1247 const char *item_name = name.GetCString();
1248 uint32_t idx = ExtractIndexFromString(item_name);
1249 if (idx < UINT32_MAX && idx >= CalculateNumChildrenIgnoringErrors())
1250 return UINT32_MAX;
1251 return idx;
1252}
1253
1256 if (!m_data_32 && !m_data_64)
1257 return 0;
1258 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1259}
1260
1263 m_children.clear();
1264 ValueObjectSP valobj_sp = m_backend.GetSP();
1265 m_ptr_size = 0;
1266 delete m_data_32;
1267 m_data_32 = nullptr;
1268 delete m_data_64;
1269 m_data_64 = nullptr;
1270 if (!valobj_sp)
1272 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1273 Status error;
1274 error.Clear();
1275 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1276 if (!process_sp)
1278 m_ptr_size = process_sp->GetAddressByteSize();
1279 m_order = process_sp->GetByteOrder();
1280 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
1281 if (m_ptr_size == 4) {
1282 m_data_32 = new DataDescriptor_32();
1283 process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
1284 error);
1285 } else {
1286 m_data_64 = new DataDescriptor_64();
1287 process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
1288 error);
1289 }
1290
1291 return error.Success() ? lldb::ChildCacheState::eReuse
1293}
1294
1295bool
1298 return true;
1299}
1300
1304 lldb::addr_t m_keys_ptr =
1305 (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr);
1306 lldb::addr_t m_values_ptr =
1307 (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
1308
1309 uint32_t num_children = CalculateNumChildrenIgnoringErrors();
1310
1311 if (idx >= num_children)
1312 return lldb::ValueObjectSP();
1313
1314 if (m_children.empty()) {
1315 // do the scan phase
1316 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1317
1318 uint32_t tries = 0;
1319 uint32_t test_idx = 0;
1320
1321 while (tries < num_children) {
1322 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
1323 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
1324 ;
1325 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1326 if (!process_sp)
1327 return lldb::ValueObjectSP();
1328 Status error;
1329 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1330 if (error.Fail())
1331 return lldb::ValueObjectSP();
1332 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1333 if (error.Fail())
1334 return lldb::ValueObjectSP();
1335
1336 test_idx++;
1337
1338 if (!key_at_idx || !val_at_idx)
1339 continue;
1340 tries++;
1341
1342 DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
1344
1345 m_children.push_back(descriptor);
1346 }
1347 }
1348
1349 if (idx >= m_children.size()) // should never happen
1350 return lldb::ValueObjectSP();
1351
1352 DictionaryItemDescriptor &dict_item = m_children[idx];
1353 if (!dict_item.valobj_sp) {
1354 if (!m_pair_type.IsValid()) {
1355 TargetSP target_sp(m_backend.GetTargetSP());
1356 if (!target_sp)
1357 return ValueObjectSP();
1358 m_pair_type = GetLLDBNSPairType(target_sp);
1359 }
1360 if (!m_pair_type.IsValid())
1361 return ValueObjectSP();
1362
1363 WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
1364
1365 if (m_ptr_size == 8) {
1366 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1367 *data_ptr = dict_item.key_ptr;
1368 *(data_ptr + 1) = dict_item.val_ptr;
1369 } else {
1370 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1371 *data_ptr = dict_item.key_ptr;
1372 *(data_ptr + 1) = dict_item.val_ptr;
1373 }
1374
1375 StreamString idx_name;
1376 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
1377 DataExtractor data(buffer_sp, m_order, m_ptr_size);
1378 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
1379 m_exe_ctx_ref, m_pair_type);
1380 }
1381 return dict_item.valobj_sp;
1382}
1383
1385 ValueObject &, Stream &, const TypeSummaryOptions &);
1386
1388 ValueObject &, Stream &, const TypeSummaryOptions &);
static llvm::raw_ostream & error(Stream &strm)
#define lldbassert(x)
Definition: LLDBAssert.h:15
uint32_t _size
Definition: NSArray.cpp:105
uint32_t _used
Definition: NSArray.cpp:103
uint32_t _muts
uint32_t _kvo
uint32_t _buffer
static CompilerType GetLLDBNSPairType(TargetSP target_sp)
uint32_t _szidx
static std::optional< size_t > CalculateNumChildren(CompilerType container_elem_type, uint64_t num_elements, CompilerType element_type)
Calculates the number of elements stored in a container (with element type 'container_elem_type') as ...
Definition: VectorType.cpp:198
bool Update(lldb::addr_t addr, ExecutionContextRef exe_ctx_rf)
Definition: CFBasicHash.cpp:20
std::function< SyntheticChildrenFrontEnd *(CXXSyntheticChildren *, lldb::ValueObjectSP)> CreateFrontEndCallback
Generic representation of a type in a programming language.
Definition: CompilerType.h:36
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
A uniqued constant string class.
Definition: ConstString.h:40
bool IsEmpty() const
Test for empty string.
Definition: ConstString.h:302
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:197
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:214
A subclass of DataBuffer that stores a data buffer on the heap.
An data extractor class.
Definition: DataExtractor.h:48
Execution context objects refer to objects in the execution of the program that is being debugged.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
A class to manage flags.
Definition: Flags.h:22
bool IsClear(ValueType bit) const
Test a single flag bit to see if it is clear (zero).
Definition: Flags.h:111
static Language * FindPlugin(lldb::LanguageType language)
Definition: Language.cpp:83
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
ClassDescriptorSP GetNonKVOClassDescriptor(ValueObject &in_value)
static ObjCLanguageRuntime * Get(Process &process)
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
A plug-in interface definition class for debugging a process.
Definition: Process.h:341
virtual size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, Status &error)
Read of memory from a process.
Definition: Process.cpp:1939
uint32_t GetAddressByteSize() const
Definition: Process.cpp:3404
static lldb::TypeSystemClangSP GetForTarget(Target &target, std::optional< IsolatedASTKind > ast_kind=DefaultAST, bool create_on_demand=true)
Returns the scratch TypeSystemClang for the given target.
An error handling class.
Definition: Status.h:44
llvm::StringRef GetString() 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
lldb::LanguageType GetLanguage() const
Definition: TypeSummary.cpp:31
static clang::FieldDecl * AddFieldToRecordType(const CompilerType &type, llvm::StringRef name, const CompilerType &field_type, lldb::AccessType access, uint32_t bitfield_bit_size)
static bool CompleteTagDeclarationDefinition(const CompilerType &type)
static bool StartTagDeclarationDefinition(const CompilerType &type)
lldb::ProcessSP GetProcessSP() const
Definition: ValueObject.h:338
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
NSCFDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
std::vector< DictionaryItemDescriptor > m_children
llvm::Expected< uint32_t > CalculateNumChildren() override
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
size_t GetIndexOfChildWithName(ConstString name) override
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
llvm::Expected< uint32_t > CalculateNumChildren() override
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
NSDictionary1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
llvm::Expected< uint32_t > CalculateNumChildren() override
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
size_t GetIndexOfChildWithName(ConstString name) override
std::vector< DictionaryItemDescriptor > m_children
NSDictionaryISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
size_t GetIndexOfChildWithName(ConstString name) override
llvm::Expected< uint32_t > CalculateNumChildren() override
lldb::ChildCacheState Update() override
This function is assumed to always succeed and if it fails, the front-end should know to deal with it...
lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override
static AdditionalFormatters< CXXFunctionSummaryFormat::Callback > & GetAdditionalSummaries()
std::vector< AdditionalFormatter< FormatterType > > AdditionalFormatters
Definition: NSDictionary.h:82
static AdditionalFormatters< CXXSyntheticChildren::CreateFrontEndCallback > & GetAdditionalSynthetics()
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
#define UINT32_MAX
Definition: lldb-defines.h:19
static const uint64_t NSDictionaryCapacities[]
uint64_t __NSDictionaryMSize_Impl(lldb_private::Process &process, lldb::addr_t valobj_addr, Status &error)
uint64_t __NSDictionaryMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, Status &error)
template bool NSDictionarySummaryProvider< false >(ValueObject &, Stream &, const TypeSummaryOptions &)
size_t ExtractIndexFromString(const char *item_name)
template bool NSDictionarySummaryProvider< true >(ValueObject &, Stream &, const TypeSummaryOptions &)
bool NSDictionarySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
SyntheticChildrenFrontEnd * NSDictionarySyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP)
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
Definition: SBAddress.h:15
@ eBasicTypeObjCID
ChildCacheState
Specifies if children need to be re-computed after a call to SyntheticChildrenFrontEnd::Update.
@ eRefetch
Children need to be recomputed dynamically.
@ eReuse
Children did not change and don't need to be recomputed; re-use what we computed the last time we cal...
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:472
@ eLanguageTypeC
Non-standardized C, such as K&R.
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:381
ByteOrder
Byte ordering definitions.
@ eByteOrderInvalid
std::shared_ptr< lldb_private::TypeSystemClang > TypeSystemClangSP
Definition: lldb-forward.h:458
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
Definition: lldb-forward.h:329
uint64_t addr_t
Definition: lldb-types.h:79
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:436
std::function< bool(ValueObject &, Stream &, const TypeSummaryOptions &)> Callback
Definition: TypeSummary.h:311