9#include "clang/AST/ASTContext.h"
10#include "clang/Basic/TargetInfo.h"
28#include "llvm/ADT/StringMap.h"
36llvm::StringMap<CXXFunctionSummaryFormat::Callback> &
38 static llvm::StringMap<CXXFunctionSummaryFormat::Callback> g_map;
42llvm::StringMap<CXXSyntheticChildren::CreateFrontEndCallback> &
44 static llvm::StringMap<CXXSyntheticChildren::CreateFrontEndCallback> g_map;
74template <
typename D32,
typename D64>
99 struct DataDescriptor_32 {
108 struct DataDescriptor_64 {
124 struct DataDescriptor_32 {
131 struct DataDescriptor_64 {
144 template <
typename PtrType>
159 template <
typename DD>
165 DD descriptor = DD();
166 process.
ReadMemory(start_of_descriptor, &descriptor,
167 sizeof(descriptor),
error);
171 return descriptor._used;
207template <
typename D32,
typename D64,
bool Inline>
328 static constexpr llvm::StringLiteral g_TypeHint(
"NSArray");
342 if (!descriptor || !descriptor->IsValid())
345 uint32_t ptr_size = process_sp->GetAddressByteSize();
354 llvm::StringRef class_name(descriptor->GetClassName());
356 static constexpr llvm::StringLiteral g_NSArrayI(
"__NSArrayI");
357 static constexpr llvm::StringLiteral g_NSArrayM(
"__NSArrayM");
358 static constexpr llvm::StringLiteral g_NSArrayI_Transfer(
359 "__NSArrayI_Transfer");
360 static constexpr llvm::StringLiteral g_NSFrozenArrayM(
"__NSFrozenArrayM");
361 static constexpr llvm::StringLiteral g_NSArray0(
"__NSArray0");
362 static constexpr llvm::StringLiteral g_NSArray1(
"__NSSingleObjectArrayI");
363 static constexpr llvm::StringLiteral g_NSArrayCF(
"__NSCFArray");
364 static constexpr llvm::StringLiteral g_NSArrayMLegacy(
"__NSArrayM_Legacy");
365 static constexpr llvm::StringLiteral g_NSArrayMImmutable(
366 "__NSArrayM_Immutable");
367 static constexpr llvm::StringLiteral g_NSCallStackArray(
"_NSCallStackArray");
368 static constexpr llvm::StringLiteral g_NSConstantArray(
"NSConstantArray");
370 if (class_name.empty())
373 if (class_name == g_NSArrayI) {
375 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
379 }
else if (class_name == g_NSConstantArray) {
381 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 8,
385 }
else if (class_name == g_NSArrayM) {
387 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
392 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
397 }
else if (class_name == g_NSArrayI_Transfer) {
399 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
403 }
else if (class_name == g_NSFrozenArrayM) {
408 }
else if (class_name == g_NSArrayMLegacy) {
410 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
414 }
else if (class_name == g_NSArrayMImmutable) {
416 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
420 }
else if (class_name == g_NSArray0) {
422 }
else if (class_name == g_NSArray1) {
424 }
else if (class_name == g_NSArrayCF || class_name == g_NSCallStackArray) {
428 value = process_sp->ReadUnsignedIntegerFromMemory(
429 valobj_addr + 2 * ptr_size, ptr_size, 0,
error);
434 auto iter = map.find(class_name), end = map.end();
436 return iter->second(valobj, stream, options);
441 llvm::StringRef prefix, suffix;
443 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
446 stream.
Printf(
"%" PRIu64
" %s%s", value,
"element", value == 1 ?
"" :
"s");
456 *valobj_sp->GetExecutionContextRef().GetTargetSP());
459 scratch_ts_sp->weak_from_this(),
460 scratch_ts_sp->getASTContext().ObjCBuiltinIdTy.getAsOpaquePtr());
461 if (valobj_sp->GetProcessSP())
462 m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize();
466template <
typename D32,
typename D64>
484 size_t pyhs_idx = idx;
490 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
495template <
typename D32,
typename D64>
512 m_ptr_size = process_sp->GetAddressByteSize();
513 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
516 process_sp->ReadMemory(data_location,
m_data_32,
sizeof(D32),
520 process_sp->ReadMemory(data_location,
m_data_64,
sizeof(D64),
528template <
typename D32,
typename D64>
537template <
typename D32,
typename D64>
539lldb_private::formatters::
540 GenericNSArrayMSyntheticFrontEnd<D32, D64>::
541 GenericNSArrayMSyntheticFrontEnd::GetDataAddress() {
542 if (!m_data_32 && !m_data_64)
544 return m_data_32 ? m_data_32->_data : m_data_64->_data;
547template <
typename D32,
typename D64>
549lldb_private::formatters::
550 GenericNSArrayMSyntheticFrontEnd<D32, D64>::
551 GenericNSArrayMSyntheticFrontEnd::GetUsedCount() {
552 if (!m_data_32 && !m_data_64)
554 return m_data_32 ? m_data_32->_used : m_data_64->_used;
557template <
typename D32,
typename D64>
559lldb_private::formatters::
560 GenericNSArrayMSyntheticFrontEnd<D32, D64>::
561 GenericNSArrayMSyntheticFrontEnd::GetOffset() {
562 if (!m_data_32 && !m_data_64)
564 return m_data_32 ? m_data_32->_offset : m_data_64->_offset;
567template <
typename D32,
typename D64>
569lldb_private::formatters::
570 GenericNSArrayMSyntheticFrontEnd<D32, D64>::
571 GenericNSArrayMSyntheticFrontEnd::GetSize() {
572 if (!m_data_32 && !m_data_64)
574 return m_data_32 ? m_data_32->_size : m_data_64->_size;
577template <
typename D32,
typename D64,
bool Inline>
586 *valobj_sp->GetExecutionContextRef().GetTargetSP());
589 scratch_ts_sp->getASTContext().ObjCBuiltinIdTy);
594template <
typename D32,
typename D64,
bool Inline>
603template <
typename D32,
typename D64,
bool Inline>
604llvm::Expected<uint32_t>
610template <
typename D32,
typename D64,
bool Inline>
628 m_ptr_size = process_sp->GetAddressByteSize();
629 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
632 process_sp->ReadMemory(data_location,
m_data_32,
sizeof(D32),
636 process_sp->ReadMemory(data_location,
m_data_64,
sizeof(D64),
644template <
typename D32,
typename D64,
bool Inline>
653 object_at_idx +=
m_ptr_size == 4 ?
sizeof(D32) :
sizeof(D64);
667 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
676llvm::Expected<size_t>
678 llvm::StringRef name) {
682llvm::Expected<uint32_t>
706llvm::Expected<size_t>
708 llvm::StringRef name) {
709 static constexpr llvm::StringLiteral g_zero(
"[0]");
717llvm::Expected<uint32_t>
737 return m_backend.GetSyntheticChildAtOffset(
738 m_backend.GetProcessSP()->GetAddressByteSize(), id_type,
true,
760 Flags flags(valobj_type.GetTypeInfo());
762 if (flags.IsClear(eTypeIsPointer)) {
764 valobj_sp = valobj_sp->AddressOf(
error);
765 if (
error.Fail() || !valobj_sp)
772 if (!descriptor || !descriptor->IsValid())
775 llvm::StringRef class_name(descriptor->GetClassName());
777 static constexpr llvm::StringLiteral g_NSArrayI(
"__NSArrayI");
778 static constexpr llvm::StringLiteral g_NSConstantArray(
"NSConstantArray");
779 static constexpr llvm::StringLiteral g_NSArrayI_Transfer(
780 "__NSArrayI_Transfer");
781 static constexpr llvm::StringLiteral g_NSFrozenArrayM(
"__NSFrozenArrayM");
782 static constexpr llvm::StringLiteral g_NSArrayM(
"__NSArrayM");
783 static constexpr llvm::StringLiteral g_NSArray0(
"__NSArray0");
784 static constexpr llvm::StringLiteral g_NSArray1(
"__NSSingleObjectArrayI");
785 static constexpr llvm::StringLiteral g_NSCallStackArray(
"_NSCallStackArray");
787 if (class_name.empty())
790 if (class_name == g_NSArrayI) {
796 }
else if (class_name == g_NSArrayI_Transfer) {
798 }
else if (class_name == g_NSConstantArray) {
800 }
else if (class_name == g_NSFrozenArrayM) {
802 }
else if (class_name == g_NSArray0) {
804 }
else if (class_name == g_NSArray1) {
806 }
else if (class_name == g_NSArrayM) {
813 }
else if (class_name == g_NSCallStackArray) {
817 auto iter = map.find(class_name), end = map.end();
819 return iter->second(synth, valobj_sp);
static llvm::raw_ostream & error(Stream &strm)
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()
Generic representation of a type in a programming language.
A uniqued constant string class.
Execution context objects refer to objects in the execution of the program that is being debugged.
static Language * FindPlugin(lldb::LanguageType language)
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
static ObjCLanguageRuntime * Get(Process &process)
virtual ClassDescriptorSP GetClassDescriptor(ValueObject &in_value)
A plug-in interface definition class for debugging a process.
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)
lldb::ValueObjectSP CreateChildValueObjectFromAddress(llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, CompilerType type, bool do_deref=true)
SyntheticChildrenFrontEnd(ValueObject &backend)
lldb::LanguageType GetLanguage() const
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
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::TypeSystemClang > TypeSystemClangSP