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(
98namespace lldb_private {
212template <
typename D32,
typename D64>
291 struct DataDescriptor_32 {
296 uint64_t GetSize() {
return _size; }
299 struct DataDescriptor_64 {
304 uint64_t GetSize() {
return _size; }
314 0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723,
315 2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607,
316 214519, 346607, 561109, 907759, 1468927, 2376191, 3845119,
317 6221311, 10066421, 16287743, 26354171, 42641881, 68996069,
318 111638519, 180634607, 292272623, 472907251
325 struct DataDescriptor_32 {
338 struct DataDescriptor_64 {
355 template <
typename DD>
361 DD descriptor = DD();
362 process.
ReadMemory(start_of_descriptor, &descriptor,
sizeof(descriptor),
367 return descriptor._used;
386template <
bool name_entries>
389 static constexpr llvm::StringLiteral g_TypeHint(
"NSDictionary");
402 if (!descriptor || !descriptor->IsValid())
405 uint32_t ptr_size = process_sp->GetAddressByteSize();
406 bool is_64bit = (ptr_size == 8);
415 ConstString class_name(descriptor->GetClassName());
417 static const ConstString g_DictionaryI(
"__NSDictionaryI");
418 static const ConstString g_DictionaryM(
"__NSDictionaryM");
419 static const ConstString g_DictionaryMLegacy(
"__NSDictionaryM_Legacy");
420 static const ConstString g_DictionaryMImmutable(
"__NSDictionaryM_Immutable");
421 static const ConstString g_DictionaryMFrozen(
"__NSFrozenDictionaryM");
422 static const ConstString g_Dictionary1(
"__NSSingleEntryDictionaryI");
423 static const ConstString g_Dictionary0(
"__NSDictionary0");
424 static const ConstString g_DictionaryCF(
"__CFDictionary");
425 static const ConstString g_DictionaryNSCF(
"__NSCFDictionary");
426 static const ConstString g_DictionaryCFRef(
"CFDictionaryRef");
427 static const ConstString g_ConstantDictionary(
"NSConstantDictionary");
432 if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) {
434 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
439 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
440 }
else if (class_name == g_ConstantDictionary) {
442 value = process_sp->ReadUnsignedIntegerFromMemory(
443 valobj_addr + 2 * ptr_size, ptr_size, 0,
error);
446 }
else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy ||
447 class_name == g_DictionaryMFrozen) {
449 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
455 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
457 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
461 }
else if (class_name == g_Dictionary1) {
463 }
else if (class_name == g_Dictionary0) {
465 }
else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
466 class_name == g_DictionaryCFRef) {
469 if (!cfbh.
Update(valobj_addr, exe_ctx))
474 for (
auto &candidate : map) {
475 if (candidate.first && candidate.first->Match(class_name))
476 return candidate.second(valobj, stream, options);
481 llvm::StringRef prefix, suffix;
483 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
486 stream.
Printf(
"%" PRIu64
" %s%s", value,
"key/value pair",
487 value == 1 ?
"" :
"s");
504 Flags flags(valobj_type.GetTypeInfo());
506 if (flags.IsClear(eTypeIsPointer)) {
508 valobj_sp = valobj_sp->AddressOf(
error);
509 if (
error.Fail() || !valobj_sp)
516 if (!descriptor || !descriptor->IsValid())
519 ConstString class_name(descriptor->GetClassName());
521 static const ConstString g_DictionaryI(
"__NSDictionaryI");
522 static const ConstString g_DictionaryM(
"__NSDictionaryM");
523 static const ConstString g_Dictionary1(
"__NSSingleEntryDictionaryI");
524 static const ConstString g_DictionaryImmutable(
"__NSDictionaryM_Immutable");
525 static const ConstString g_DictionaryMFrozen(
"__NSFrozenDictionaryM");
526 static const ConstString g_DictionaryMLegacy(
"__NSDictionaryM_Legacy");
527 static const ConstString g_Dictionary0(
"__NSDictionary0");
528 static const ConstString g_DictionaryCF(
"__CFDictionary");
529 static const ConstString g_DictionaryNSCF(
"__NSCFDictionary");
530 static const ConstString g_DictionaryCFRef(
"CFDictionaryRef");
531 static const ConstString g_ConstantDictionary(
"NSConstantDictionary");
533 if (class_name.IsEmpty())
536 if (class_name == g_DictionaryI) {
538 }
else if (class_name == g_ConstantDictionary) {
539 return (
new NSConstantDictionarySyntheticFrontEnd(valobj_sp));
540 }
else if (class_name == g_DictionaryM || class_name == g_DictionaryMFrozen) {
546 return (
new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp));
548 }
else if (class_name == g_DictionaryMLegacy) {
549 return (
new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp));
550 }
else if (class_name == g_Dictionary1) {
551 return (
new NSDictionary1SyntheticFrontEnd(valobj_sp));
552 }
else if (class_name == g_DictionaryCF || class_name == g_DictionaryNSCF ||
553 class_name == g_DictionaryCFRef) {
554 return (
new NSCFDictionarySyntheticFrontEnd(valobj_sp));
557 for (
auto &candidate : map) {
558 if (candidate.first && candidate.first->Match((class_name)))
559 return candidate.second(synth, valobj_sp);
602 m_ptr_size = process_sp->GetAddressByteSize();
603 m_order = process_sp->GetByteOrder();
604 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
625 if (idx >= num_children)
633 uint32_t test_idx = 0;
635 while (tries < num_children) {
642 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
645 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
651 if (!key_at_idx || !val_at_idx)
679 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
681 *(data_ptr + 1) = dict_item.
val_ptr;
683 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
685 *(data_ptr + 1) = dict_item.
val_ptr;
689 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
721 m_ptr_size = process_sp->GetAddressByteSize();
722 m_order = process_sp->GetByteOrder();
736 if (idx >= num_children)
748 uint32_t test_idx = 0;
754 while (tries < num_children) {
755 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
756 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
758 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
761 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
767 if (!key_at_idx || !val_at_idx)
798 uint32_t *data_ptr =
reinterpret_cast<uint32_t *
>(buffer_sp->GetBytes());
800 *(data_ptr + 1) = dict_item.
val_ptr;
803 uint64_t *data_ptr =
reinterpret_cast<uint64_t *
>(buffer_sp->GetBytes());
805 *(data_ptr + 1) = dict_item.
val_ptr;
808 lldbassert(
false &&
"pointer size is not 4 nor 8");
812 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
840 m_ptr_size = process_sp->GetAddressByteSize();
841 m_order = process_sp->GetByteOrder();
842 uint64_t valobj_addr = valobj_sp->GetValueAsUnsigned(0);
843 m_size = process_sp->ReadUnsignedIntegerFromMemory(
848 process_sp->ReadPointerFromMemory(valobj_addr + 3 *
m_ptr_size,
error);
852 process_sp->ReadPointerFromMemory(valobj_addr + 4 *
m_ptr_size,
error);
862 if (idx >= num_children)
872 for (
unsigned int child = 0; child < num_children; ++child) {
874 key_at_idx = process_sp->ReadPointerFromMemory(
878 val_at_idx = process_sp->ReadPointerFromMemory(
905 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
907 *(data_ptr + 1) = dict_item.
val_ptr;
909 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
911 *(data_ptr + 1) = dict_item.
val_ptr;
915 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
932 return llvm::createStringError(
"Type has no child named '%s'",
956 auto process_sp(
m_backend.GetProcessSP());
960 auto ptr_size = process_sp->GetAddressByteSize();
981 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
982 *data_ptr = key_at_idx;
983 *(data_ptr + 1) = value_at_idx;
985 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
986 *data_ptr = key_at_idx;
987 *(data_ptr + 1) = value_at_idx;
990 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size);
992 "[0]", data,
m_backend.GetExecutionContextRef(), pair_type);
997template <
typename D32,
typename D64>
1003template <
typename D32,
typename D64>
1008 m_data_32 =
nullptr;
1010 m_data_64 =
nullptr;
1013template <
typename D32,
typename D64>
1014llvm::Expected<uint32_t>
1022template <
typename D32,
typename D64>
1041 m_ptr_size = process_sp->GetAddressByteSize();
1042 m_order = process_sp->GetByteOrder();
1043 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
1046 process_sp->ReadMemory(data_location,
m_data_32,
sizeof(D32),
1050 process_sp->ReadMemory(data_location,
m_data_64,
sizeof(D64),
1058template <
typename D32,
typename D64>
1076 if (idx >= num_children)
1084 uint32_t test_idx = 0;
1086 while (tries < num_children) {
1087 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1088 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1094 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
1097 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
1103 if (!key_at_idx || !val_at_idx)
1131 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1132 *data_ptr = dict_item.
key_ptr;
1133 *(data_ptr + 1) = dict_item.
val_ptr;
1135 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1136 *data_ptr = dict_item.
key_ptr;
1137 *(data_ptr + 1) = dict_item.
val_ptr;
1141 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
1185 m_ptr_size = process_sp->GetAddressByteSize();
1186 m_order = process_sp->GetByteOrder();
1187 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
1212 if (idx >= num_children)
1220 uint32_t test_idx = 0;
1222 while (tries < num_children) {
1223 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1224 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1230 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
1233 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
1239 if (!key_at_idx || !val_at_idx)
1267 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1268 *data_ptr = dict_item.
key_ptr;
1269 *(data_ptr + 1) = dict_item.
val_ptr;
1271 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1272 *data_ptr = dict_item.
key_ptr;
1273 *(data_ptr + 1) = dict_item.
val_ptr;
1277 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.
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.
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