11#include "clang/AST/DeclCXX.h"
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>(
77 scratch_ts_sp->getASTContext(), g_lldb_autogen_nspair);
80 compiler_type = scratch_ts_sp->CreateRecordType(
82 g_lldb_autogen_nspair, llvm::to_underlying(clang::TagTypeKind::Struct),
99namespace lldb_private {
219template <
typename D32,
typename D64>
302 struct DataDescriptor_32 {
307 uint64_t GetSize() {
return _size; }
310 struct DataDescriptor_64 {
315 uint64_t GetSize() {
return _size; }
325 0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723,
326 2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607,
327 214519, 346607, 561109, 907759, 1468927, 2376191, 3845119,
328 6221311, 10066421, 16287743, 26354171, 42641881, 68996069,
329 111638519, 180634607, 292272623, 472907251
336 struct DataDescriptor_32 {
349 struct DataDescriptor_64 {
366 template <
typename DD>
372 DD descriptor = DD();
373 process.
ReadMemory(start_of_descriptor, &descriptor,
sizeof(descriptor),
378 return descriptor._used;
397template <
bool name_entries>
400 static constexpr llvm::StringLiteral g_TypeHint(
"NSDictionary");
413 if (!descriptor || !descriptor->IsValid())
416 uint32_t ptr_size = process_sp->GetAddressByteSize();
417 bool is_64bit = (ptr_size == 8);
426 ConstString class_name(descriptor->GetClassName());
428 static const ConstString g_DictionaryI(
"__NSDictionaryI");
429 static const ConstString g_DictionaryM(
"__NSDictionaryM");
430 static const ConstString g_DictionaryMLegacy(
"__NSDictionaryM_Legacy");
431 static const ConstString g_DictionaryMImmutable(
"__NSDictionaryM_Immutable");
432 static const ConstString g_DictionaryMFrozen(
"__NSFrozenDictionaryM");
433 static const ConstString g_Dictionary1(
"__NSSingleEntryDictionaryI");
434 static const ConstString g_Dictionary0(
"__NSDictionary0");
435 static const ConstString g_DictionaryCF(
"__CFDictionary");
436 static const ConstString g_DictionaryNSCF(
"__NSCFDictionary");
437 static const ConstString g_DictionaryCFRef(
"CFDictionaryRef");
438 static const ConstString g_ConstantDictionary(
"NSConstantDictionary");
443 if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) {
445 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
450 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
451 }
else if (class_name == g_ConstantDictionary) {
453 value = process_sp->ReadUnsignedIntegerFromMemory(
454 valobj_addr + 2 * ptr_size, ptr_size, 0,
error);
457 }
else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy ||
458 class_name == g_DictionaryMFrozen) {
460 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
466 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
468 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
472 }
else if (class_name == g_Dictionary1) {
474 }
else if (class_name == g_Dictionary0) {
476 }
else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
477 class_name == g_DictionaryCFRef) {
480 if (!cfbh.
Update(valobj_addr, exe_ctx))
485 for (
auto &candidate : map) {
486 if (candidate.first && candidate.first->Match(class_name))
487 return candidate.second(valobj, stream, options);
492 llvm::StringRef prefix, suffix;
494 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
497 stream.
Printf(
"%" PRIu64
" %s%s", value,
"key/value pair",
498 value == 1 ?
"" :
"s");
517 if (flags.
IsClear(eTypeIsPointer)) {
519 valobj_sp = valobj_sp->AddressOf(
error);
520 if (
error.Fail() || !valobj_sp)
527 if (!descriptor || !descriptor->IsValid())
530 ConstString class_name(descriptor->GetClassName());
532 static const ConstString g_DictionaryI(
"__NSDictionaryI");
533 static const ConstString g_DictionaryM(
"__NSDictionaryM");
534 static const ConstString g_Dictionary1(
"__NSSingleEntryDictionaryI");
535 static const ConstString g_DictionaryImmutable(
"__NSDictionaryM_Immutable");
536 static const ConstString g_DictionaryMFrozen(
"__NSFrozenDictionaryM");
537 static const ConstString g_DictionaryMLegacy(
"__NSDictionaryM_Legacy");
538 static const ConstString g_Dictionary0(
"__NSDictionary0");
539 static const ConstString g_DictionaryCF(
"__CFDictionary");
540 static const ConstString g_DictionaryNSCF(
"__NSCFDictionary");
541 static const ConstString g_DictionaryCFRef(
"CFDictionaryRef");
542 static const ConstString g_ConstantDictionary(
"NSConstantDictionary");
547 if (class_name == g_DictionaryI) {
549 }
else if (class_name == g_ConstantDictionary) {
551 }
else if (class_name == g_DictionaryM || class_name == g_DictionaryMFrozen) {
559 }
else if (class_name == g_DictionaryMLegacy) {
561 }
else if (class_name == g_Dictionary1) {
563 }
else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
564 class_name == g_DictionaryCFRef) {
568 for (
auto &candidate : map) {
569 if (candidate.first && candidate.first->Match((class_name)))
570 return candidate.second(synth, valobj_sp);
593 return llvm::createStringError(
"Type has no child named '%s'",
596 uint32_t idx = *optional_idx;
598 return llvm::createStringError(
"Type has no child named '%s'",
627 m_ptr_size = process_sp->GetAddressByteSize();
628 m_order = process_sp->GetByteOrder();
629 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
650 if (idx >= num_children)
658 uint32_t test_idx = 0;
660 while (tries < num_children) {
667 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
670 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
676 if (!key_at_idx || !val_at_idx)
704 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
706 *(data_ptr + 1) = dict_item.
val_ptr;
708 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
710 *(data_ptr + 1) = dict_item.
val_ptr;
714 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
731 return llvm::createStringError(
"Type has no child named '%s'",
734 uint32_t idx = *optional_idx;
736 return llvm::createStringError(
"Type has no child named '%s'",
760 m_ptr_size = process_sp->GetAddressByteSize();
761 m_order = process_sp->GetByteOrder();
775 if (idx >= num_children)
787 uint32_t test_idx = 0;
793 while (tries < num_children) {
794 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
795 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
797 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
800 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
806 if (!key_at_idx || !val_at_idx)
837 uint32_t *data_ptr =
reinterpret_cast<uint32_t *
>(buffer_sp->GetBytes());
839 *(data_ptr + 1) = dict_item.
val_ptr;
842 uint64_t *data_ptr =
reinterpret_cast<uint64_t *
>(buffer_sp->GetBytes());
844 *(data_ptr + 1) = dict_item.
val_ptr;
847 lldbassert(
false &&
"pointer size is not 4 nor 8");
851 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
863llvm::Expected<size_t>
868 return llvm::createStringError(
"Type has no child named '%s'",
871 uint32_t idx = *optional_idx;
873 return llvm::createStringError(
"Type has no child named '%s'",
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(
902 process_sp->ReadPointerFromMemory(valobj_addr + 3 *
m_ptr_size,
error);
906 process_sp->ReadPointerFromMemory(valobj_addr + 4 *
m_ptr_size,
error);
916 if (idx >= num_children)
926 for (
unsigned int child = 0; child < num_children; ++child) {
928 key_at_idx = process_sp->ReadPointerFromMemory(
932 val_at_idx = process_sp->ReadPointerFromMemory(
959 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
961 *(data_ptr + 1) = dict_item.
val_ptr;
963 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
965 *(data_ptr + 1) = dict_item.
val_ptr;
969 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
986 return llvm::createStringError(
"Type has no child named '%s'",
1010 auto process_sp(
m_backend.GetProcessSP());
1014 auto ptr_size = process_sp->GetAddressByteSize();
1034 if (ptr_size == 8) {
1035 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1036 *data_ptr = key_at_idx;
1037 *(data_ptr + 1) = value_at_idx;
1039 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1040 *data_ptr = key_at_idx;
1041 *(data_ptr + 1) = value_at_idx;
1044 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size);
1046 "[0]", data,
m_backend.GetExecutionContextRef(), pair_type);
1051template <
typename D32,
typename D64>
1057template <
typename D32,
typename D64>
1062 m_data_32 =
nullptr;
1064 m_data_64 =
nullptr;
1067template <
typename D32,
typename D64>
1068llvm::Expected<size_t>
1072 if (!optional_idx) {
1073 return llvm::createStringError(
"Type has no child named '%s'",
1076 uint32_t idx = *optional_idx;
1078 return llvm::createStringError(
"Type has no child named '%s'",
1083template <
typename D32,
typename D64>
1084llvm::Expected<uint32_t>
1092template <
typename D32,
typename D64>
1111 m_ptr_size = process_sp->GetAddressByteSize();
1112 m_order = process_sp->GetByteOrder();
1113 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
1116 process_sp->ReadMemory(data_location,
m_data_32,
sizeof(D32),
1120 process_sp->ReadMemory(data_location,
m_data_64,
sizeof(D64),
1128template <
typename D32,
typename D64>
1146 if (idx >= num_children)
1154 uint32_t test_idx = 0;
1156 while (tries < num_children) {
1157 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1158 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1164 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
1167 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
1173 if (!key_at_idx || !val_at_idx)
1201 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1202 *data_ptr = dict_item.
key_ptr;
1203 *(data_ptr + 1) = dict_item.
val_ptr;
1205 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1206 *data_ptr = dict_item.
key_ptr;
1207 *(data_ptr + 1) = dict_item.
val_ptr;
1211 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
1234 if (!optional_idx) {
1235 return llvm::createStringError(
"Type has no child named '%s'",
1238 uint32_t idx = *optional_idx;
1240 return llvm::createStringError(
"Type has no child named '%s'",
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;
1296 if (idx >= num_children)
1304 uint32_t test_idx = 0;
1306 while (tries < num_children) {
1307 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1308 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1314 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
1317 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
1323 if (!key_at_idx || !val_at_idx)
1351 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1352 *data_ptr = dict_item.
key_ptr;
1353 *(data_ptr + 1) = dict_item.
val_ptr;
1355 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1356 *data_ptr = dict_item.
key_ptr;
1357 *(data_ptr + 1) = dict_item.
val_ptr;
1361 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
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.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
bool IsEmpty() const
Test for empty string.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
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.
uint32_t CalculateNumChildrenIgnoringErrors(uint32_t max=UINT32_MAX)
lldb::ValueObjectSP CreateValueObjectFromData(llvm::StringRef name, const DataExtractor &data, const ExecutionContext &exe_ctx, CompilerType type)
SyntheticChildrenFrontEnd(ValueObject &backend)
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.
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
@ 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