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().startswith(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
66static CompilerType GetLLDBNSPairType(TargetSP target_sp) {
67 CompilerType compiler_type;
68
69 TypeSystemClangSP scratch_ts_sp =
71
72 if (scratch_ts_sp) {
73 ConstString g_lldb_autogen_nspair("__lldb_autogen_nspair");
74
75 compiler_type = scratch_ts_sp->GetTypeForIdentifier<clang::CXXRecordDecl>(
76 g_lldb_autogen_nspair);
77
78 if (!compiler_type) {
79 compiler_type = scratch_ts_sp->CreateRecordType(
81 g_lldb_autogen_nspair.GetCString(), clang::TTK_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 }
96 return compiler_type;
97}
98
99namespace lldb_private {
100namespace formatters {
102public:
103 NSDictionaryISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
104
106
107 size_t CalculateNumChildren() override;
108
109 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
110
111 bool Update() override;
112
113 bool MightHaveChildren() override;
114
115 size_t GetIndexOfChildWithName(ConstString name) override;
116
117private:
121 };
122
124 uint64_t _used : 58;
126 };
127
131 lldb::ValueObjectSP valobj_sp;
132 };
133
135 uint8_t m_ptr_size = 8;
137 DataDescriptor_32 *m_data_32 = nullptr;
138 DataDescriptor_64 *m_data_64 = nullptr;
141 std::vector<DictionaryItemDescriptor> m_children;
142};
143
145public:
146 NSConstantDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
147
148 size_t CalculateNumChildren() override;
149
150 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
151
152 bool Update() override;
153
154 bool MightHaveChildren() override;
155
156 size_t GetIndexOfChildWithName(ConstString name) override;
157
158private:
161 uint8_t m_ptr_size = 8;
163 unsigned int m_size = 0;
166
170 lldb::ValueObjectSP valobj_sp;
171 };
172
173 std::vector<DictionaryItemDescriptor> m_children;
174};
175
177public:
178 NSCFDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
179
180 size_t CalculateNumChildren() override;
181
182 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
183
184 bool Update() override;
185
186 bool MightHaveChildren() override;
187
188 size_t GetIndexOfChildWithName(ConstString name) override;
189
190private:
194 lldb::ValueObjectSP valobj_sp;
195 };
196
198 uint8_t m_ptr_size = 8;
200
202
204 std::vector<DictionaryItemDescriptor> m_children;
205};
206
208public:
209 NSDictionary1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
210
212
213 size_t CalculateNumChildren() override;
214
215 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
216
217 bool Update() override;
218
219 bool MightHaveChildren() override;
220
221 size_t GetIndexOfChildWithName(ConstString name) override;
222
223private:
224 ValueObjectSP m_pair;
225};
226
227template <typename D32, typename D64>
229public:
230 GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
231
233
234 size_t CalculateNumChildren() override;
235
236 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
237
238 bool Update() override;
239
240 bool MightHaveChildren() override;
241
242 size_t GetIndexOfChildWithName(ConstString name) override;
243
244private:
248 lldb::ValueObjectSP valobj_sp;
249 };
250
252 uint8_t m_ptr_size = 8;
257 std::vector<DictionaryItemDescriptor> m_children;
258};
259
260namespace Foundation1100 {
262 public:
263 NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
264
266
267 size_t CalculateNumChildren() override;
268
269 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
270
271 bool Update() override;
272
273 bool MightHaveChildren() override;
274
275 size_t GetIndexOfChildWithName(ConstString name) override;
276
277 private:
285 };
286
288 uint64_t _used : 58;
290 uint64_t _size;
291 uint64_t _mutations;
292 uint64_t _objs_addr;
293 uint64_t _keys_addr;
294 };
295
299 lldb::ValueObjectSP valobj_sp;
300 };
301
303 uint8_t m_ptr_size = 8;
305 DataDescriptor_32 *m_data_32 = nullptr;
306 DataDescriptor_64 *m_data_64 = nullptr;
308 std::vector<DictionaryItemDescriptor> m_children;
309 };
310}
311
312namespace Foundation1428 {
313 namespace {
314 struct DataDescriptor_32 {
319 uint64_t GetSize() { return _size; }
320 };
321
322 struct DataDescriptor_64 {
323 uint64_t _used : 58;
324 uint32_t _kvo : 1;
325 uint64_t _size;
326 uint64_t _buffer;
327 uint64_t GetSize() { return _size; }
328 };
329 }
330
333}
334
335namespace Foundation1437 {
336 static const uint64_t NSDictionaryCapacities[] = {
337 0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723,
338 2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607,
339 214519, 346607, 561109, 907759, 1468927, 2376191, 3845119,
340 6221311, 10066421, 16287743, 26354171, 42641881, 68996069,
341 111638519, 180634607, 292272623, 472907251
342 };
343
344 static const size_t NSDictionaryNumSizeBuckets =
345 sizeof(NSDictionaryCapacities) / sizeof(uint64_t);
346
347 namespace {
348 struct DataDescriptor_32 {
351 uint32_t _used : 25;
352 uint32_t _kvo : 1;
354
355 uint64_t GetSize() {
356 return (_szidx) >= NSDictionaryNumSizeBuckets ?
357 0 : NSDictionaryCapacities[_szidx];
358 }
359 };
360
361 struct DataDescriptor_64 {
362 uint64_t _buffer;
364 uint32_t _used : 25;
365 uint32_t _kvo : 1;
366 uint32_t _szidx : 6;
367
368 uint64_t GetSize() {
371 }
372 };
373 } // namespace
374
377
378 template <typename DD>
379 uint64_t
381 lldb::addr_t valobj_addr, Status &error) {
382 const lldb::addr_t start_of_descriptor =
383 valobj_addr + process.GetAddressByteSize();
384 DD descriptor = DD();
385 process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor),
386 error);
387 if (error.Fail()) {
388 return 0;
389 }
390 return descriptor._used;
391 }
392
393 uint64_t
395 Status &error) {
396 if (process.GetAddressByteSize() == 4) {
397 return __NSDictionaryMSize_Impl<DataDescriptor_32>(process, valobj_addr,
398 error);
399 } else {
400 return __NSDictionaryMSize_Impl<DataDescriptor_64>(process, valobj_addr,
401 error);
402 }
403 }
404
405}
406} // namespace formatters
407} // namespace lldb_private
408
409template <bool name_entries>
411 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
412 static constexpr llvm::StringLiteral g_TypeHint("NSDictionary");
413 ProcessSP process_sp = valobj.GetProcessSP();
414 if (!process_sp)
415 return false;
416
417 ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp);
418
419 if (!runtime)
420 return false;
421
423 runtime->GetNonKVOClassDescriptor(valobj));
424
425 if (!descriptor || !descriptor->IsValid())
426 return false;
427
428 uint32_t ptr_size = process_sp->GetAddressByteSize();
429 bool is_64bit = (ptr_size == 8);
430
431 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
432
433 if (!valobj_addr)
434 return false;
435
436 uint64_t value = 0;
437
438 ConstString class_name(descriptor->GetClassName());
439
440 static const ConstString g_DictionaryI("__NSDictionaryI");
441 static const ConstString g_DictionaryM("__NSDictionaryM");
442 static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
443 static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable");
444 static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");
445 static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
446 static const ConstString g_Dictionary0("__NSDictionary0");
447 static const ConstString g_DictionaryCF("__CFDictionary");
448 static const ConstString g_DictionaryNSCF("__NSCFDictionary");
449 static const ConstString g_DictionaryCFRef("CFDictionaryRef");
450 static const ConstString g_ConstantDictionary("NSConstantDictionary");
451
452 if (class_name.IsEmpty())
453 return false;
454
455 if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) {
457 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
458 ptr_size, 0, error);
459 if (error.Fail())
460 return false;
461
462 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
463 } else if (class_name == g_ConstantDictionary) {
465 value = process_sp->ReadUnsignedIntegerFromMemory(
466 valobj_addr + 2 * ptr_size, ptr_size, 0, error);
467 if (error.Fail())
468 return false;
469 } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy ||
470 class_name == g_DictionaryMFrozen) {
471 AppleObjCRuntime *apple_runtime =
472 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
474 if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) {
475 value = Foundation1437::__NSDictionaryMSize(*process_sp, valobj_addr,
476 error);
477 } else {
478 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
479 ptr_size, 0, error);
480 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
481 }
482 if (error.Fail())
483 return false;
484 } else if (class_name == g_Dictionary1) {
485 value = 1;
486 } else if (class_name == g_Dictionary0) {
487 value = 0;
488 } else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
489 class_name == g_DictionaryCFRef) {
490 ExecutionContext exe_ctx(process_sp);
491 CFBasicHash cfbh;
492 if (!cfbh.Update(valobj_addr, exe_ctx))
493 return false;
494 value = cfbh.GetCount();
495 } else {
497 for (auto &candidate : map) {
498 if (candidate.first && candidate.first->Match(class_name))
499 return candidate.second(valobj, stream, options);
500 }
501 return false;
502 }
503
504 llvm::StringRef prefix, suffix;
505 if (Language *language = Language::FindPlugin(options.GetLanguage()))
506 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
507
508 stream << prefix;
509 stream.Printf("%" PRIu64 " %s%s", value, "key/value pair",
510 value == 1 ? "" : "s");
511 stream << suffix;
512 return true;
513}
514
517 CXXSyntheticChildren *synth, lldb::ValueObjectSP valobj_sp) {
518 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
519 if (!process_sp)
520 return nullptr;
521 AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
522 ObjCLanguageRuntime::Get(*process_sp));
523 if (!runtime)
524 return nullptr;
525
526 CompilerType valobj_type(valobj_sp->GetCompilerType());
527 Flags flags(valobj_type.GetTypeInfo());
528
529 if (flags.IsClear(eTypeIsPointer)) {
531 valobj_sp = valobj_sp->AddressOf(error);
532 if (error.Fail() || !valobj_sp)
533 return nullptr;
534 }
535
537 runtime->GetClassDescriptor(*valobj_sp));
538
539 if (!descriptor || !descriptor->IsValid())
540 return nullptr;
541
542 ConstString class_name(descriptor->GetClassName());
543
544 static const ConstString g_DictionaryI("__NSDictionaryI");
545 static const ConstString g_DictionaryM("__NSDictionaryM");
546 static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
547 static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable");
548 static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM");
549 static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
550 static const ConstString g_Dictionary0("__NSDictionary0");
551 static const ConstString g_DictionaryCF("__CFDictionary");
552 static const ConstString g_DictionaryNSCF("__NSCFDictionary");
553 static const ConstString g_DictionaryCFRef("CFDictionaryRef");
554 static const ConstString g_ConstantDictionary("NSConstantDictionary");
555
556 if (class_name.IsEmpty())
557 return nullptr;
558
559 if (class_name == g_DictionaryI) {
560 return (new NSDictionaryISyntheticFrontEnd(valobj_sp));
561 } else if (class_name == g_ConstantDictionary) {
562 return (new NSConstantDictionarySyntheticFrontEnd(valobj_sp));
563 } else if (class_name == g_DictionaryM || class_name == g_DictionaryMFrozen) {
564 if (runtime->GetFoundationVersion() >= 1437) {
566 } else if (runtime->GetFoundationVersion() >= 1428) {
568 } else {
570 }
571 } else if (class_name == g_DictionaryMLegacy) {
573 } else if (class_name == g_Dictionary1) {
574 return (new NSDictionary1SyntheticFrontEnd(valobj_sp));
575 } else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
576 class_name == g_DictionaryCFRef) {
577 return (new NSCFDictionarySyntheticFrontEnd(valobj_sp));
578 } else {
580 for (auto &candidate : map) {
581 if (candidate.first && candidate.first->Match((class_name)))
582 return candidate.second(synth, valobj_sp);
583 }
584 }
585
586 return nullptr;
587}
588
590 NSDictionaryISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
591 : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_type() {}
592
595 delete m_data_32;
596 m_data_32 = nullptr;
597 delete m_data_64;
598 m_data_64 = nullptr;
599}
600
603 const char *item_name = name.GetCString();
604 uint32_t idx = ExtractIndexFromString(item_name);
605 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
606 return UINT32_MAX;
607 return idx;
608}
609
612 if (!m_data_32 && !m_data_64)
613 return 0;
614 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
615}
616
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)
626 return false;
627 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
629 error.Clear();
630 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
631 if (!process_sp)
632 return false;
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())
646 return false;
647 m_data_ptr = data_location + m_ptr_size;
648 return false;
649}
650
653 return true;
654}
655
656lldb::ValueObjectSP
658 size_t idx) {
659 uint32_t num_children = CalculateNumChildren();
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,
692 lldb::ValueObjectSP()};
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
734 NSCFDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
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 >= CalculateNumChildren())
743 return UINT32_MAX;
744 return idx;
745}
746
749 if (!m_hashtable.IsValid())
750 return 0;
751 return m_hashtable.GetCount();
752}
753
755 m_children.clear();
756 ValueObjectSP valobj_sp = m_backend.GetSP();
757 m_ptr_size = 0;
758 if (!valobj_sp)
759 return false;
760 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
761
762 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
763 if (!process_sp)
764 return false;
765 m_ptr_size = process_sp->GetAddressByteSize();
766 m_order = process_sp->GetByteOrder();
767 return m_hashtable.Update(valobj_sp->GetValueAsUnsigned(0), m_exe_ctx_ref);
768}
769
772 return true;
773}
774
775lldb::ValueObjectSP
777 size_t idx) {
778 lldb::addr_t m_keys_ptr = m_hashtable.GetKeyPointer();
779 lldb::addr_t m_values_ptr = m_hashtable.GetValuePointer();
780
781 const uint32_t num_children = CalculateNumChildren();
782
783 if (idx >= num_children)
784 return lldb::ValueObjectSP();
785
786 if (m_children.empty()) {
787 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
788 if (!process_sp)
789 return lldb::ValueObjectSP();
790
792 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
793
794 uint32_t tries = 0;
795 uint32_t test_idx = 0;
796
797 // Iterate over inferior memory, reading key/value pointers by shifting each
798 // cursor by test_index * m_ptr_size. Returns an empty ValueObject if a read
799 // fails, otherwise, continue until the number of tries matches the number
800 // of childen.
801 while (tries < num_children) {
802 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
803 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
804
805 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
806 if (error.Fail())
807 return lldb::ValueObjectSP();
808 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
809 if (error.Fail())
810 return lldb::ValueObjectSP();
811
812 test_idx++;
813
814 if (!key_at_idx || !val_at_idx)
815 continue;
816 tries++;
817
818 DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
819 lldb::ValueObjectSP()};
820
821 m_children.push_back(descriptor);
822 }
823 }
824
825 if (idx >= m_children.size()) // should never happen
826 return lldb::ValueObjectSP();
827
828 DictionaryItemDescriptor &dict_item = m_children[idx];
829 if (!dict_item.valobj_sp) {
830 if (!m_pair_type.IsValid()) {
831 TargetSP target_sp(m_backend.GetTargetSP());
832 if (!target_sp)
833 return ValueObjectSP();
834 m_pair_type = GetLLDBNSPairType(target_sp);
835 }
836 if (!m_pair_type.IsValid())
837 return ValueObjectSP();
838
839 WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
840
841 switch (m_ptr_size) {
842 case 0: // architecture has no clue - fail
843 return lldb::ValueObjectSP();
844 case 4: {
845 uint32_t *data_ptr = reinterpret_cast<uint32_t *>(buffer_sp->GetBytes());
846 *data_ptr = dict_item.key_ptr;
847 *(data_ptr + 1) = dict_item.val_ptr;
848 } break;
849 case 8: {
850 uint64_t *data_ptr = reinterpret_cast<uint64_t *>(buffer_sp->GetBytes());
851 *data_ptr = dict_item.key_ptr;
852 *(data_ptr + 1) = dict_item.val_ptr;
853 } break;
854 default:
855 lldbassert(false && "pointer size is not 4 nor 8");
856 }
857
858 StreamString idx_name;
859 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
860 DataExtractor data(buffer_sp, m_order, m_ptr_size);
861 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
862 m_exe_ctx_ref, m_pair_type);
863 }
864 return dict_item.valobj_sp;
865}
866
868 NSConstantDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
869 : SyntheticChildrenFrontEnd(*valobj_sp) {}
870
873 const char *item_name = name.GetCString();
874 uint32_t idx = ExtractIndexFromString(item_name);
875 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
876 return UINT32_MAX;
877 return idx;
878}
879
882 return m_size;
883}
884
886 ValueObjectSP valobj_sp = m_backend.GetSP();
887 if (!valobj_sp)
888 return false;
889 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
891 error.Clear();
892 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
893 if (!process_sp)
894 return false;
895 m_ptr_size = process_sp->GetAddressByteSize();
896 m_order = process_sp->GetByteOrder();
897 uint64_t valobj_addr = valobj_sp->GetValueAsUnsigned(0);
898 m_size = process_sp->ReadUnsignedIntegerFromMemory(
899 valobj_addr + 2 * m_ptr_size, m_ptr_size, 0, error);
900 if (error.Fail())
901 return false;
902 m_keys_ptr =
903 process_sp->ReadPointerFromMemory(valobj_addr + 3 * m_ptr_size, error);
904 if (error.Fail())
905 return false;
906 m_objects_ptr =
907 process_sp->ReadPointerFromMemory(valobj_addr + 4 * m_ptr_size, error);
908 return !error.Fail();
909}
910
913 return true;
914}
915
916lldb::ValueObjectSP lldb_private::formatters::
918 uint32_t num_children = CalculateNumChildren();
919
920 if (idx >= num_children)
921 return lldb::ValueObjectSP();
922
923 if (m_children.empty()) {
924 // do the scan phase
925 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
926 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
927 if (!process_sp)
928 return lldb::ValueObjectSP();
929
930 for (unsigned int child = 0; child < num_children; ++child) {
932 key_at_idx = process_sp->ReadPointerFromMemory(
933 m_keys_ptr + child * m_ptr_size, error);
934 if (error.Fail())
935 return lldb::ValueObjectSP();
936 val_at_idx = process_sp->ReadPointerFromMemory(
937 m_objects_ptr + child * m_ptr_size, error);
938 if (error.Fail())
939 return lldb::ValueObjectSP();
940 DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
941 lldb::ValueObjectSP()};
942 m_children.push_back(descriptor);
943 }
944 }
945
946 if (idx >= m_children.size()) // should never happen
947 return lldb::ValueObjectSP();
948
949 DictionaryItemDescriptor &dict_item = m_children[idx];
950 if (!dict_item.valobj_sp) {
951 if (!m_pair_type.IsValid()) {
952 TargetSP target_sp(m_backend.GetTargetSP());
953 if (!target_sp)
954 return ValueObjectSP();
955 m_pair_type = GetLLDBNSPairType(target_sp);
956 }
957 if (!m_pair_type.IsValid())
958 return ValueObjectSP();
959
960 WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
961
962 if (m_ptr_size == 8) {
963 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
964 *data_ptr = dict_item.key_ptr;
965 *(data_ptr + 1) = dict_item.val_ptr;
966 } else {
967 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
968 *data_ptr = dict_item.key_ptr;
969 *(data_ptr + 1) = dict_item.val_ptr;
970 }
971
972 StreamString idx_name;
973 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
974 DataExtractor data(buffer_sp, m_order, m_ptr_size);
975 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
976 m_exe_ctx_ref, m_pair_type);
977 }
978 return dict_item.valobj_sp;
979}
980
982 NSDictionary1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
983 : SyntheticChildrenFrontEnd(*valobj_sp.get()), m_pair(nullptr) {}
984
987 static const ConstString g_zero("[0]");
988 return name == g_zero ? 0 : UINT32_MAX;
989}
990
993 return 1;
994}
995
997 m_pair.reset();
998 return false;
999}
1000
1003 return true;
1004}
1005
1006lldb::ValueObjectSP
1008 size_t idx) {
1009 if (idx != 0)
1010 return lldb::ValueObjectSP();
1011
1012 if (m_pair.get())
1013 return m_pair;
1014
1015 auto process_sp(m_backend.GetProcessSP());
1016 if (!process_sp)
1017 return nullptr;
1018
1019 auto ptr_size = process_sp->GetAddressByteSize();
1020
1021 lldb::addr_t key_ptr =
1022 m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS) + ptr_size;
1023 lldb::addr_t value_ptr = key_ptr + ptr_size;
1024
1025 Status error;
1026
1027 lldb::addr_t value_at_idx = process_sp->ReadPointerFromMemory(key_ptr, error);
1028 if (error.Fail())
1029 return nullptr;
1030 lldb::addr_t key_at_idx = process_sp->ReadPointerFromMemory(value_ptr, error);
1031 if (error.Fail())
1032 return nullptr;
1033
1034 auto pair_type =
1035 GetLLDBNSPairType(process_sp->GetTarget().shared_from_this());
1036
1037 WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * ptr_size, 0));
1038
1039 if (ptr_size == 8) {
1040 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1041 *data_ptr = key_at_idx;
1042 *(data_ptr + 1) = value_at_idx;
1043 } else {
1044 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1045 *data_ptr = key_at_idx;
1046 *(data_ptr + 1) = value_at_idx;
1047 }
1048
1049 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size);
1050 m_pair = CreateValueObjectFromData(
1051 "[0]", data, m_backend.GetExecutionContextRef(), pair_type);
1052
1053 return m_pair;
1054}
1055
1056template <typename D32, typename D64>
1058 GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
1059 : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(),
1060 m_data_32(nullptr), m_data_64(nullptr), m_pair_type() {}
1061
1062template <typename D32, typename D64>
1065 delete m_data_32;
1066 m_data_32 = nullptr;
1067 delete m_data_64;
1068 m_data_64 = nullptr;
1069}
1070
1071template <typename D32, typename D64>
1073 D32, D64>::GetIndexOfChildWithName(ConstString name) {
1074 const char *item_name = name.GetCString();
1075 uint32_t idx = ExtractIndexFromString(item_name);
1076 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1077 return UINT32_MAX;
1078 return idx;
1079}
1080
1081template <typename D32, typename D64>
1082size_t
1084 if (!m_data_32 && !m_data_64)
1085 return 0;
1086 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1087}
1088
1089template <typename D32, typename D64>
1090bool
1092 Update() {
1093 m_children.clear();
1094 ValueObjectSP valobj_sp = m_backend.GetSP();
1095 m_ptr_size = 0;
1096 delete m_data_32;
1097 m_data_32 = nullptr;
1098 delete m_data_64;
1099 m_data_64 = nullptr;
1100 if (!valobj_sp)
1101 return false;
1102 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1103 Status error;
1104 error.Clear();
1105 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1106 if (!process_sp)
1107 return false;
1108 m_ptr_size = process_sp->GetAddressByteSize();
1109 m_order = process_sp->GetByteOrder();
1110 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
1111 if (m_ptr_size == 4) {
1112 m_data_32 = new D32();
1113 process_sp->ReadMemory(data_location, m_data_32, sizeof(D32),
1114 error);
1115 } else {
1116 m_data_64 = new D64();
1117 process_sp->ReadMemory(data_location, m_data_64, sizeof(D64),
1118 error);
1119 }
1120
1121 return error.Success();
1122}
1123
1124template <typename D32, typename D64>
1125bool
1128 return true;
1129}
1130
1131template <typename D32, typename D64>
1132lldb::ValueObjectSP
1134 D32, D64>::GetChildAtIndex(size_t idx) {
1135 lldb::addr_t m_keys_ptr;
1136 lldb::addr_t m_values_ptr;
1137 if (m_data_32) {
1138 uint32_t size = m_data_32->GetSize();
1139 m_keys_ptr = m_data_32->_buffer;
1140 m_values_ptr = m_data_32->_buffer + (m_ptr_size * size);
1141 } else {
1142 uint32_t size = m_data_64->GetSize();
1143 m_keys_ptr = m_data_64->_buffer;
1144 m_values_ptr = m_data_64->_buffer + (m_ptr_size * size);
1145 }
1146
1147 uint32_t num_children = CalculateNumChildren();
1148
1149 if (idx >= num_children)
1150 return lldb::ValueObjectSP();
1151
1152 if (m_children.empty()) {
1153 // do the scan phase
1154 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1155
1156 uint32_t tries = 0;
1157 uint32_t test_idx = 0;
1158
1159 while (tries < num_children) {
1160 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
1161 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
1162 ;
1163 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1164 if (!process_sp)
1165 return lldb::ValueObjectSP();
1166 Status error;
1167 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1168 if (error.Fail())
1169 return lldb::ValueObjectSP();
1170 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1171 if (error.Fail())
1172 return lldb::ValueObjectSP();
1173
1174 test_idx++;
1175
1176 if (!key_at_idx || !val_at_idx)
1177 continue;
1178 tries++;
1179
1180 DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
1181 lldb::ValueObjectSP()};
1182
1183 m_children.push_back(descriptor);
1184 }
1185 }
1186
1187 if (idx >= m_children.size()) // should never happen
1188 return lldb::ValueObjectSP();
1189
1190 DictionaryItemDescriptor &dict_item = m_children[idx];
1191 if (!dict_item.valobj_sp) {
1192 if (!m_pair_type.IsValid()) {
1193 TargetSP target_sp(m_backend.GetTargetSP());
1194 if (!target_sp)
1195 return ValueObjectSP();
1196 m_pair_type = GetLLDBNSPairType(target_sp);
1197 }
1198 if (!m_pair_type.IsValid())
1199 return ValueObjectSP();
1200
1201 WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
1202
1203 if (m_ptr_size == 8) {
1204 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1205 *data_ptr = dict_item.key_ptr;
1206 *(data_ptr + 1) = dict_item.val_ptr;
1207 } else {
1208 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1209 *data_ptr = dict_item.key_ptr;
1210 *(data_ptr + 1) = dict_item.val_ptr;
1211 }
1212
1213 StreamString idx_name;
1214 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
1215 DataExtractor data(buffer_sp, m_order, m_ptr_size);
1216 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
1217 m_exe_ctx_ref, m_pair_type);
1218 }
1219 return dict_item.valobj_sp;
1220}
1221
1223 NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
1224 : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_pair_type() {}
1225
1228 delete m_data_32;
1229 m_data_32 = nullptr;
1230 delete m_data_64;
1231 m_data_64 = nullptr;
1232}
1233
1234size_t
1237 const char *item_name = name.GetCString();
1238 uint32_t idx = ExtractIndexFromString(item_name);
1239 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
1240 return UINT32_MAX;
1241 return idx;
1242}
1243
1244size_t
1247 if (!m_data_32 && !m_data_64)
1248 return 0;
1249 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1250}
1251
1252bool
1255 m_children.clear();
1256 ValueObjectSP valobj_sp = m_backend.GetSP();
1257 m_ptr_size = 0;
1258 delete m_data_32;
1259 m_data_32 = nullptr;
1260 delete m_data_64;
1261 m_data_64 = nullptr;
1262 if (!valobj_sp)
1263 return false;
1264 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1265 Status error;
1266 error.Clear();
1267 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
1268 if (!process_sp)
1269 return false;
1270 m_ptr_size = process_sp->GetAddressByteSize();
1271 m_order = process_sp->GetByteOrder();
1272 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
1273 if (m_ptr_size == 4) {
1274 m_data_32 = new DataDescriptor_32();
1275 process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
1276 error);
1277 } else {
1278 m_data_64 = new DataDescriptor_64();
1279 process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
1280 error);
1281 }
1282
1283 return error.Success();
1284}
1285
1286bool
1289 return true;
1290}
1291
1292lldb::ValueObjectSP
1295 lldb::addr_t m_keys_ptr =
1296 (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr);
1297 lldb::addr_t m_values_ptr =
1298 (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
1299
1300 uint32_t num_children = CalculateNumChildren();
1301
1302 if (idx >= num_children)
1303 return lldb::ValueObjectSP();
1304
1305 if (m_children.empty()) {
1306 // do the scan phase
1307 lldb::addr_t key_at_idx = 0, val_at_idx = 0;
1308
1309 uint32_t tries = 0;
1310 uint32_t test_idx = 0;
1311
1312 while (tries < num_children) {
1313 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
1314 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
1315 ;
1316 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1317 if (!process_sp)
1318 return lldb::ValueObjectSP();
1319 Status error;
1320 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
1321 if (error.Fail())
1322 return lldb::ValueObjectSP();
1323 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
1324 if (error.Fail())
1325 return lldb::ValueObjectSP();
1326
1327 test_idx++;
1328
1329 if (!key_at_idx || !val_at_idx)
1330 continue;
1331 tries++;
1332
1333 DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
1334 lldb::ValueObjectSP()};
1335
1336 m_children.push_back(descriptor);
1337 }
1338 }
1339
1340 if (idx >= m_children.size()) // should never happen
1341 return lldb::ValueObjectSP();
1342
1343 DictionaryItemDescriptor &dict_item = m_children[idx];
1344 if (!dict_item.valobj_sp) {
1345 if (!m_pair_type.IsValid()) {
1346 TargetSP target_sp(m_backend.GetTargetSP());
1347 if (!target_sp)
1348 return ValueObjectSP();
1349 m_pair_type = GetLLDBNSPairType(target_sp);
1350 }
1351 if (!m_pair_type.IsValid())
1352 return ValueObjectSP();
1353
1354 WritableDataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
1355
1356 if (m_ptr_size == 8) {
1357 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1358 *data_ptr = dict_item.key_ptr;
1359 *(data_ptr + 1) = dict_item.val_ptr;
1360 } else {
1361 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1362 *data_ptr = dict_item.key_ptr;
1363 *(data_ptr + 1) = dict_item.val_ptr;
1364 }
1365
1366 StreamString idx_name;
1367 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
1368 DataExtractor data(buffer_sp, m_order, m_ptr_size);
1369 dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
1370 m_exe_ctx_ref, m_pair_type);
1371 }
1372 return dict_item.valobj_sp;
1373}
1374
1376 ValueObject &, Stream &, const TypeSummaryOptions &);
1377
1379 ValueObject &, Stream &, const TypeSummaryOptions &);
static llvm::raw_ostream & error(Stream &strm)
#define lldbassert(x)
Definition: LLDBAssert.h:13
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 size_t CalculateNumChildren(CompilerType container_type, CompilerType element_type, lldb_private::ExecutionContextScope *exe_scope=nullptr)
Definition: VectorType.cpp:172
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:39
bool IsEmpty() const
Test for empty string.
Definition: ConstString.h:306
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:204
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:218
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:53
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:335
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:1941
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:107
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)
NSCFDictionarySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
std::vector< DictionaryItemDescriptor > m_children
size_t GetIndexOfChildWithName(ConstString name) override
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
NSDictionary1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
size_t GetIndexOfChildWithName(ConstString name) override
std::vector< DictionaryItemDescriptor > m_children
NSDictionaryISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override
size_t GetIndexOfChildWithName(ConstString name) 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:74
#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
@ eLanguageTypeC
Non-standardized C, such as K&R.
ByteOrder
Byte ordering definitions.
@ eByteOrderInvalid
uint64_t addr_t
Definition: lldb-types.h:79
std::function< bool(ValueObject &, Stream &, const TypeSummaryOptions &)> Callback
Definition: TypeSummary.h:311