9#include "clang/AST/ASTContext.h"
10#include "clang/Basic/TargetInfo.h"
34std::map<ConstString, CXXFunctionSummaryFormat::Callback> &
36 static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
40std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> &
42 static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>
75template <
typename D32,
typename D64>
100 struct DataDescriptor_32 {
109 struct DataDescriptor_64 {
125 struct DataDescriptor_32 {
132 struct DataDescriptor_64 {
145 template <
typename PtrType>
160 template <
typename DD>
166 DD descriptor = DD();
167 process.
ReadMemory(start_of_descriptor, &descriptor,
168 sizeof(descriptor),
error);
172 return descriptor._used;
208template <
typename D32,
typename D64,
bool Inline>
331 static constexpr llvm::StringLiteral g_TypeHint(
"NSArray");
345 if (!descriptor || !descriptor->IsValid())
348 uint32_t ptr_size = process_sp->GetAddressByteSize();
357 ConstString class_name(descriptor->GetClassName());
361 static const ConstString g_NSArrayI_Transfer(
"__NSArrayI_Transfer");
362 static const ConstString g_NSFrozenArrayM(
"__NSFrozenArrayM");
364 static const ConstString g_NSArray1(
"__NSSingleObjectArrayI");
365 static const ConstString g_NSArrayCF(
"__NSCFArray");
366 static const ConstString g_NSArrayMLegacy(
"__NSArrayM_Legacy");
367 static const ConstString g_NSArrayMImmutable(
"__NSArrayM_Immutable");
368 static const ConstString g_NSCallStackArray(
"_NSCallStackArray");
369 static const ConstString g_NSConstantArray(
"NSConstantArray");
374 if (class_name == g_NSArrayI) {
376 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
380 }
else if (class_name == g_NSConstantArray) {
382 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 8,
386 }
else if (class_name == g_NSArrayM) {
388 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
393 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
398 }
else if (class_name == g_NSArrayI_Transfer) {
400 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
404 }
else if (class_name == g_NSFrozenArrayM) {
409 }
else if (class_name == g_NSArrayMLegacy) {
411 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
415 }
else if (class_name == g_NSArrayMImmutable) {
417 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
421 }
else if (class_name == g_NSArray0) {
423 }
else if (class_name == g_NSArray1) {
425 }
else if (class_name == g_NSArrayCF || class_name == g_NSCallStackArray) {
429 value = process_sp->ReadUnsignedIntegerFromMemory(
430 valobj_addr + 2 * ptr_size, ptr_size, 0,
error);
435 auto iter = map.find(class_name), end = map.end();
437 return iter->second(valobj, stream, options);
442 llvm::StringRef prefix, suffix;
444 std::tie(prefix, suffix) = language->GetFormatterPrefixSuffix(g_TypeHint);
447 stream.
Printf(
"%" PRIu64
" %s%s", value,
"element", value == 1 ?
"" :
"s");
457 *valobj_sp->GetExecutionContextRef().GetTargetSP());
460 scratch_ts_sp->weak_from_this(),
461 scratch_ts_sp->getASTContext().ObjCBuiltinIdTy.getAsOpaquePtr());
462 if (valobj_sp->GetProcessSP())
463 m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize();
467template <
typename D32,
typename D64>
485 size_t pyhs_idx = idx;
491 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
496template <
typename D32,
typename D64>
513 m_ptr_size = process_sp->GetAddressByteSize();
514 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
517 process_sp->ReadMemory(data_location,
m_data_32,
sizeof(D32),
521 process_sp->ReadMemory(data_location,
m_data_64,
sizeof(D64),
533 return llvm::createStringError(
"Type has no child named '%s'",
536 uint32_t idx = *optional_idx;
538 return llvm::createStringError(
"Type has no child named '%s'",
543template <
typename D32,
typename D64>
552template <
typename D32,
typename D64>
554lldb_private::formatters::
555 GenericNSArrayMSyntheticFrontEnd<D32, D64>::
556 GenericNSArrayMSyntheticFrontEnd::GetDataAddress() {
557 if (!m_data_32 && !m_data_64)
559 return m_data_32 ? m_data_32->_data : m_data_64->_data;
562template <
typename D32,
typename D64>
564lldb_private::formatters::
565 GenericNSArrayMSyntheticFrontEnd<D32, D64>::
566 GenericNSArrayMSyntheticFrontEnd::GetUsedCount() {
567 if (!m_data_32 && !m_data_64)
569 return m_data_32 ? m_data_32->_used : m_data_64->_used;
572template <
typename D32,
typename D64>
574lldb_private::formatters::
575 GenericNSArrayMSyntheticFrontEnd<D32, D64>::
576 GenericNSArrayMSyntheticFrontEnd::GetOffset() {
577 if (!m_data_32 && !m_data_64)
579 return m_data_32 ? m_data_32->_offset : m_data_64->_offset;
582template <
typename D32,
typename D64>
584lldb_private::formatters::
585 GenericNSArrayMSyntheticFrontEnd<D32, D64>::
586 GenericNSArrayMSyntheticFrontEnd::GetSize() {
587 if (!m_data_32 && !m_data_64)
589 return m_data_32 ? m_data_32->_size : m_data_64->_size;
592template <
typename D32,
typename D64,
bool Inline>
601 *valobj_sp->GetExecutionContextRef().GetTargetSP());
604 scratch_ts_sp->getASTContext().ObjCBuiltinIdTy);
609template <
typename D32,
typename D64,
bool Inline>
618template <
typename D32,
typename D64,
bool Inline>
619llvm::Expected<size_t>
624 return llvm::createStringError(
"Type has no child named '%s'",
627 uint32_t idx = *optional_idx;
629 return llvm::createStringError(
"Type has no child named '%s'",
634template <
typename D32,
typename D64,
bool Inline>
635llvm::Expected<uint32_t>
641template <
typename D32,
typename D64,
bool Inline>
659 m_ptr_size = process_sp->GetAddressByteSize();
660 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) +
m_ptr_size;
663 process_sp->ReadMemory(data_location,
m_data_32,
sizeof(D32),
667 process_sp->ReadMemory(data_location,
m_data_64,
sizeof(D64),
675template <
typename D32,
typename D64,
bool Inline>
684 object_at_idx +=
m_ptr_size == 4 ?
sizeof(D32) :
sizeof(D64);
698 idx_name.
Printf(
"[%" PRIu64
"]", (uint64_t)idx);
707llvm::Expected<size_t>
713llvm::Expected<uint32_t>
737llvm::Expected<size_t>
748llvm::Expected<uint32_t>
768 return m_backend.GetSyntheticChildAtOffset(
769 m_backend.GetProcessSP()->GetAddressByteSize(), id_type,
true,
793 if (flags.
IsClear(eTypeIsPointer)) {
795 valobj_sp = valobj_sp->AddressOf(
error);
796 if (
error.Fail() || !valobj_sp)
803 if (!descriptor || !descriptor->IsValid())
806 ConstString class_name(descriptor->GetClassName());
809 static const ConstString g_NSConstantArray(
"NSConstantArray");
810 static const ConstString g_NSArrayI_Transfer(
"__NSArrayI_Transfer");
811 static const ConstString g_NSFrozenArrayM(
"__NSFrozenArrayM");
814 static const ConstString g_NSArray1(
"__NSSingleObjectArrayI");
815 static const ConstString g_NSArrayMLegacy(
"__NSArrayM_Legacy");
816 static const ConstString g_NSArrayMImmutable(
"__NSArrayM_Immutable");
817 static const ConstString g_NSCallStackArray(
"_NSCallStackArray");
822 if (class_name == g_NSArrayI) {
828 }
else if (class_name == g_NSArrayI_Transfer) {
830 }
else if (class_name == g_NSConstantArray) {
832 }
else if (class_name == g_NSFrozenArrayM) {
834 }
else if (class_name == g_NSArray0) {
836 }
else if (class_name == g_NSArray1) {
838 }
else if (class_name == g_NSArrayM) {
845 }
else if (class_name == g_NSCallStackArray) {
849 auto iter = map.find(class_name), end = map.end();
851 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.
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
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.
Execution context objects refer to objects in the execution of the program that is being debugged.
bool IsClear(ValueType bit) const
Test a single flag bit to see if it is clear (zero).
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.
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 CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, CompilerType type, bool do_deref=true)
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