11#include "clang/AST/DeclCXX.h"
19#include "llvm/Support/ErrorExtras.h"
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 ConstString class_name(descriptor->GetClassName());
419 static const ConstString g_DictionaryI(
"__NSDictionaryI");
420 static const ConstString g_DictionaryM(
"__NSDictionaryM");
421 static const ConstString g_DictionaryMLegacy(
"__NSDictionaryM_Legacy");
422 static const ConstString g_DictionaryMImmutable(
"__NSDictionaryM_Immutable");
423 static const ConstString g_DictionaryMFrozen(
"__NSFrozenDictionaryM");
424 static const ConstString g_Dictionary1(
"__NSSingleEntryDictionaryI");
425 static const ConstString g_Dictionary0(
"__NSDictionary0");
426 static const ConstString g_DictionaryCF(
"__CFDictionary");
427 static const ConstString g_DictionaryNSCF(
"__NSCFDictionary");
428 static const ConstString g_DictionaryCFRef(
"CFDictionaryRef");
429 static const ConstString g_ConstantDictionary(
"NSConstantDictionary");
434 if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) {
436 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
441 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
442 }
else if (class_name == g_ConstantDictionary) {
444 value = process_sp->ReadUnsignedIntegerFromMemory(
445 valobj_addr + 2 * ptr_size, ptr_size, 0,
error);
448 }
else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy ||
449 class_name == g_DictionaryMFrozen) {
451 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
457 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
459 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
463 }
else if (class_name == g_Dictionary1) {
465 }
else if (class_name == g_Dictionary0) {
467 }
else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
468 class_name == g_DictionaryCFRef) {
471 if (!cfbh.
Update(valobj_addr, exe_ctx))
476 for (
auto &candidate : map) {
477 if (candidate.first && candidate.first->Match(class_name))
478 return candidate.second(valobj, stream, options);
483 llvm::StringRef prefix, suffix;
485 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
488 stream.
Printf(
"%" PRIu64
" %s%s", value,
"key/value pair",
489 value == 1 ?
"" :
"s");
506 Flags flags(valobj_type.GetTypeInfo());
508 if (flags.IsClear(eTypeIsPointer)) {
510 valobj_sp = valobj_sp->AddressOf(
error);
511 if (
error.Fail() || !valobj_sp)
518 if (!descriptor || !descriptor->IsValid())
521 ConstString class_name(descriptor->GetClassName());
523 static const ConstString g_DictionaryI(
"__NSDictionaryI");
524 static const ConstString g_DictionaryM(
"__NSDictionaryM");
525 static const ConstString g_Dictionary1(
"__NSSingleEntryDictionaryI");
526 static const ConstString g_DictionaryImmutable(
"__NSDictionaryM_Immutable");
527 static const ConstString g_DictionaryMFrozen(
"__NSFrozenDictionaryM");
528 static const ConstString g_DictionaryMLegacy(
"__NSDictionaryM_Legacy");
529 static const ConstString g_Dictionary0(
"__NSDictionary0");
530 static const ConstString g_DictionaryCF(
"__CFDictionary");
531 static const ConstString g_DictionaryNSCF(
"__NSCFDictionary");
532 static const ConstString g_DictionaryCFRef(
"CFDictionaryRef");
533 static const ConstString g_ConstantDictionary(
"NSConstantDictionary");
535 if (class_name.IsEmpty())
538 if (class_name == g_DictionaryI) {
540 }
else if (class_name == g_ConstantDictionary) {
541 return (
new NSConstantDictionarySyntheticFrontEnd(valobj_sp));
542 }
else if (class_name == g_DictionaryM || class_name == g_DictionaryMFrozen) {
548 return (
new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp));
550 }
else if (class_name == g_DictionaryMLegacy) {
551 return (
new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp));
552 }
else if (class_name == g_Dictionary1) {
553 return (
new NSDictionary1SyntheticFrontEnd(valobj_sp));
554 }
else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
555 class_name == g_DictionaryCFRef) {
556 return (
new NSCFDictionarySyntheticFrontEnd(valobj_sp));
559 for (
auto &candidate : map) {
560 if (candidate.first && candidate.first->Match((class_name)))
561 return candidate.second(synth, valobj_sp);
604 m_ptr_size = process_sp->GetAddressByteSize();
605 m_order = process_sp->GetByteOrder();
606 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
627 if (idx >= num_children)
635 uint32_t test_idx = 0;
637 while (tries < num_children) {
644 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
647 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
653 if (!key_at_idx || !val_at_idx)
681 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
683 *(data_ptr + 1) = dict_item.
val_ptr;
685 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
687 *(data_ptr + 1) = dict_item.
val_ptr;
691 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
723 m_ptr_size = process_sp->GetAddressByteSize();
724 m_order = process_sp->GetByteOrder();
738 if (idx >= num_children)
750 uint32_t test_idx = 0;
756 while (tries < num_children) {
757 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
758 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
760 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
763 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
769 if (!key_at_idx || !val_at_idx)
800 uint32_t *data_ptr =
reinterpret_cast<uint32_t *
>(buffer_sp->GetBytes());
802 *(data_ptr + 1) = dict_item.
val_ptr;
805 uint64_t *data_ptr =
reinterpret_cast<uint64_t *
>(buffer_sp->GetBytes());
807 *(data_ptr + 1) = dict_item.
val_ptr;
810 lldbassert(
false &&
"pointer size is not 4 nor 8");
814 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
842 m_ptr_size = process_sp->GetAddressByteSize();
843 m_order = process_sp->GetByteOrder();
844 uint64_t valobj_addr = valobj_sp->GetValueAsUnsigned(0);
845 m_size = process_sp->ReadUnsignedIntegerFromMemory(
850 process_sp->ReadPointerFromMemory(valobj_addr + 3 *
m_ptr_size,
error);
854 process_sp->ReadPointerFromMemory(valobj_addr + 4 *
m_ptr_size,
error);
864 if (idx >= num_children)
874 for (
unsigned int child = 0; child < num_children; ++child) {
876 key_at_idx = process_sp->ReadPointerFromMemory(
880 val_at_idx = process_sp->ReadPointerFromMemory(
907 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
909 *(data_ptr + 1) = dict_item.
val_ptr;
911 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
913 *(data_ptr + 1) = dict_item.
val_ptr;
917 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
934 return llvm::createStringErrorV(
"type has no child named '{0}'", name);
957 auto process_sp(
m_backend.GetProcessSP());
961 auto ptr_size = process_sp->GetAddressByteSize();
982 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
983 *data_ptr = key_at_idx;
984 *(data_ptr + 1) = value_at_idx;
986 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
987 *data_ptr = key_at_idx;
988 *(data_ptr + 1) = value_at_idx;
991 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size);
993 "[0]", data,
m_backend.GetExecutionContextRef(), pair_type);
998template <
typename D32,
typename D64>
1004template <
typename D32,
typename D64>
1009 m_data_32 =
nullptr;
1011 m_data_64 =
nullptr;
1014template <
typename D32,
typename D64>
1015llvm::Expected<uint32_t>
1023template <
typename D32,
typename D64>
1042 m_ptr_size = process_sp->GetAddressByteSize();
1043 m_order = process_sp->GetByteOrder();
1044 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
1047 process_sp->ReadMemory(data_location,
m_data_32,
sizeof(D32),
1051 process_sp->ReadMemory(data_location,
m_data_64,
sizeof(D64),
1059template <
typename D32,
typename D64>
1077 if (idx >= num_children)
1085 uint32_t test_idx = 0;
1087 while (tries < num_children) {
1088 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1089 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1095 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
1098 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
1104 if (!key_at_idx || !val_at_idx)
1132 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1133 *data_ptr = dict_item.
key_ptr;
1134 *(data_ptr + 1) = dict_item.
val_ptr;
1136 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1137 *data_ptr = dict_item.
key_ptr;
1138 *(data_ptr + 1) = dict_item.
val_ptr;
1142 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
1186 m_ptr_size = process_sp->GetAddressByteSize();
1187 m_order = process_sp->GetByteOrder();
1188 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
1213 if (idx >= num_children)
1221 uint32_t test_idx = 0;
1223 while (tries < num_children) {
1224 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1225 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1231 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
1234 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
1240 if (!key_at_idx || !val_at_idx)
1268 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1269 *data_ptr = dict_item.
key_ptr;
1270 *(data_ptr + 1) = dict_item.
val_ptr;
1272 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1273 *data_ptr = dict_item.
key_ptr;
1274 *(data_ptr + 1) = dict_item.
val_ptr;
1278 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 uniqued constant string class.
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.
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 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