1 //===-- NSArray.cpp -------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "clang/AST/ASTContext.h"
10 #include "clang/Basic/TargetInfo.h"
14 #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
15 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
17 #include "lldb/Core/ValueObject.h"
18 #include "lldb/Core/ValueObjectConstResult.h"
19 #include "lldb/DataFormatters/FormattersHelpers.h"
20 #include "lldb/Expression/FunctionCaller.h"
21 #include "lldb/Target/Language.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Utility/DataBufferHeap.h"
24 #include "lldb/Utility/Endian.h"
25 #include "lldb/Utility/Status.h"
26 #include "lldb/Utility/Stream.h"
29 using namespace lldb_private
;
30 using namespace lldb_private::formatters
;
32 namespace lldb_private
{
33 namespace formatters
{
34 std::map
<ConstString
, CXXFunctionSummaryFormat::Callback
> &
35 NSArray_Additionals::GetAdditionalSummaries() {
36 static std::map
<ConstString
, CXXFunctionSummaryFormat::Callback
> g_map
;
40 std::map
<ConstString
, CXXSyntheticChildren::CreateFrontEndCallback
> &
41 NSArray_Additionals::GetAdditionalSynthetics() {
42 static std::map
<ConstString
, CXXSyntheticChildren::CreateFrontEndCallback
>
47 class NSArrayMSyntheticFrontEndBase
: public SyntheticChildrenFrontEnd
{
49 NSArrayMSyntheticFrontEndBase(lldb::ValueObjectSP valobj_sp
);
51 ~NSArrayMSyntheticFrontEndBase() override
= default;
53 size_t CalculateNumChildren() override
;
55 lldb::ValueObjectSP
GetChildAtIndex(size_t idx
) override
;
57 bool Update() override
= 0;
59 bool MightHaveChildren() override
;
61 size_t GetIndexOfChildWithName(ConstString name
) override
;
64 virtual lldb::addr_t
GetDataAddress() = 0;
66 virtual uint64_t GetUsedCount() = 0;
68 virtual uint64_t GetOffset() = 0;
70 virtual uint64_t GetSize() = 0;
72 ExecutionContextRef m_exe_ctx_ref
;
73 uint8_t m_ptr_size
= 8;
74 CompilerType m_id_type
;
77 template <typename D32
, typename D64
>
78 class GenericNSArrayMSyntheticFrontEnd
: public NSArrayMSyntheticFrontEndBase
{
80 GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp
);
82 ~GenericNSArrayMSyntheticFrontEnd() override
;
84 bool Update() override
;
87 lldb::addr_t
GetDataAddress() override
;
89 uint64_t GetUsedCount() override
;
91 uint64_t GetOffset() override
;
93 uint64_t GetSize() override
;
100 namespace Foundation1010
{
102 struct DataDescriptor_32
{
111 struct DataDescriptor_64
{
121 using NSArrayMSyntheticFrontEnd
=
122 GenericNSArrayMSyntheticFrontEnd
<DataDescriptor_32
, DataDescriptor_64
>;
125 namespace Foundation1428
{
127 struct DataDescriptor_32
{
134 struct DataDescriptor_64
{
142 using NSArrayMSyntheticFrontEnd
=
143 GenericNSArrayMSyntheticFrontEnd
<DataDescriptor_32
, DataDescriptor_64
>;
146 namespace Foundation1437
{
147 template <typename PtrType
>
148 struct DataDescriptor
{
158 using NSArrayMSyntheticFrontEnd
=
159 GenericNSArrayMSyntheticFrontEnd
<
160 DataDescriptor
<uint32_t>, DataDescriptor
<uint64_t>>;
162 template <typename DD
>
164 __NSArrayMSize_Impl(lldb_private::Process
&process
,
165 lldb::addr_t valobj_addr
, Status
&error
) {
166 const lldb::addr_t start_of_descriptor
=
167 valobj_addr
+ process
.GetAddressByteSize();
168 DD descriptor
= DD();
169 process
.ReadMemory(start_of_descriptor
, &descriptor
,
170 sizeof(descriptor
), error
);
174 return descriptor
._used
;
178 __NSArrayMSize(lldb_private::Process
&process
, lldb::addr_t valobj_addr
,
180 if (process
.GetAddressByteSize() == 4) {
181 return __NSArrayMSize_Impl
<DataDescriptor
<uint32_t>>(process
, valobj_addr
,
184 return __NSArrayMSize_Impl
<DataDescriptor
<uint64_t>>(process
, valobj_addr
,
191 namespace CallStackArray
{
192 struct DataDescriptor_32
{
196 const uint32_t _size
= 0;
199 struct DataDescriptor_64
{
203 const uint64_t _size
= 0;
206 using NSCallStackArraySyntheticFrontEnd
=
207 GenericNSArrayMSyntheticFrontEnd
<DataDescriptor_32
, DataDescriptor_64
>;
208 } // namespace CallStackArray
210 template <typename D32
, typename D64
, bool Inline
>
211 class GenericNSArrayISyntheticFrontEnd
: public SyntheticChildrenFrontEnd
{
213 GenericNSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp
);
215 ~GenericNSArrayISyntheticFrontEnd() override
;
217 size_t CalculateNumChildren() override
;
219 lldb::ValueObjectSP
GetChildAtIndex(size_t idx
) override
;
221 bool Update() override
;
223 bool MightHaveChildren() override
;
225 size_t GetIndexOfChildWithName(ConstString name
) override
;
228 ExecutionContextRef m_exe_ctx_ref
;
229 uint8_t m_ptr_size
= 8;
233 CompilerType m_id_type
;
236 namespace Foundation1300
{
247 using NSArrayISyntheticFrontEnd
=
248 GenericNSArrayISyntheticFrontEnd
<IDD32
, IDD64
, true>;
251 namespace Foundation1430
{
252 using NSArrayISyntheticFrontEnd
=
253 Foundation1428::NSArrayMSyntheticFrontEnd
;
256 namespace Foundation1436
{
259 uint32_t list
; // in Inline cases, this is the first element
264 uint64_t list
; // in Inline cases, this is the first element
267 using NSArrayI_TransferSyntheticFrontEnd
=
268 GenericNSArrayISyntheticFrontEnd
<IDD32
, IDD64
, false>;
270 using NSArrayISyntheticFrontEnd
=
271 GenericNSArrayISyntheticFrontEnd
<IDD32
, IDD64
, true>;
273 using NSFrozenArrayMSyntheticFrontEnd
=
274 Foundation1437::NSArrayMSyntheticFrontEnd
;
277 __NSFrozenArrayMSize(lldb_private::Process
&process
, lldb::addr_t valobj_addr
,
279 return Foundation1437::__NSArrayMSize(process
, valobj_addr
, error
);
283 namespace ConstantArray
{
285 struct ConstantArray32
{
290 struct ConstantArray64
{
295 using NSConstantArraySyntheticFrontEnd
=
296 GenericNSArrayISyntheticFrontEnd
<ConstantArray32
, ConstantArray64
, false>;
297 } // namespace ConstantArray
299 class NSArray0SyntheticFrontEnd
: public SyntheticChildrenFrontEnd
{
301 NSArray0SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp
);
303 ~NSArray0SyntheticFrontEnd() override
= default;
305 size_t CalculateNumChildren() override
;
307 lldb::ValueObjectSP
GetChildAtIndex(size_t idx
) override
;
309 bool Update() override
;
311 bool MightHaveChildren() override
;
313 size_t GetIndexOfChildWithName(ConstString name
) override
;
316 class NSArray1SyntheticFrontEnd
: public SyntheticChildrenFrontEnd
{
318 NSArray1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp
);
320 ~NSArray1SyntheticFrontEnd() override
= default;
322 size_t CalculateNumChildren() override
;
324 lldb::ValueObjectSP
GetChildAtIndex(size_t idx
) override
;
326 bool Update() override
;
328 bool MightHaveChildren() override
;
330 size_t GetIndexOfChildWithName(ConstString name
) override
;
332 } // namespace formatters
333 } // namespace lldb_private
335 bool lldb_private::formatters::NSArraySummaryProvider(
336 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
) {
337 static constexpr llvm::StringLiteral
g_TypeHint("NSArray");
339 ProcessSP process_sp
= valobj
.GetProcessSP();
343 ObjCLanguageRuntime
*runtime
= ObjCLanguageRuntime::Get(*process_sp
);
348 ObjCLanguageRuntime::ClassDescriptorSP
descriptor(
349 runtime
->GetClassDescriptor(valobj
));
351 if (!descriptor
|| !descriptor
->IsValid())
354 uint32_t ptr_size
= process_sp
->GetAddressByteSize();
356 lldb::addr_t valobj_addr
= valobj
.GetValueAsUnsigned(0);
363 ConstString
class_name(descriptor
->GetClassName());
365 static const ConstString
g_NSArrayI("__NSArrayI");
366 static const ConstString
g_NSArrayM("__NSArrayM");
367 static const ConstString
g_NSArrayI_Transfer("__NSArrayI_Transfer");
368 static const ConstString
g_NSFrozenArrayM("__NSFrozenArrayM");
369 static const ConstString
g_NSArray0("__NSArray0");
370 static const ConstString
g_NSArray1("__NSSingleObjectArrayI");
371 static const ConstString
g_NSArrayCF("__NSCFArray");
372 static const ConstString
g_NSArrayMLegacy("__NSArrayM_Legacy");
373 static const ConstString
g_NSArrayMImmutable("__NSArrayM_Immutable");
374 static const ConstString
g_NSCallStackArray("_NSCallStackArray");
375 static const ConstString
g_NSConstantArray("NSConstantArray");
377 if (class_name
.IsEmpty())
380 if (class_name
== g_NSArrayI
) {
382 value
= process_sp
->ReadUnsignedIntegerFromMemory(valobj_addr
+ ptr_size
,
386 } else if (class_name
== g_NSConstantArray
) {
388 value
= process_sp
->ReadUnsignedIntegerFromMemory(valobj_addr
+ ptr_size
, 8,
392 } else if (class_name
== g_NSArrayM
) {
393 AppleObjCRuntime
*apple_runtime
=
394 llvm::dyn_cast_or_null
<AppleObjCRuntime
>(runtime
);
396 if (apple_runtime
&& apple_runtime
->GetFoundationVersion() >= 1437) {
397 value
= Foundation1437::__NSArrayMSize(*process_sp
, valobj_addr
, error
);
399 value
= process_sp
->ReadUnsignedIntegerFromMemory(valobj_addr
+ ptr_size
,
404 } else if (class_name
== g_NSArrayI_Transfer
) {
406 value
= process_sp
->ReadUnsignedIntegerFromMemory(valobj_addr
+ ptr_size
,
410 } else if (class_name
== g_NSFrozenArrayM
) {
412 value
= Foundation1436::__NSFrozenArrayMSize(*process_sp
, valobj_addr
, error
);
415 } else if (class_name
== g_NSArrayMLegacy
) {
417 value
= process_sp
->ReadUnsignedIntegerFromMemory(valobj_addr
+ ptr_size
,
421 } else if (class_name
== g_NSArrayMImmutable
) {
423 value
= process_sp
->ReadUnsignedIntegerFromMemory(valobj_addr
+ ptr_size
,
427 } else if (class_name
== g_NSArray0
) {
429 } else if (class_name
== g_NSArray1
) {
431 } else if (class_name
== g_NSArrayCF
|| class_name
== g_NSCallStackArray
) {
432 // __NSCFArray and _NSCallStackArray store the number of elements as a
433 // pointer-sized value at offset `2 * ptr_size`.
435 value
= process_sp
->ReadUnsignedIntegerFromMemory(
436 valobj_addr
+ 2 * ptr_size
, ptr_size
, 0, error
);
440 auto &map(NSArray_Additionals::GetAdditionalSummaries());
441 auto iter
= map
.find(class_name
), end
= map
.end();
443 return iter
->second(valobj
, stream
, options
);
448 llvm::StringRef prefix
, suffix
;
449 if (Language
*language
= Language::FindPlugin(options
.GetLanguage()))
450 std::tie(prefix
, suffix
) = language
->GetFormatterPrefixSuffix(g_TypeHint
);
453 stream
.Printf("%" PRIu64
" %s%s", value
, "element", value
== 1 ? "" : "s");
458 lldb_private::formatters::NSArrayMSyntheticFrontEndBase::
459 NSArrayMSyntheticFrontEndBase(lldb::ValueObjectSP valobj_sp
)
460 : SyntheticChildrenFrontEnd(*valobj_sp
), m_exe_ctx_ref(), m_id_type() {
462 TypeSystemClangSP scratch_ts_sp
= ScratchTypeSystemClang::GetForTarget(
463 *valobj_sp
->GetExecutionContextRef().GetTargetSP());
465 m_id_type
= CompilerType(
466 scratch_ts_sp
->weak_from_this(),
467 scratch_ts_sp
->getASTContext().ObjCBuiltinIdTy
.getAsOpaquePtr());
468 if (valobj_sp
->GetProcessSP())
469 m_ptr_size
= valobj_sp
->GetProcessSP()->GetAddressByteSize();
473 template <typename D32
, typename D64
>
474 lldb_private::formatters::
475 GenericNSArrayMSyntheticFrontEnd
<D32
, D64
>::
476 GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp
)
477 : NSArrayMSyntheticFrontEndBase(valobj_sp
), m_data_32(nullptr),
478 m_data_64(nullptr) {}
481 lldb_private::formatters::NSArrayMSyntheticFrontEndBase::CalculateNumChildren() {
482 return GetUsedCount();
486 lldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetChildAtIndex(
488 if (idx
>= CalculateNumChildren())
489 return lldb::ValueObjectSP();
490 lldb::addr_t object_at_idx
= GetDataAddress();
491 size_t pyhs_idx
= idx
;
492 pyhs_idx
+= GetOffset();
493 if (GetSize() <= pyhs_idx
)
494 pyhs_idx
-= GetSize();
495 object_at_idx
+= (pyhs_idx
* m_ptr_size
);
496 StreamString idx_name
;
497 idx_name
.Printf("[%" PRIu64
"]", (uint64_t)idx
);
498 return CreateValueObjectFromAddress(idx_name
.GetString(), object_at_idx
,
499 m_exe_ctx_ref
, m_id_type
);
502 template <typename D32
, typename D64
>
504 lldb_private::formatters::
505 GenericNSArrayMSyntheticFrontEnd
<D32
, D64
>::Update() {
506 ValueObjectSP valobj_sp
= m_backend
.GetSP();
514 m_exe_ctx_ref
= valobj_sp
->GetExecutionContextRef();
517 lldb::ProcessSP
process_sp(valobj_sp
->GetProcessSP());
520 m_ptr_size
= process_sp
->GetAddressByteSize();
521 uint64_t data_location
= valobj_sp
->GetValueAsUnsigned(0) + m_ptr_size
;
522 if (m_ptr_size
== 4) {
523 m_data_32
= new D32();
524 process_sp
->ReadMemory(data_location
, m_data_32
, sizeof(D32
),
527 m_data_64
= new D64();
528 process_sp
->ReadMemory(data_location
, m_data_64
, sizeof(D64
),
532 return error
.Success();
536 lldb_private::formatters::NSArrayMSyntheticFrontEndBase::MightHaveChildren() {
541 lldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetIndexOfChildWithName(
543 const char *item_name
= name
.GetCString();
544 uint32_t idx
= ExtractIndexFromString(item_name
);
545 if (idx
< UINT32_MAX
&& idx
>= CalculateNumChildren())
550 template <typename D32
, typename D64
>
551 lldb_private::formatters::
552 GenericNSArrayMSyntheticFrontEnd
<D32
, D64
>::
553 ~GenericNSArrayMSyntheticFrontEnd
<D32
, D64
>() {
560 template <typename D32
, typename D64
>
562 lldb_private::formatters::
563 GenericNSArrayMSyntheticFrontEnd
<D32
, D64
>::
564 GenericNSArrayMSyntheticFrontEnd::GetDataAddress() {
565 if (!m_data_32
&& !m_data_64
)
566 return LLDB_INVALID_ADDRESS
;
567 return m_data_32
? m_data_32
->_data
: m_data_64
->_data
;
570 template <typename D32
, typename D64
>
572 lldb_private::formatters::
573 GenericNSArrayMSyntheticFrontEnd
<D32
, D64
>::
574 GenericNSArrayMSyntheticFrontEnd::GetUsedCount() {
575 if (!m_data_32
&& !m_data_64
)
577 return m_data_32
? m_data_32
->_used
: m_data_64
->_used
;
580 template <typename D32
, typename D64
>
582 lldb_private::formatters::
583 GenericNSArrayMSyntheticFrontEnd
<D32
, D64
>::
584 GenericNSArrayMSyntheticFrontEnd::GetOffset() {
585 if (!m_data_32
&& !m_data_64
)
587 return m_data_32
? m_data_32
->_offset
: m_data_64
->_offset
;
590 template <typename D32
, typename D64
>
592 lldb_private::formatters::
593 GenericNSArrayMSyntheticFrontEnd
<D32
, D64
>::
594 GenericNSArrayMSyntheticFrontEnd::GetSize() {
595 if (!m_data_32
&& !m_data_64
)
597 return m_data_32
? m_data_32
->_size
: m_data_64
->_size
;
600 template <typename D32
, typename D64
, bool Inline
>
601 lldb_private::formatters::GenericNSArrayISyntheticFrontEnd
<D32
, D64
, Inline
>::
602 GenericNSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp
)
603 : SyntheticChildrenFrontEnd(*valobj_sp
), m_exe_ctx_ref(),
604 m_data_32(nullptr), m_data_64(nullptr) {
606 CompilerType type
= valobj_sp
->GetCompilerType();
608 TypeSystemClangSP scratch_ts_sp
= ScratchTypeSystemClang::GetForTarget(
609 *valobj_sp
->GetExecutionContextRef().GetTargetSP());
611 m_id_type
= scratch_ts_sp
->GetType(
612 scratch_ts_sp
->getASTContext().ObjCBuiltinIdTy
);
617 template <typename D32
, typename D64
, bool Inline
>
618 lldb_private::formatters::GenericNSArrayISyntheticFrontEnd
<D32
, D64
, Inline
>::
619 ~GenericNSArrayISyntheticFrontEnd
<D32
, D64
, Inline
>() {
626 template <typename D32
, typename D64
, bool Inline
>
628 lldb_private::formatters::GenericNSArrayISyntheticFrontEnd
<D32
, D64
, Inline
>::
629 GetIndexOfChildWithName(ConstString name
) {
630 const char *item_name
= name
.GetCString();
631 uint32_t idx
= ExtractIndexFromString(item_name
);
632 if (idx
< UINT32_MAX
&& idx
>= CalculateNumChildren())
637 template <typename D32
, typename D64
, bool Inline
>
639 lldb_private::formatters::GenericNSArrayISyntheticFrontEnd
<D32
, D64
, Inline
>::
640 CalculateNumChildren() {
641 return m_data_32
? m_data_32
->used
: m_data_64
->used
;
644 template <typename D32
, typename D64
, bool Inline
>
646 lldb_private::formatters::GenericNSArrayISyntheticFrontEnd
<D32
, D64
, Inline
>::
648 ValueObjectSP valobj_sp
= m_backend
.GetSP();
656 m_exe_ctx_ref
= valobj_sp
->GetExecutionContextRef();
659 lldb::ProcessSP
process_sp(valobj_sp
->GetProcessSP());
662 m_ptr_size
= process_sp
->GetAddressByteSize();
663 uint64_t data_location
= valobj_sp
->GetValueAsUnsigned(0) + m_ptr_size
;
664 if (m_ptr_size
== 4) {
665 m_data_32
= new D32();
666 process_sp
->ReadMemory(data_location
, m_data_32
, sizeof(D32
),
669 m_data_64
= new D64();
670 process_sp
->ReadMemory(data_location
, m_data_64
, sizeof(D64
),
674 return error
.Success();
677 template <typename D32
, typename D64
, bool Inline
>
679 lldb_private::formatters::GenericNSArrayISyntheticFrontEnd
<D32
, D64
, Inline
>::
680 MightHaveChildren() {
684 template <typename D32
, typename D64
, bool Inline
>
686 lldb_private::formatters::GenericNSArrayISyntheticFrontEnd
<D32
, D64
, Inline
>::
687 GetChildAtIndex(size_t idx
) {
688 if (idx
>= CalculateNumChildren())
689 return lldb::ValueObjectSP();
690 lldb::addr_t object_at_idx
;
692 object_at_idx
= m_backend
.GetSP()->GetValueAsUnsigned(0) + m_ptr_size
;
693 object_at_idx
+= m_ptr_size
== 4 ? sizeof(D32
) : sizeof(D64
); // skip the data header
694 object_at_idx
-= m_ptr_size
; // we treat the last entry in the data header as the first pointer
696 object_at_idx
= m_data_32
? m_data_32
->list
: m_data_64
->list
;
698 object_at_idx
+= (idx
* m_ptr_size
);
700 ProcessSP process_sp
= m_exe_ctx_ref
.GetProcessSP();
702 return lldb::ValueObjectSP();
705 return lldb::ValueObjectSP();
706 StreamString idx_name
;
707 idx_name
.Printf("[%" PRIu64
"]", (uint64_t)idx
);
708 return CreateValueObjectFromAddress(idx_name
.GetString(), object_at_idx
,
709 m_exe_ctx_ref
, m_id_type
);
712 lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd(
713 lldb::ValueObjectSP valobj_sp
)
714 : SyntheticChildrenFrontEnd(*valobj_sp
) {}
717 lldb_private::formatters::NSArray0SyntheticFrontEnd::GetIndexOfChildWithName(
723 lldb_private::formatters::NSArray0SyntheticFrontEnd::CalculateNumChildren() {
727 bool lldb_private::formatters::NSArray0SyntheticFrontEnd::Update() {
731 bool lldb_private::formatters::NSArray0SyntheticFrontEnd::MightHaveChildren() {
736 lldb_private::formatters::NSArray0SyntheticFrontEnd::GetChildAtIndex(
738 return lldb::ValueObjectSP();
741 lldb_private::formatters::NSArray1SyntheticFrontEnd::NSArray1SyntheticFrontEnd(
742 lldb::ValueObjectSP valobj_sp
)
743 : SyntheticChildrenFrontEnd(*valobj_sp
.get()) {}
746 lldb_private::formatters::NSArray1SyntheticFrontEnd::GetIndexOfChildWithName(
748 static const ConstString
g_zero("[0]");
757 lldb_private::formatters::NSArray1SyntheticFrontEnd::CalculateNumChildren() {
761 bool lldb_private::formatters::NSArray1SyntheticFrontEnd::Update() {
765 bool lldb_private::formatters::NSArray1SyntheticFrontEnd::MightHaveChildren() {
770 lldb_private::formatters::NSArray1SyntheticFrontEnd::GetChildAtIndex(
772 static const ConstString
g_zero("[0]");
775 TypeSystemClangSP scratch_ts_sp
=
776 ScratchTypeSystemClang::GetForTarget(*m_backend
.GetTargetSP());
778 CompilerType
id_type(scratch_ts_sp
->GetBasicType(lldb::eBasicTypeObjCID
));
779 return m_backend
.GetSyntheticChildAtOffset(
780 m_backend
.GetProcessSP()->GetAddressByteSize(), id_type
, true,
784 return lldb::ValueObjectSP();
787 SyntheticChildrenFrontEnd
*
788 lldb_private::formatters::NSArraySyntheticFrontEndCreator(
789 CXXSyntheticChildren
*synth
, lldb::ValueObjectSP valobj_sp
) {
793 lldb::ProcessSP
process_sp(valobj_sp
->GetProcessSP());
796 AppleObjCRuntime
*runtime
= llvm::dyn_cast_or_null
<AppleObjCRuntime
>(
797 ObjCLanguageRuntime::Get(*process_sp
));
801 CompilerType
valobj_type(valobj_sp
->GetCompilerType());
802 Flags
flags(valobj_type
.GetTypeInfo());
804 if (flags
.IsClear(eTypeIsPointer
)) {
806 valobj_sp
= valobj_sp
->AddressOf(error
);
807 if (error
.Fail() || !valobj_sp
)
811 ObjCLanguageRuntime::ClassDescriptorSP
descriptor(
812 runtime
->GetClassDescriptor(*valobj_sp
));
814 if (!descriptor
|| !descriptor
->IsValid())
817 ConstString
class_name(descriptor
->GetClassName());
819 static const ConstString
g_NSArrayI("__NSArrayI");
820 static const ConstString
g_NSConstantArray("NSConstantArray");
821 static const ConstString
g_NSArrayI_Transfer("__NSArrayI_Transfer");
822 static const ConstString
g_NSFrozenArrayM("__NSFrozenArrayM");
823 static const ConstString
g_NSArrayM("__NSArrayM");
824 static const ConstString
g_NSArray0("__NSArray0");
825 static const ConstString
g_NSArray1("__NSSingleObjectArrayI");
826 static const ConstString
g_NSArrayMLegacy("__NSArrayM_Legacy");
827 static const ConstString
g_NSArrayMImmutable("__NSArrayM_Immutable");
828 static const ConstString
g_NSCallStackArray("_NSCallStackArray");
830 if (class_name
.IsEmpty())
833 if (class_name
== g_NSArrayI
) {
834 if (runtime
->GetFoundationVersion() >= 1436)
835 return (new Foundation1436::NSArrayISyntheticFrontEnd(valobj_sp
));
836 if (runtime
->GetFoundationVersion() >= 1430)
837 return (new Foundation1430::NSArrayISyntheticFrontEnd(valobj_sp
));
838 return (new Foundation1300::NSArrayISyntheticFrontEnd(valobj_sp
));
839 } else if (class_name
== g_NSArrayI_Transfer
) {
840 return (new Foundation1436::NSArrayI_TransferSyntheticFrontEnd(valobj_sp
));
841 } else if (class_name
== g_NSConstantArray
) {
842 return new ConstantArray::NSConstantArraySyntheticFrontEnd(valobj_sp
);
843 } else if (class_name
== g_NSFrozenArrayM
) {
844 return (new Foundation1436::NSFrozenArrayMSyntheticFrontEnd(valobj_sp
));
845 } else if (class_name
== g_NSArray0
) {
846 return (new NSArray0SyntheticFrontEnd(valobj_sp
));
847 } else if (class_name
== g_NSArray1
) {
848 return (new NSArray1SyntheticFrontEnd(valobj_sp
));
849 } else if (class_name
== g_NSArrayM
) {
850 if (runtime
->GetFoundationVersion() >= 1437)
851 return (new Foundation1437::NSArrayMSyntheticFrontEnd(valobj_sp
));
852 if (runtime
->GetFoundationVersion() >= 1428)
853 return (new Foundation1428::NSArrayMSyntheticFrontEnd(valobj_sp
));
854 if (runtime
->GetFoundationVersion() >= 1100)
855 return (new Foundation1010::NSArrayMSyntheticFrontEnd(valobj_sp
));
856 } else if (class_name
== g_NSCallStackArray
) {
857 return (new CallStackArray::NSCallStackArraySyntheticFrontEnd(valobj_sp
));
859 auto &map(NSArray_Additionals::GetAdditionalSynthetics());
860 auto iter
= map
.find(class_name
), end
= map
.end();
862 return iter
->second(synth
, valobj_sp
);