11#include "clang/AST/DeclCXX.h"
40 return class_name.
GetStringRef().startswith(m_prefix.GetStringRef());
48 return (class_name == m_name);
74 static constexpr llvm::StringLiteral g_lldb_autogen_nspair(
"__lldb_autogen_nspair");
76 compiler_type = scratch_ts_sp->GetTypeForIdentifier<clang::CXXRecordDecl>(g_lldb_autogen_nspair);
79 compiler_type = scratch_ts_sp->CreateRecordType(
81 g_lldb_autogen_nspair, llvm::to_underlying(clang::TagTypeKind::Struct),
110 bool Update()
override;
112 bool MightHaveChildren()
override;
114 size_t GetIndexOfChildWithName(
ConstString name)
override;
134 uint8_t m_ptr_size = 8;
151 bool Update()
override;
153 bool MightHaveChildren()
override;
155 size_t GetIndexOfChildWithName(
ConstString name)
override;
160 uint8_t m_ptr_size = 8;
162 unsigned int m_size = 0;
183 bool Update()
override;
185 bool MightHaveChildren()
override;
187 size_t GetIndexOfChildWithName(
ConstString name)
override;
197 uint8_t m_ptr_size = 8;
216 bool Update()
override;
218 bool MightHaveChildren()
override;
220 size_t GetIndexOfChildWithName(
ConstString name)
override;
226template <
typename D32,
typename D64>
237 bool Update()
override;
239 bool MightHaveChildren()
override;
241 size_t GetIndexOfChildWithName(
ConstString name)
override;
251 uint8_t m_ptr_size = 8;
259namespace Foundation1100 {
270 bool Update()
override;
272 bool MightHaveChildren()
override;
274 size_t GetIndexOfChildWithName(
ConstString name)
override;
302 uint8_t m_ptr_size = 8;
311namespace Foundation1428 {
313 struct DataDescriptor_32 {
318 uint64_t GetSize() {
return _size; }
321 struct DataDescriptor_64 {
326 uint64_t GetSize() {
return _size; }
334namespace Foundation1437 {
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
347 struct DataDescriptor_32 {
355 return (
_szidx) >= NSDictionaryNumSizeBuckets ?
356 0 : NSDictionaryCapacities[
_szidx];
360 struct DataDescriptor_64 {
377 template <
typename DD>
383 DD descriptor = DD();
384 process.
ReadMemory(start_of_descriptor, &descriptor,
sizeof(descriptor),
389 return descriptor._used;
396 return __NSDictionaryMSize_Impl<DataDescriptor_32>(process, valobj_addr,
399 return __NSDictionaryMSize_Impl<DataDescriptor_64>(process, valobj_addr,
408template <
bool name_entries>
411 static constexpr llvm::StringLiteral g_TypeHint(
"NSDictionary");
424 if (!descriptor || !descriptor->IsValid())
427 uint32_t ptr_size = process_sp->GetAddressByteSize();
428 bool is_64bit = (ptr_size == 8);
437 ConstString class_name(descriptor->GetClassName());
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");
454 if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) {
456 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
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);
468 }
else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy ||
469 class_name == g_DictionaryMFrozen) {
471 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
477 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
479 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
483 }
else if (class_name == g_Dictionary1) {
485 }
else if (class_name == g_Dictionary0) {
487 }
else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
488 class_name == g_DictionaryCFRef) {
491 if (!cfbh.
Update(valobj_addr, exe_ctx))
496 for (
auto &candidate : map) {
497 if (candidate.first && candidate.first->Match(class_name))
498 return candidate.second(valobj, stream, options);
503 llvm::StringRef prefix, suffix;
505 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
508 stream.
Printf(
"%" PRIu64
" %s%s", value,
"key/value pair",
509 value == 1 ?
"" :
"s");
528 if (flags.
IsClear(eTypeIsPointer)) {
530 valobj_sp = valobj_sp->AddressOf(
error);
531 if (
error.Fail() || !valobj_sp)
538 if (!descriptor || !descriptor->IsValid())
541 ConstString class_name(descriptor->GetClassName());
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");
558 if (class_name == g_DictionaryI) {
560 }
else if (class_name == g_ConstantDictionary) {
562 }
else if (class_name == g_DictionaryM || class_name == g_DictionaryMFrozen) {
570 }
else if (class_name == g_DictionaryMLegacy) {
572 }
else if (class_name == g_Dictionary1) {
574 }
else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
575 class_name == g_DictionaryCFRef) {
579 for (
auto &candidate : map) {
580 if (candidate.first && candidate.first->Match((class_name)))
581 return candidate.second(synth, valobj_sp);
611 if (!m_data_32 && !m_data_64)
613 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
626 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
632 m_ptr_size = process_sp->GetAddressByteSize();
633 m_order = process_sp->GetByteOrder();
634 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
635 if (m_ptr_size == 4) {
646 m_data_ptr = data_location + m_ptr_size;
660 if (idx >= num_children)
663 if (m_children.empty()) {
668 uint32_t test_idx = 0;
670 while (tries < num_children) {
671 key_at_idx = m_data_ptr + (2 * test_idx * m_ptr_size);
672 val_at_idx = key_at_idx + m_ptr_size;
673 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
677 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
680 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
686 if (!key_at_idx || !val_at_idx)
693 m_children.push_back(descriptor);
697 if (idx >= m_children.size())
702 if (!m_pair_type.IsValid()) {
703 TargetSP target_sp(m_backend.GetTargetSP());
708 if (!m_pair_type.IsValid())
713 if (m_ptr_size == 8) {
714 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
716 *(data_ptr + 1) = dict_item.
val_ptr;
718 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
720 *(data_ptr + 1) = dict_item.
val_ptr;
724 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
727 m_exe_ctx_ref, m_pair_type);
748 if (!m_hashtable.IsValid())
750 return m_hashtable.GetCount();
759 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
764 m_ptr_size = process_sp->GetAddressByteSize();
765 m_order = process_sp->GetByteOrder();
766 return m_hashtable.Update(valobj_sp->GetValueAsUnsigned(0), m_exe_ctx_ref);
778 lldb::addr_t m_values_ptr = m_hashtable.GetValuePointer();
782 if (idx >= num_children)
785 if (m_children.empty()) {
786 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
794 uint32_t test_idx = 0;
800 while (tries < num_children) {
801 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
802 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
804 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
807 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
813 if (!key_at_idx || !val_at_idx)
820 m_children.push_back(descriptor);
824 if (idx >= m_children.size())
829 if (!m_pair_type.IsValid()) {
830 TargetSP target_sp(m_backend.GetTargetSP());
835 if (!m_pair_type.IsValid())
840 switch (m_ptr_size) {
844 uint32_t *data_ptr =
reinterpret_cast<uint32_t *
>(buffer_sp->GetBytes());
846 *(data_ptr + 1) = dict_item.
val_ptr;
849 uint64_t *data_ptr =
reinterpret_cast<uint64_t *
>(buffer_sp->GetBytes());
851 *(data_ptr + 1) = dict_item.
val_ptr;
854 lldbassert(
false &&
"pointer size is not 4 nor 8");
858 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
861 m_exe_ctx_ref, m_pair_type);
888 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
894 m_ptr_size = process_sp->GetAddressByteSize();
895 m_order = process_sp->GetByteOrder();
896 uint64_t valobj_addr = valobj_sp->GetValueAsUnsigned(0);
897 m_size = process_sp->ReadUnsignedIntegerFromMemory(
898 valobj_addr + 2 * m_ptr_size, m_ptr_size, 0,
error);
902 process_sp->ReadPointerFromMemory(valobj_addr + 3 * m_ptr_size,
error);
906 process_sp->ReadPointerFromMemory(valobj_addr + 4 * m_ptr_size,
error);
907 return !
error.Fail();
919 if (idx >= num_children)
922 if (m_children.empty()) {
925 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
929 for (
unsigned int child = 0; child < num_children; ++child) {
931 key_at_idx = process_sp->ReadPointerFromMemory(
932 m_keys_ptr + child * m_ptr_size,
error);
935 val_at_idx = process_sp->ReadPointerFromMemory(
936 m_objects_ptr + child * m_ptr_size,
error);
941 m_children.push_back(descriptor);
945 if (idx >= m_children.size())
950 if (!m_pair_type.IsValid()) {
951 TargetSP target_sp(m_backend.GetTargetSP());
956 if (!m_pair_type.IsValid())
961 if (m_ptr_size == 8) {
962 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
964 *(data_ptr + 1) = dict_item.
val_ptr;
966 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
968 *(data_ptr + 1) = dict_item.
val_ptr;
972 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
975 m_exe_ctx_ref, m_pair_type);
1014 auto process_sp(m_backend.GetProcessSP());
1018 auto ptr_size = process_sp->GetAddressByteSize();
1038 if (ptr_size == 8) {
1039 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1040 *data_ptr = key_at_idx;
1041 *(data_ptr + 1) = value_at_idx;
1043 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1044 *data_ptr = key_at_idx;
1045 *(data_ptr + 1) = value_at_idx;
1048 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size);
1049 m_pair = CreateValueObjectFromData(
1050 "[0]", data, m_backend.GetExecutionContextRef(), pair_type);
1055template <
typename D32,
typename D64>
1059 m_data_32(nullptr), m_data_64(nullptr), m_pair_type() {}
1061template <
typename D32,
typename D64>
1065 m_data_32 =
nullptr;
1067 m_data_64 =
nullptr;
1070template <
typename D32,
typename D64>
1080template <
typename D32,
typename D64>
1083 if (!m_data_32 && !m_data_64)
1085 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1088template <
typename D32,
typename D64>
1096 m_data_32 =
nullptr;
1098 m_data_64 =
nullptr;
1101 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1107 m_ptr_size = process_sp->GetAddressByteSize();
1108 m_order = process_sp->GetByteOrder();
1109 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
1110 if (m_ptr_size == 4) {
1111 m_data_32 =
new D32();
1112 process_sp->ReadMemory(data_location, m_data_32,
sizeof(D32),
1115 m_data_64 =
new D64();
1116 process_sp->ReadMemory(data_location, m_data_64,
sizeof(D64),
1120 return error.Success();
1123template <
typename D32,
typename D64>
1130template <
typename D32,
typename D64>
1133 D32, D64>::GetChildAtIndex(
size_t idx) {
1137 uint32_t size = m_data_32->GetSize();
1138 m_keys_ptr = m_data_32->_buffer;
1139 m_values_ptr = m_data_32->_buffer + (m_ptr_size * size);
1141 uint32_t size = m_data_64->GetSize();
1142 m_keys_ptr = m_data_64->_buffer;
1143 m_values_ptr = m_data_64->_buffer + (m_ptr_size * size);
1148 if (idx >= num_children)
1151 if (m_children.empty()) {
1156 uint32_t test_idx = 0;
1158 while (tries < num_children) {
1159 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
1160 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
1162 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1166 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
1169 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
1175 if (!key_at_idx || !val_at_idx)
1182 m_children.push_back(descriptor);
1186 if (idx >= m_children.size())
1191 if (!m_pair_type.IsValid()) {
1192 TargetSP target_sp(m_backend.GetTargetSP());
1197 if (!m_pair_type.IsValid())
1202 if (m_ptr_size == 8) {
1203 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1204 *data_ptr = dict_item.
key_ptr;
1205 *(data_ptr + 1) = dict_item.
val_ptr;
1207 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1208 *data_ptr = dict_item.
key_ptr;
1209 *(data_ptr + 1) = dict_item.
val_ptr;
1213 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
1216 m_exe_ctx_ref, m_pair_type);
1228 m_data_32 =
nullptr;
1230 m_data_64 =
nullptr;
1246 if (!m_data_32 && !m_data_64)
1248 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
1258 m_data_32 =
nullptr;
1260 m_data_64 =
nullptr;
1263 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
1269 m_ptr_size = process_sp->GetAddressByteSize();
1270 m_order = process_sp->GetByteOrder();
1271 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
1272 if (m_ptr_size == 4) {
1282 return error.Success();
1295 (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr);
1297 (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
1301 if (idx >= num_children)
1304 if (m_children.empty()) {
1309 uint32_t test_idx = 0;
1311 while (tries < num_children) {
1312 key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
1313 val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
1315 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
1319 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
1322 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
1328 if (!key_at_idx || !val_at_idx)
1335 m_children.push_back(descriptor);
1339 if (idx >= m_children.size())
1344 if (!m_pair_type.IsValid()) {
1345 TargetSP target_sp(m_backend.GetTargetSP());
1350 if (!m_pair_type.IsValid())
1355 if (m_ptr_size == 8) {
1356 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1357 *data_ptr = dict_item.
key_ptr;
1358 *(data_ptr + 1) = dict_item.
val_ptr;
1360 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1361 *data_ptr = dict_item.
key_ptr;
1362 *(data_ptr + 1) = dict_item.
val_ptr;
1366 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
1369 m_exe_ctx_ref, m_pair_type);
static llvm::raw_ostream & error(Stream &strm)
static CompilerType GetLLDBNSPairType(TargetSP target_sp)
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 ...
uint32_t GetFoundationVersion()
bool Update(lldb::addr_t addr, ExecutionContextRef exe_ctx_rf)
std::function< SyntheticChildrenFrontEnd *(CXXSyntheticChildren *, lldb::ValueObjectSP)> CreateFrontEndCallback
Generic representation of a type in a programming language.
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
A uniqued constant string class.
bool IsEmpty() const
Test for empty string.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
const char * GetCString() const
Get the string value as a C string.
A subclass of DataBuffer that stores a data buffer on the heap.
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.
bool IsClear(ValueType bit) const
Test a single flag bit to see if it is clear (zero).
static Language * FindPlugin(lldb::LanguageType language)
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.
virtual size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, Status &error)
Read of memory from a process.
uint32_t GetAddressByteSize() const
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.
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
lldb::LanguageType GetLanguage() const
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
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
@ eLanguageTypeC
Non-standardized C, such as K&R.
std::shared_ptr< lldb_private::Process > ProcessSP
ByteOrder
Byte ordering definitions.
std::shared_ptr< lldb_private::TypeSystemClang > TypeSystemClangSP
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
std::shared_ptr< lldb_private::Target > TargetSP