11#include "clang/AST/DeclCXX.h"
19#include "llvm/Support/ErrorExtras.h"
41 llvm::StringRef class_name) {
42 return class_name.starts_with(
m_prefix);
49 llvm::StringRef class_name) {
50 return (class_name ==
m_name);
76 static constexpr llvm::StringLiteral g_lldb_autogen_nspair(
"__lldb_autogen_nspair");
78 compiler_type = scratch_ts_sp->GetTypeForIdentifier<clang::CXXRecordDecl>(
79 scratch_ts_sp->getASTContext(), g_lldb_autogen_nspair);
82 compiler_type = scratch_ts_sp->CreateRecordType(
100namespace lldb_private {
214template <
typename D32,
typename D64>
293 struct DataDescriptor_32 {
298 uint64_t GetSize() {
return _size; }
301 struct DataDescriptor_64 {
306 uint64_t GetSize() {
return _size; }
316 0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723,
317 2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607,
318 214519, 346607, 561109, 907759, 1468927, 2376191, 3845119,
319 6221311, 10066421, 16287743, 26354171, 42641881, 68996069,
320 111638519, 180634607, 292272623, 472907251
327 struct DataDescriptor_32 {
340 struct DataDescriptor_64 {
357 template <
typename DD>
363 DD descriptor = DD();
364 process.
ReadMemory(start_of_descriptor, &descriptor,
sizeof(descriptor),
369 return descriptor._used;
388template <
bool name_entries>
391 static constexpr llvm::StringLiteral g_TypeHint(
"NSDictionary");
404 if (!descriptor || !descriptor->IsValid())
407 uint32_t ptr_size = process_sp->GetAddressByteSize();
408 bool is_64bit = (ptr_size == 8);
417 llvm::StringRef class_name(descriptor->GetClassName());
419 static constexpr llvm::StringLiteral g_DictionaryI(
"__NSDictionaryI");
420 static constexpr llvm::StringLiteral g_DictionaryM(
"__NSDictionaryM");
421 static constexpr llvm::StringLiteral g_DictionaryMLegacy(
422 "__NSDictionaryM_Legacy");
423 static constexpr llvm::StringLiteral g_DictionaryMImmutable(
424 "__NSDictionaryM_Immutable");
425 static constexpr llvm::StringLiteral g_DictionaryMFrozen(
426 "__NSFrozenDictionaryM");
427 static constexpr llvm::StringLiteral g_Dictionary1(
428 "__NSSingleEntryDictionaryI");
429 static constexpr llvm::StringLiteral g_Dictionary0(
"__NSDictionary0");
430 static constexpr llvm::StringLiteral g_DictionaryCF(
"__CFDictionary");
431 static constexpr llvm::StringLiteral g_DictionaryNSCF(
"__NSCFDictionary");
432 static constexpr llvm::StringLiteral g_DictionaryCFRef(
"CFDictionaryRef");
433 static constexpr llvm::StringLiteral g_ConstantDictionary(
434 "NSConstantDictionary");
436 if (class_name.empty())
439 if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) {
441 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
446 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
447 }
else if (class_name == g_ConstantDictionary) {
449 value = process_sp->ReadUnsignedIntegerFromMemory(
450 valobj_addr + 2 * ptr_size, ptr_size, 0,
error);
453 }
else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy ||
454 class_name == g_DictionaryMFrozen) {
456 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
462 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
464 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
468 }
else if (class_name == g_Dictionary1) {
470 }
else if (class_name == g_Dictionary0) {
472 }
else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
473 class_name == g_DictionaryCFRef) {
476 if (!cfbh.
Update(valobj_addr, exe_ctx))
481 for (
auto &candidate : map) {
482 if (candidate.first && candidate.first->Match(class_name))
483 return candidate.second(valobj, stream, options);
488 llvm::StringRef prefix, suffix;
490 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
493 stream.
Printf(
"%" PRIu64
" %s%s", value,
"key/value pair",
494 value == 1 ?
"" :
"s");
511 Flags flags(valobj_type.GetTypeInfo());
513 if (flags.IsClear(eTypeIsPointer)) {
515 valobj_sp = valobj_sp->AddressOf(
error);
516 if (
error.Fail() || !valobj_sp)
523 if (!descriptor || !descriptor->IsValid())
526 llvm::StringRef class_name(descriptor->GetClassName());
528 static constexpr llvm::StringLiteral g_DictionaryI(
"__NSDictionaryI");
529 static constexpr llvm::StringLiteral g_DictionaryM(
"__NSDictionaryM");
530 static constexpr llvm::StringLiteral g_Dictionary1(
531 "__NSSingleEntryDictionaryI");
532 static constexpr llvm::StringLiteral g_DictionaryMFrozen(
533 "__NSFrozenDictionaryM");
534 static constexpr llvm::StringLiteral g_DictionaryMLegacy(
535 "__NSDictionaryM_Legacy");
536 static constexpr llvm::StringLiteral g_DictionaryCF(
"__CFDictionary");
537 static constexpr llvm::StringLiteral g_DictionaryNSCF(
"__NSCFDictionary");
538 static constexpr llvm::StringLiteral g_DictionaryCFRef(
"CFDictionaryRef");
539 static constexpr llvm::StringLiteral g_ConstantDictionary(
540 "NSConstantDictionary");
542 if (class_name.empty())
545 if (class_name == g_DictionaryI) {
547 }
else if (class_name == g_ConstantDictionary) {
548 return (
new NSConstantDictionarySyntheticFrontEnd(valobj_sp));
549 }
else if (class_name == g_DictionaryM || class_name == g_DictionaryMFrozen) {
555 return (
new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp));
557 }
else if (class_name == g_DictionaryMLegacy) {
558 return (
new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp));
559 }
else if (class_name == g_Dictionary1) {
560 return (
new NSDictionary1SyntheticFrontEnd(valobj_sp));
561 }
else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
562 class_name == g_DictionaryCFRef) {
563 return (
new NSCFDictionarySyntheticFrontEnd(valobj_sp));
566 for (
auto &candidate : map) {
567 if (candidate.first && candidate.first->Match((class_name)))
568 return candidate.second(synth, valobj_sp);
611 m_ptr_size = process_sp->GetAddressByteSize();
612 m_order = process_sp->GetByteOrder();
613 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
634 if (idx >= num_children)
642 uint32_t test_idx = 0;
644 while (tries < num_children) {
650 llvm::Expected<lldb::addr_t> key =
651 process_sp->ReadPointerFromMemory(key_at_idx);
653 llvm::consumeError(key.takeError());
657 llvm::Expected<lldb::addr_t> val =
658 process_sp->ReadPointerFromMemory(val_at_idx);
660 llvm::consumeError(val.takeError());
667 if (!key_at_idx || !val_at_idx)
695 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
697 *(data_ptr + 1) = dict_item.
val_ptr;
699 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
701 *(data_ptr + 1) = dict_item.
val_ptr;
705 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
737 m_ptr_size = process_sp->GetAddressByteSize();
738 m_order = process_sp->GetByteOrder();
752 if (idx >= num_children)
763 uint32_t test_idx = 0;
769 while (tries < num_children) {
770 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
771 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
773 llvm::Expected<lldb::addr_t> key =
774 process_sp->ReadPointerFromMemory(key_at_idx);
776 llvm::consumeError(key.takeError());
780 llvm::Expected<lldb::addr_t> val =
781 process_sp->ReadPointerFromMemory(val_at_idx);
783 llvm::consumeError(val.takeError());
790 if (!key_at_idx || !val_at_idx)
821 uint32_t *data_ptr =
reinterpret_cast<uint32_t *
>(buffer_sp->GetBytes());
823 *(data_ptr + 1) = dict_item.
val_ptr;
826 uint64_t *data_ptr =
reinterpret_cast<uint64_t *
>(buffer_sp->GetBytes());
828 *(data_ptr + 1) = dict_item.
val_ptr;
831 lldbassert(
false &&
"pointer size is not 4 nor 8");
835 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
863 m_ptr_size = process_sp->GetAddressByteSize();
864 m_order = process_sp->GetByteOrder();
865 uint64_t valobj_addr = valobj_sp->GetValueAsUnsigned(0);
866 m_size = process_sp->ReadUnsignedIntegerFromMemory(
870 llvm::Expected<lldb::addr_t> keys_ptr =
871 process_sp->ReadPointerFromMemory(valobj_addr + 3 *
m_ptr_size);
873 llvm::consumeError(keys_ptr.takeError());
877 llvm::Expected<lldb::addr_t> objects_ptr =
878 process_sp->ReadPointerFromMemory(valobj_addr + 4 *
m_ptr_size);
880 llvm::consumeError(objects_ptr.takeError());
892 if (idx >= num_children)
902 for (
unsigned int child = 0; child < num_children; ++child) {
903 llvm::Expected<lldb::addr_t> key =
906 llvm::consumeError(key.takeError());
910 llvm::Expected<lldb::addr_t> val =
913 llvm::consumeError(val.takeError());
940 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
942 *(data_ptr + 1) = dict_item.
val_ptr;
944 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
946 *(data_ptr + 1) = dict_item.
val_ptr;
950 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
962llvm::Expected<size_t>
965 static constexpr llvm::StringLiteral g_zero(
"[0]");
968 return llvm::createStringErrorV(
"type has no child named '{0}'", name);
991 auto process_sp(
m_backend.GetProcessSP());
995 auto ptr_size = process_sp->GetAddressByteSize();
1001 llvm::Expected<lldb::addr_t> value_at_idx =
1002 process_sp->ReadPointerFromMemory(key_ptr);
1003 if (!value_at_idx) {
1004 llvm::consumeError(value_at_idx.takeError());
1007 llvm::Expected<lldb::addr_t> key_at_idx =
1008 process_sp->ReadPointerFromMemory(value_ptr);
1010 llvm::consumeError(key_at_idx.takeError());
1019 if (ptr_size == 8) {
1020 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1021 *data_ptr = *key_at_idx;
1022 *(data_ptr + 1) = *value_at_idx;
1024 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1025 *data_ptr = *key_at_idx;
1026 *(data_ptr + 1) = *value_at_idx;
1029 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size);
1031 "[0]", data,
m_backend.GetExecutionContextRef(), pair_type);
1036template <
typename D32,
typename D64>
1042template <
typename D32,
typename D64>
1047 m_data_32 =
nullptr;
1049 m_data_64 =
nullptr;
1052template <
typename D32,
typename D64>
1053llvm::Expected<uint32_t>
1061template <
typename D32,
typename D64>
1080 m_ptr_size = process_sp->GetAddressByteSize();
1081 m_order = process_sp->GetByteOrder();
1082 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
1085 process_sp->ReadMemory(data_location,
m_data_32,
sizeof(D32),
1089 process_sp->ReadMemory(data_location,
m_data_64,
sizeof(D64),
1097template <
typename D32,
typename D64>
1115 if (idx >= num_children)
1123 uint32_t test_idx = 0;
1125 while (tries < num_children) {
1126 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1127 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1132 llvm::Expected<lldb::addr_t> key =
1133 process_sp->ReadPointerFromMemory(key_at_idx);
1135 llvm::consumeError(key.takeError());
1139 llvm::Expected<lldb::addr_t> val =
1140 process_sp->ReadPointerFromMemory(val_at_idx);
1142 llvm::consumeError(val.takeError());
1149 if (!key_at_idx || !val_at_idx)
1177 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1178 *data_ptr = dict_item.
key_ptr;
1179 *(data_ptr + 1) = dict_item.
val_ptr;
1181 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1182 *data_ptr = dict_item.
key_ptr;
1183 *(data_ptr + 1) = dict_item.
val_ptr;
1187 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
1231 m_ptr_size = process_sp->GetAddressByteSize();
1232 m_order = process_sp->GetByteOrder();
1233 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
1258 if (idx >= num_children)
1266 uint32_t test_idx = 0;
1268 while (tries < num_children) {
1269 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1270 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1275 llvm::Expected<lldb::addr_t> key =
1276 process_sp->ReadPointerFromMemory(key_at_idx);
1278 llvm::consumeError(key.takeError());
1282 llvm::Expected<lldb::addr_t> val =
1283 process_sp->ReadPointerFromMemory(val_at_idx);
1285 llvm::consumeError(val.takeError());
1292 if (!key_at_idx || !val_at_idx)
1320 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1321 *data_ptr = dict_item.
key_ptr;
1322 *(data_ptr + 1) = dict_item.
val_ptr;
1324 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1325 *data_ptr = dict_item.
key_ptr;
1326 *(data_ptr + 1) = dict_item.
val_ptr;
1330 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.
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.
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.
size_t ReadMemory(const ProcessAddress &process_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)
SyntheticChildrenFrontEnd(ValueObject &backend)
lldb::ValueObjectSP CreateChildValueObjectFromData(llvm::StringRef name, const DataExtractor &data, const ExecutionContext &exe_ctx, CompilerType type)
lldb::LanguageType GetLanguage() const
static bool CompleteTagDeclarationDefinition(const CompilerType &type)
static bool StartTagDeclarationDefinition(const CompilerType &type)
static clang::FieldDecl * AddFieldToRecordType(const CompilerType &type, llvm::StringRef name, const CompilerType &field_type, uint32_t bitfield_bit_size)
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