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) {
657 llvm::Expected<lldb::addr_t> key =
658 process_sp->ReadPointerFromMemory(key_at_idx);
660 llvm::consumeError(key.takeError());
664 llvm::Expected<lldb::addr_t> val =
665 process_sp->ReadPointerFromMemory(val_at_idx);
667 llvm::consumeError(val.takeError());
674 if (!key_at_idx || !val_at_idx)
702 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
704 *(data_ptr + 1) = dict_item.
val_ptr;
706 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
708 *(data_ptr + 1) = dict_item.
val_ptr;
712 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
744 m_ptr_size = process_sp->GetAddressByteSize();
745 m_order = process_sp->GetByteOrder();
759 if (idx >= num_children)
770 uint32_t test_idx = 0;
776 while (tries < num_children) {
777 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
778 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
780 llvm::Expected<lldb::addr_t> key =
781 process_sp->ReadPointerFromMemory(key_at_idx);
783 llvm::consumeError(key.takeError());
787 llvm::Expected<lldb::addr_t> val =
788 process_sp->ReadPointerFromMemory(val_at_idx);
790 llvm::consumeError(val.takeError());
797 if (!key_at_idx || !val_at_idx)
828 uint32_t *data_ptr =
reinterpret_cast<uint32_t *
>(buffer_sp->GetBytes());
830 *(data_ptr + 1) = dict_item.
val_ptr;
833 uint64_t *data_ptr =
reinterpret_cast<uint64_t *
>(buffer_sp->GetBytes());
835 *(data_ptr + 1) = dict_item.
val_ptr;
838 lldbassert(
false &&
"pointer size is not 4 nor 8");
842 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
870 m_ptr_size = process_sp->GetAddressByteSize();
871 m_order = process_sp->GetByteOrder();
872 uint64_t valobj_addr = valobj_sp->GetValueAsUnsigned(0);
873 m_size = process_sp->ReadUnsignedIntegerFromMemory(
877 llvm::Expected<lldb::addr_t> keys_ptr =
878 process_sp->ReadPointerFromMemory(valobj_addr + 3 *
m_ptr_size);
880 llvm::consumeError(keys_ptr.takeError());
884 llvm::Expected<lldb::addr_t> objects_ptr =
885 process_sp->ReadPointerFromMemory(valobj_addr + 4 *
m_ptr_size);
887 llvm::consumeError(objects_ptr.takeError());
899 if (idx >= num_children)
909 for (
unsigned int child = 0; child < num_children; ++child) {
910 llvm::Expected<lldb::addr_t> key =
913 llvm::consumeError(key.takeError());
917 llvm::Expected<lldb::addr_t> val =
920 llvm::consumeError(val.takeError());
947 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
949 *(data_ptr + 1) = dict_item.
val_ptr;
951 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
953 *(data_ptr + 1) = dict_item.
val_ptr;
957 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
971 static constexpr llvm::StringLiteral g_zero(
"[0]");
974 return llvm::createStringErrorV(
"type has no child named '{0}'", name);
997 auto process_sp(
m_backend.GetProcessSP());
1001 auto ptr_size = process_sp->GetAddressByteSize();
1007 llvm::Expected<lldb::addr_t> value_at_idx =
1008 process_sp->ReadPointerFromMemory(key_ptr);
1009 if (!value_at_idx) {
1010 llvm::consumeError(value_at_idx.takeError());
1013 llvm::Expected<lldb::addr_t> key_at_idx =
1014 process_sp->ReadPointerFromMemory(value_ptr);
1016 llvm::consumeError(key_at_idx.takeError());
1025 if (ptr_size == 8) {
1026 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1027 *data_ptr = *key_at_idx;
1028 *(data_ptr + 1) = *value_at_idx;
1030 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1031 *data_ptr = *key_at_idx;
1032 *(data_ptr + 1) = *value_at_idx;
1035 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size);
1037 "[0]", data,
m_backend.GetExecutionContextRef(), pair_type);
1042template <
typename D32,
typename D64>
1048template <
typename D32,
typename D64>
1053 m_data_32 =
nullptr;
1055 m_data_64 =
nullptr;
1058template <
typename D32,
typename D64>
1059llvm::Expected<uint32_t>
1067template <
typename D32,
typename D64>
1086 m_ptr_size = process_sp->GetAddressByteSize();
1087 m_order = process_sp->GetByteOrder();
1088 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
1091 process_sp->ReadMemory(data_location,
m_data_32,
sizeof(D32),
1095 process_sp->ReadMemory(data_location,
m_data_64,
sizeof(D64),
1103template <
typename D32,
typename D64>
1121 if (idx >= num_children)
1129 uint32_t test_idx = 0;
1131 while (tries < num_children) {
1132 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1133 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1138 llvm::Expected<lldb::addr_t> key =
1139 process_sp->ReadPointerFromMemory(key_at_idx);
1141 llvm::consumeError(key.takeError());
1145 llvm::Expected<lldb::addr_t> val =
1146 process_sp->ReadPointerFromMemory(val_at_idx);
1148 llvm::consumeError(val.takeError());
1155 if (!key_at_idx || !val_at_idx)
1183 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1184 *data_ptr = dict_item.
key_ptr;
1185 *(data_ptr + 1) = dict_item.
val_ptr;
1187 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1188 *data_ptr = dict_item.
key_ptr;
1189 *(data_ptr + 1) = dict_item.
val_ptr;
1193 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
1237 m_ptr_size = process_sp->GetAddressByteSize();
1238 m_order = process_sp->GetByteOrder();
1239 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
1264 if (idx >= num_children)
1272 uint32_t test_idx = 0;
1274 while (tries < num_children) {
1275 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1276 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1281 llvm::Expected<lldb::addr_t> key =
1282 process_sp->ReadPointerFromMemory(key_at_idx);
1284 llvm::consumeError(key.takeError());
1288 llvm::Expected<lldb::addr_t> val =
1289 process_sp->ReadPointerFromMemory(val_at_idx);
1291 llvm::consumeError(val.takeError());
1298 if (!key_at_idx || !val_at_idx)
1326 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1327 *data_ptr = dict_item.
key_ptr;
1328 *(data_ptr + 1) = dict_item.
val_ptr;
1330 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1331 *data_ptr = dict_item.
key_ptr;
1332 *(data_ptr + 1) = dict_item.
val_ptr;
1336 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(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