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);
969llvm::Expected<size_t>
972 static constexpr llvm::StringLiteral g_zero(
"[0]");
975 return llvm::createStringErrorV(
"type has no child named '{0}'", name);
998 auto process_sp(
m_backend.GetProcessSP());
1002 auto ptr_size = process_sp->GetAddressByteSize();
1008 llvm::Expected<lldb::addr_t> value_at_idx =
1009 process_sp->ReadPointerFromMemory(key_ptr);
1010 if (!value_at_idx) {
1011 llvm::consumeError(value_at_idx.takeError());
1014 llvm::Expected<lldb::addr_t> key_at_idx =
1015 process_sp->ReadPointerFromMemory(value_ptr);
1017 llvm::consumeError(key_at_idx.takeError());
1026 if (ptr_size == 8) {
1027 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1028 *data_ptr = *key_at_idx;
1029 *(data_ptr + 1) = *value_at_idx;
1031 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1032 *data_ptr = *key_at_idx;
1033 *(data_ptr + 1) = *value_at_idx;
1036 DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size);
1038 "[0]", data,
m_backend.GetExecutionContextRef(), pair_type);
1043template <
typename D32,
typename D64>
1049template <
typename D32,
typename D64>
1054 m_data_32 =
nullptr;
1056 m_data_64 =
nullptr;
1059template <
typename D32,
typename D64>
1060llvm::Expected<uint32_t>
1068template <
typename D32,
typename D64>
1087 m_ptr_size = process_sp->GetAddressByteSize();
1088 m_order = process_sp->GetByteOrder();
1089 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
1092 process_sp->ReadMemory(data_location,
m_data_32,
sizeof(D32),
1096 process_sp->ReadMemory(data_location,
m_data_64,
sizeof(D64),
1104template <
typename D32,
typename D64>
1122 if (idx >= num_children)
1130 uint32_t test_idx = 0;
1132 while (tries < num_children) {
1133 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1134 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1139 llvm::Expected<lldb::addr_t> key =
1140 process_sp->ReadPointerFromMemory(key_at_idx);
1142 llvm::consumeError(key.takeError());
1146 llvm::Expected<lldb::addr_t> val =
1147 process_sp->ReadPointerFromMemory(val_at_idx);
1149 llvm::consumeError(val.takeError());
1156 if (!key_at_idx || !val_at_idx)
1184 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1185 *data_ptr = dict_item.
key_ptr;
1186 *(data_ptr + 1) = dict_item.
val_ptr;
1188 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1189 *data_ptr = dict_item.
key_ptr;
1190 *(data_ptr + 1) = dict_item.
val_ptr;
1194 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
1238 m_ptr_size = process_sp->GetAddressByteSize();
1239 m_order = process_sp->GetByteOrder();
1240 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
1265 if (idx >= num_children)
1273 uint32_t test_idx = 0;
1275 while (tries < num_children) {
1276 key_at_idx = m_keys_ptr + (test_idx *
m_ptr_size);
1277 val_at_idx = m_values_ptr + (test_idx *
m_ptr_size);
1282 llvm::Expected<lldb::addr_t> key =
1283 process_sp->ReadPointerFromMemory(key_at_idx);
1285 llvm::consumeError(key.takeError());
1289 llvm::Expected<lldb::addr_t> val =
1290 process_sp->ReadPointerFromMemory(val_at_idx);
1292 llvm::consumeError(val.takeError());
1299 if (!key_at_idx || !val_at_idx)
1327 uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
1328 *data_ptr = dict_item.
key_ptr;
1329 *(data_ptr + 1) = dict_item.
val_ptr;
1331 uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
1332 *data_ptr = dict_item.
key_ptr;
1333 *(data_ptr + 1) = dict_item.
val_ptr;
1337 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