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());
418 llvm::StringRef class_name_ref(class_name.
GetStringRef());
420 static constexpr llvm::StringLiteral g_DictionaryI(
"__NSDictionaryI");
421 static constexpr llvm::StringLiteral g_DictionaryM(
"__NSDictionaryM");
422 static constexpr llvm::StringLiteral g_DictionaryMLegacy(
423 "__NSDictionaryM_Legacy");
424 static constexpr llvm::StringLiteral g_DictionaryMImmutable(
425 "__NSDictionaryM_Immutable");
426 static constexpr llvm::StringLiteral g_DictionaryMFrozen(
427 "__NSFrozenDictionaryM");
428 static constexpr llvm::StringLiteral g_Dictionary1(
429 "__NSSingleEntryDictionaryI");
430 static constexpr llvm::StringLiteral g_Dictionary0(
"__NSDictionary0");
431 static constexpr llvm::StringLiteral g_DictionaryCF(
"__CFDictionary");
432 static constexpr llvm::StringLiteral g_DictionaryNSCF(
"__NSCFDictionary");
433 static constexpr llvm::StringLiteral g_DictionaryCFRef(
"CFDictionaryRef");
434 static constexpr llvm::StringLiteral g_ConstantDictionary(
435 "NSConstantDictionary");
437 if (class_name_ref.empty())
440 if (class_name_ref == g_DictionaryI ||
441 class_name_ref == g_DictionaryMImmutable) {
443 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
448 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
449 }
else if (class_name_ref == g_ConstantDictionary) {
451 value = process_sp->ReadUnsignedIntegerFromMemory(
452 valobj_addr + 2 * ptr_size, ptr_size, 0,
error);
455 }
else if (class_name_ref == g_DictionaryM ||
456 class_name_ref == g_DictionaryMLegacy ||
457 class_name_ref == g_DictionaryMFrozen) {
459 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
465 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
467 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
471 }
else if (class_name_ref == g_Dictionary1) {
473 }
else if (class_name_ref == g_Dictionary0) {
475 }
else if (class_name_ref == g_DictionaryCF ||
476 class_name_ref == g_DictionaryNSCF ||
477 class_name_ref == 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");
515 Flags flags(valobj_type.GetTypeInfo());
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());
531 llvm::StringRef class_name_ref(class_name.GetStringRef());
533 static constexpr llvm::StringLiteral g_DictionaryI(
"__NSDictionaryI");
534 static constexpr llvm::StringLiteral g_DictionaryM(
"__NSDictionaryM");
535 static constexpr llvm::StringLiteral g_Dictionary1(
536 "__NSSingleEntryDictionaryI");
537 static constexpr llvm::StringLiteral g_DictionaryMFrozen(
538 "__NSFrozenDictionaryM");
539 static constexpr llvm::StringLiteral g_DictionaryMLegacy(
540 "__NSDictionaryM_Legacy");
541 static constexpr llvm::StringLiteral g_DictionaryCF(
"__CFDictionary");
542 static constexpr llvm::StringLiteral g_DictionaryNSCF(
"__NSCFDictionary");
543 static constexpr llvm::StringLiteral g_DictionaryCFRef(
"CFDictionaryRef");
544 static constexpr llvm::StringLiteral g_ConstantDictionary(
545 "NSConstantDictionary");
547 if (class_name_ref.empty())
550 if (class_name_ref == g_DictionaryI) {
552 }
else if (class_name_ref == g_ConstantDictionary) {
553 return (
new NSConstantDictionarySyntheticFrontEnd(valobj_sp));
554 }
else if (class_name_ref == g_DictionaryM ||
555 class_name_ref == g_DictionaryMFrozen) {
561 return (
new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp));
563 }
else if (class_name_ref == g_DictionaryMLegacy) {
564 return (
new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp));
565 }
else if (class_name_ref == g_Dictionary1) {
566 return (
new NSDictionary1SyntheticFrontEnd(valobj_sp));
567 }
else if (class_name_ref == g_DictionaryCF ||
568 class_name_ref == g_DictionaryNSCF ||
569 class_name_ref == g_DictionaryCFRef) {
570 return (
new NSCFDictionarySyntheticFrontEnd(valobj_sp));
573 for (
auto &candidate : map) {
574 if (candidate.first && candidate.first->Match((class_name)))
575 return candidate.second(synth, valobj_sp);
618 m_ptr_size = process_sp->GetAddressByteSize();
619 m_order = process_sp->GetByteOrder();
620 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
641 if (idx >= num_children)
649 uint32_t test_idx = 0;
651 while (tries < num_children) {
658 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
661 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
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)
764 uint32_t test_idx = 0;
770 while (tries < num_children) {
771 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
772 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
774 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
777 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
783 if (!key_at_idx || !val_at_idx)
814 uint32_t *data_ptr =
reinterpret_cast<uint32_t *
>(buffer_sp->GetBytes());
816 *(data_ptr + 1) = dict_item.
val_ptr;
819 uint64_t *data_ptr =
reinterpret_cast<uint64_t *
>(buffer_sp->GetBytes());
821 *(data_ptr + 1) = dict_item.
val_ptr;
824 lldbassert(
false &&
"pointer size is not 4 nor 8");
828 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
856 m_ptr_size = process_sp->GetAddressByteSize();
857 m_order = process_sp->GetByteOrder();
858 uint64_t valobj_addr = valobj_sp->GetValueAsUnsigned(0);
859 m_size = process_sp->ReadUnsignedIntegerFromMemory(
864 process_sp->ReadPointerFromMemory(valobj_addr + 3 *
m_ptr_size,
error);
868 process_sp->ReadPointerFromMemory(valobj_addr + 4 *
m_ptr_size,
error);
878 if (idx >= num_children)
888 for (
unsigned int child = 0; child < num_children; ++child) {
890 key_at_idx = process_sp->ReadPointerFromMemory(
894 val_at_idx = process_sp->ReadPointerFromMemory(
921 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
923 *(data_ptr + 1) = dict_item.
val_ptr;
925 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
927 *(data_ptr + 1) = dict_item.
val_ptr;
931 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
945 static constexpr llvm::StringLiteral g_zero(
"[0]");
948 return llvm::createStringErrorV(
"type has no child named '{0}'", name);
971 auto process_sp(
m_backend.GetProcessSP());
975 auto ptr_size = process_sp->GetAddressByteSize();
996 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
997 *data_ptr = key_at_idx;
998 *(data_ptr + 1) = value_at_idx;
1000 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1001 *data_ptr = key_at_idx;
1002 *(data_ptr + 1) = value_at_idx;
1005 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size);
1007 "[0]", data,
m_backend.GetExecutionContextRef(), pair_type);
1012template <
typename D32,
typename D64>
1018template <
typename D32,
typename D64>
1023 m_data_32 =
nullptr;
1025 m_data_64 =
nullptr;
1028template <
typename D32,
typename D64>
1029llvm::Expected<uint32_t>
1037template <
typename D32,
typename D64>
1056 m_ptr_size = process_sp->GetAddressByteSize();
1057 m_order = process_sp->GetByteOrder();
1058 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
1061 process_sp->ReadMemory(data_location,
m_data_32,
sizeof(D32),
1065 process_sp->ReadMemory(data_location,
m_data_64,
sizeof(D64),
1073template <
typename D32,
typename D64>
1091 if (idx >= num_children)
1099 uint32_t test_idx = 0;
1101 while (tries < num_children) {
1102 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1103 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1109 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
1112 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
1118 if (!key_at_idx || !val_at_idx)
1146 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1147 *data_ptr = dict_item.
key_ptr;
1148 *(data_ptr + 1) = dict_item.
val_ptr;
1150 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1151 *data_ptr = dict_item.
key_ptr;
1152 *(data_ptr + 1) = dict_item.
val_ptr;
1156 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
1200 m_ptr_size = process_sp->GetAddressByteSize();
1201 m_order = process_sp->GetByteOrder();
1202 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
1227 if (idx >= num_children)
1235 uint32_t test_idx = 0;
1237 while (tries < num_children) {
1238 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1239 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1245 key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx,
error);
1248 val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx,
error);
1254 if (!key_at_idx || !val_at_idx)
1282 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1283 *data_ptr = dict_item.
key_ptr;
1284 *(data_ptr + 1) = dict_item.
val_ptr;
1286 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1287 *data_ptr = dict_item.
key_ptr;
1288 *(data_ptr + 1) = dict_item.
val_ptr;
1292 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.
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)
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