1 //===-- NSSet.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 //===----------------------------------------------------------------------===//
10 #include "CFBasicHash.h"
12 #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
13 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
14 #include "lldb/DataFormatters/FormattersHelpers.h"
15 #include "lldb/Target/Language.h"
16 #include "lldb/Target/Target.h"
17 #include "lldb/Utility/DataBufferHeap.h"
18 #include "lldb/Utility/Endian.h"
19 #include "lldb/Utility/Status.h"
20 #include "lldb/Utility/Stream.h"
21 #include "lldb/ValueObject/ValueObject.h"
22 #include "lldb/ValueObject/ValueObjectConstResult.h"
25 using namespace lldb_private
;
26 using namespace lldb_private::formatters
;
28 std::map
<ConstString
, CXXFunctionSummaryFormat::Callback
> &
29 NSSet_Additionals::GetAdditionalSummaries() {
30 static std::map
<ConstString
, CXXFunctionSummaryFormat::Callback
> g_map
;
34 std::map
<ConstString
, CXXSyntheticChildren::CreateFrontEndCallback
> &
35 NSSet_Additionals::GetAdditionalSynthetics() {
36 static std::map
<ConstString
, CXXSyntheticChildren::CreateFrontEndCallback
>
41 namespace lldb_private
{
42 namespace formatters
{
43 class NSSetISyntheticFrontEnd
: public SyntheticChildrenFrontEnd
{
45 NSSetISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp
);
47 ~NSSetISyntheticFrontEnd() override
;
49 llvm::Expected
<uint32_t> CalculateNumChildren() override
;
51 lldb::ValueObjectSP
GetChildAtIndex(uint32_t idx
) override
;
53 lldb::ChildCacheState
Update() override
;
55 bool MightHaveChildren() override
;
57 size_t GetIndexOfChildWithName(ConstString name
) override
;
60 struct DataDescriptor_32
{
65 struct DataDescriptor_64
{
70 struct SetItemDescriptor
{
71 lldb::addr_t item_ptr
;
72 lldb::ValueObjectSP valobj_sp
;
75 ExecutionContextRef m_exe_ctx_ref
;
76 uint8_t m_ptr_size
= 8;
77 DataDescriptor_32
*m_data_32
= nullptr;
78 DataDescriptor_64
*m_data_64
= nullptr;
79 lldb::addr_t m_data_ptr
= LLDB_INVALID_ADDRESS
;
80 std::vector
<SetItemDescriptor
> m_children
;
83 class NSCFSetSyntheticFrontEnd
: public SyntheticChildrenFrontEnd
{
85 NSCFSetSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp
);
87 llvm::Expected
<uint32_t> CalculateNumChildren() override
;
89 lldb::ValueObjectSP
GetChildAtIndex(uint32_t idx
) override
;
91 lldb::ChildCacheState
Update() override
;
93 bool MightHaveChildren() override
;
95 size_t GetIndexOfChildWithName(ConstString name
) override
;
98 struct SetItemDescriptor
{
99 lldb::addr_t item_ptr
;
100 lldb::ValueObjectSP valobj_sp
;
103 ExecutionContextRef m_exe_ctx_ref
;
104 uint8_t m_ptr_size
= 8;
105 lldb::ByteOrder m_order
= lldb::eByteOrderInvalid
;
107 CFBasicHash m_hashtable
;
109 CompilerType m_pair_type
;
110 std::vector
<SetItemDescriptor
> m_children
;
113 template <typename D32
, typename D64
>
114 class GenericNSSetMSyntheticFrontEnd
: public SyntheticChildrenFrontEnd
{
116 GenericNSSetMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp
);
118 ~GenericNSSetMSyntheticFrontEnd() override
;
120 llvm::Expected
<uint32_t> CalculateNumChildren() override
;
122 lldb::ValueObjectSP
GetChildAtIndex(uint32_t idx
) override
;
124 lldb::ChildCacheState
Update() override
;
126 bool MightHaveChildren() override
;
128 size_t GetIndexOfChildWithName(ConstString name
) override
;
132 struct SetItemDescriptor
{
133 lldb::addr_t item_ptr
;
134 lldb::ValueObjectSP valobj_sp
;
137 ExecutionContextRef m_exe_ctx_ref
;
138 uint8_t m_ptr_size
= 8;
141 std::vector
<SetItemDescriptor
> m_children
;
144 namespace Foundation1300
{
145 struct DataDescriptor_32
{
152 struct DataDescriptor_64
{
159 using NSSetMSyntheticFrontEnd
=
160 GenericNSSetMSyntheticFrontEnd
<DataDescriptor_32
, DataDescriptor_64
>;
163 namespace Foundation1428
{
164 struct DataDescriptor_32
{
171 struct DataDescriptor_64
{
178 using NSSetMSyntheticFrontEnd
=
179 GenericNSSetMSyntheticFrontEnd
<DataDescriptor_32
, DataDescriptor_64
>;
182 namespace Foundation1437
{
183 struct DataDescriptor_32
{
192 struct DataDescriptor_64
{
201 using NSSetMSyntheticFrontEnd
=
202 GenericNSSetMSyntheticFrontEnd
<DataDescriptor_32
, DataDescriptor_64
>;
204 template <typename DD
>
206 __NSSetMSize_Impl(lldb_private::Process
&process
, lldb::addr_t valobj_addr
,
208 const lldb::addr_t start_of_descriptor
=
209 valobj_addr
+ process
.GetAddressByteSize();
210 DD descriptor
= DD();
211 process
.ReadMemory(start_of_descriptor
, &descriptor
, sizeof(descriptor
),
216 return descriptor
._used
;
220 __NSSetMSize(lldb_private::Process
&process
, lldb::addr_t valobj_addr
,
222 if (process
.GetAddressByteSize() == 4) {
223 return __NSSetMSize_Impl
<DataDescriptor_32
>(process
, valobj_addr
, error
);
225 return __NSSetMSize_Impl
<DataDescriptor_64
>(process
, valobj_addr
, error
);
230 class NSSetCodeRunningSyntheticFrontEnd
: public SyntheticChildrenFrontEnd
{
232 NSSetCodeRunningSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp
);
234 ~NSSetCodeRunningSyntheticFrontEnd() override
;
236 llvm::Expected
<uint32_t> CalculateNumChildren() override
;
238 lldb::ValueObjectSP
GetChildAtIndex(uint32_t idx
) override
;
240 lldb::ChildCacheState
Update() override
;
242 bool MightHaveChildren() override
;
244 size_t GetIndexOfChildWithName(ConstString name
) override
;
246 } // namespace formatters
247 } // namespace lldb_private
249 template <bool cf_style
>
250 bool lldb_private::formatters::NSSetSummaryProvider(
251 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
) {
252 static constexpr llvm::StringLiteral
g_TypeHint("NSSet");
254 ProcessSP process_sp
= valobj
.GetProcessSP();
258 ObjCLanguageRuntime
*runtime
= ObjCLanguageRuntime::Get(*process_sp
);
263 ObjCLanguageRuntime::ClassDescriptorSP
descriptor(
264 runtime
->GetClassDescriptor(valobj
));
266 if (!descriptor
|| !descriptor
->IsValid())
269 uint32_t ptr_size
= process_sp
->GetAddressByteSize();
270 bool is_64bit
= (ptr_size
== 8);
272 lldb::addr_t valobj_addr
= valobj
.GetValueAsUnsigned(0);
279 ConstString
class_name(descriptor
->GetClassName());
281 static const ConstString
g_SetI("__NSSetI");
282 static const ConstString
g_OrderedSetI("__NSOrderedSetI");
283 static const ConstString
g_SetM("__NSSetM");
284 static const ConstString
g_SetCF("__NSCFSet");
285 static const ConstString
g_SetCFRef("CFSetRef");
287 if (class_name
.IsEmpty())
290 if (class_name
== g_SetI
|| class_name
== g_OrderedSetI
) {
292 value
= process_sp
->ReadUnsignedIntegerFromMemory(valobj_addr
+ ptr_size
,
296 value
&= (is_64bit
? ~0xFC00000000000000UL
: ~0xFC000000U
);
297 } else if (class_name
== g_SetM
) {
298 AppleObjCRuntime
*apple_runtime
=
299 llvm::dyn_cast_or_null
<AppleObjCRuntime
>(runtime
);
301 if (apple_runtime
&& apple_runtime
->GetFoundationVersion() >= 1437) {
302 value
= Foundation1437::__NSSetMSize(*process_sp
, valobj_addr
, error
);
304 value
= process_sp
->ReadUnsignedIntegerFromMemory(valobj_addr
+ ptr_size
,
306 value
&= (is_64bit
? ~0xFC00000000000000UL
: ~0xFC000000U
);
310 } else if (class_name
== g_SetCF
|| class_name
== g_SetCFRef
) {
311 ExecutionContext
exe_ctx(process_sp
);
313 if (!cfbh
.Update(valobj_addr
, exe_ctx
))
315 value
= cfbh
.GetCount();
317 auto &map(NSSet_Additionals::GetAdditionalSummaries());
318 auto iter
= map
.find(class_name
), end
= map
.end();
320 return iter
->second(valobj
, stream
, options
);
325 llvm::StringRef prefix
, suffix
;
326 if (Language
*language
= Language::FindPlugin(options
.GetLanguage()))
327 std::tie(prefix
, suffix
) = language
->GetFormatterPrefixSuffix(g_TypeHint
);
330 stream
.Printf("%" PRIu64
" %s%s", value
, "element", value
== 1 ? "" : "s");
335 SyntheticChildrenFrontEnd
*
336 lldb_private::formatters::NSSetSyntheticFrontEndCreator(
337 CXXSyntheticChildren
*synth
, lldb::ValueObjectSP valobj_sp
) {
338 lldb::ProcessSP
process_sp(valobj_sp
->GetProcessSP());
341 ObjCLanguageRuntime
*runtime
= ObjCLanguageRuntime::Get(*process_sp
);
345 CompilerType
valobj_type(valobj_sp
->GetCompilerType());
346 Flags
flags(valobj_type
.GetTypeInfo());
348 if (flags
.IsClear(eTypeIsPointer
)) {
350 valobj_sp
= valobj_sp
->AddressOf(error
);
351 if (error
.Fail() || !valobj_sp
)
355 ObjCLanguageRuntime::ClassDescriptorSP
descriptor(
356 runtime
->GetClassDescriptor(*valobj_sp
));
358 if (!descriptor
|| !descriptor
->IsValid())
361 ConstString class_name
= descriptor
->GetClassName();
363 static const ConstString
g_SetI("__NSSetI");
364 static const ConstString
g_OrderedSetI("__NSOrderedSetI");
365 static const ConstString
g_SetM("__NSSetM");
366 static const ConstString
g_SetCF("__NSCFSet");
367 static const ConstString
g_SetCFRef("CFSetRef");
369 if (class_name
.IsEmpty())
372 if (class_name
== g_SetI
|| class_name
== g_OrderedSetI
) {
373 return (new NSSetISyntheticFrontEnd(valobj_sp
));
374 } else if (class_name
== g_SetM
) {
375 AppleObjCRuntime
*apple_runtime
=
376 llvm::dyn_cast_or_null
<AppleObjCRuntime
>(runtime
);
378 if (apple_runtime
->GetFoundationVersion() >= 1437)
379 return (new Foundation1437::NSSetMSyntheticFrontEnd(valobj_sp
));
380 else if (apple_runtime
->GetFoundationVersion() >= 1428)
381 return (new Foundation1428::NSSetMSyntheticFrontEnd(valobj_sp
));
383 return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp
));
385 return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp
));
387 } else if (class_name
== g_SetCF
|| class_name
== g_SetCFRef
) {
388 return (new NSCFSetSyntheticFrontEnd(valobj_sp
));
390 auto &map(NSSet_Additionals::GetAdditionalSynthetics());
391 auto iter
= map
.find(class_name
), end
= map
.end();
393 return iter
->second(synth
, valobj_sp
);
398 lldb_private::formatters::NSSetISyntheticFrontEnd::NSSetISyntheticFrontEnd(
399 lldb::ValueObjectSP valobj_sp
)
400 : SyntheticChildrenFrontEnd(*valobj_sp
), m_exe_ctx_ref() {
405 lldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd() {
413 lldb_private::formatters::NSSetISyntheticFrontEnd::GetIndexOfChildWithName(
415 const char *item_name
= name
.GetCString();
416 uint32_t idx
= ExtractIndexFromString(item_name
);
417 if (idx
< UINT32_MAX
&& idx
>= CalculateNumChildrenIgnoringErrors())
422 llvm::Expected
<uint32_t>
423 lldb_private::formatters::NSSetISyntheticFrontEnd::CalculateNumChildren() {
424 if (!m_data_32
&& !m_data_64
)
426 return (m_data_32
? m_data_32
->_used
: m_data_64
->_used
);
429 lldb::ChildCacheState
430 lldb_private::formatters::NSSetISyntheticFrontEnd::Update() {
437 ValueObjectSP valobj_sp
= m_backend
.GetSP();
439 return lldb::ChildCacheState::eRefetch
;
441 return lldb::ChildCacheState::eRefetch
;
442 m_exe_ctx_ref
= valobj_sp
->GetExecutionContextRef();
443 lldb::ProcessSP
process_sp(valobj_sp
->GetProcessSP());
445 return lldb::ChildCacheState::eRefetch
;
446 m_ptr_size
= process_sp
->GetAddressByteSize();
447 uint64_t data_location
= valobj_sp
->GetValueAsUnsigned(0) + m_ptr_size
;
449 if (m_ptr_size
== 4) {
450 m_data_32
= new DataDescriptor_32();
451 process_sp
->ReadMemory(data_location
, m_data_32
, sizeof(DataDescriptor_32
),
454 m_data_64
= new DataDescriptor_64();
455 process_sp
->ReadMemory(data_location
, m_data_64
, sizeof(DataDescriptor_64
),
459 return lldb::ChildCacheState::eRefetch
;
460 m_data_ptr
= data_location
+ m_ptr_size
;
461 return lldb::ChildCacheState::eReuse
;
464 bool lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren() {
469 lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex(
471 uint32_t num_children
= CalculateNumChildrenIgnoringErrors();
473 if (idx
>= num_children
)
474 return lldb::ValueObjectSP();
476 ProcessSP process_sp
= m_exe_ctx_ref
.GetProcessSP();
478 return lldb::ValueObjectSP();
480 if (m_children
.empty()) {
482 lldb::addr_t obj_at_idx
= 0;
485 uint32_t test_idx
= 0;
487 while (tries
< num_children
) {
488 obj_at_idx
= m_data_ptr
+ (test_idx
* m_ptr_size
);
490 return lldb::ValueObjectSP();
492 obj_at_idx
= process_sp
->ReadPointerFromMemory(obj_at_idx
, error
);
494 return lldb::ValueObjectSP();
502 SetItemDescriptor descriptor
= {obj_at_idx
, lldb::ValueObjectSP()};
504 m_children
.push_back(descriptor
);
508 if (idx
>= m_children
.size()) // should never happen
509 return lldb::ValueObjectSP();
511 SetItemDescriptor
&set_item
= m_children
[idx
];
512 if (!set_item
.valobj_sp
) {
513 auto ptr_size
= process_sp
->GetAddressByteSize();
514 DataBufferHeap
buffer(ptr_size
, 0);
516 case 0: // architecture has no clue - fail
517 return lldb::ValueObjectSP();
519 *reinterpret_cast<uint32_t *>(buffer
.GetBytes()) =
520 static_cast<uint32_t>(set_item
.item_ptr
);
523 *reinterpret_cast<uint64_t *>(buffer
.GetBytes()) =
524 static_cast<uint64_t>(set_item
.item_ptr
);
527 lldbassert(false && "pointer size is not 4 nor 8");
529 StreamString idx_name
;
530 idx_name
.Printf("[%" PRIu64
"]", (uint64_t)idx
);
532 DataExtractor
data(buffer
.GetBytes(), buffer
.GetByteSize(),
533 process_sp
->GetByteOrder(),
534 process_sp
->GetAddressByteSize());
536 set_item
.valobj_sp
= CreateValueObjectFromData(
537 idx_name
.GetString(), data
, m_exe_ctx_ref
,
538 m_backend
.GetCompilerType().GetBasicTypeFromAST(
539 lldb::eBasicTypeObjCID
));
541 return set_item
.valobj_sp
;
544 lldb_private::formatters::NSCFSetSyntheticFrontEnd::NSCFSetSyntheticFrontEnd(
545 lldb::ValueObjectSP valobj_sp
)
546 : SyntheticChildrenFrontEnd(*valobj_sp
), m_exe_ctx_ref(), m_hashtable(),
550 lldb_private::formatters::NSCFSetSyntheticFrontEnd::GetIndexOfChildWithName(
552 const char *item_name
= name
.GetCString();
553 const uint32_t idx
= ExtractIndexFromString(item_name
);
554 if (idx
< UINT32_MAX
&& idx
>= CalculateNumChildrenIgnoringErrors())
559 llvm::Expected
<uint32_t>
560 lldb_private::formatters::NSCFSetSyntheticFrontEnd::CalculateNumChildren() {
561 if (!m_hashtable
.IsValid())
563 return m_hashtable
.GetCount();
566 lldb::ChildCacheState
567 lldb_private::formatters::NSCFSetSyntheticFrontEnd::Update() {
569 ValueObjectSP valobj_sp
= m_backend
.GetSP();
572 return lldb::ChildCacheState::eRefetch
;
573 m_exe_ctx_ref
= valobj_sp
->GetExecutionContextRef();
575 lldb::ProcessSP
process_sp(valobj_sp
->GetProcessSP());
577 return lldb::ChildCacheState::eRefetch
;
578 m_ptr_size
= process_sp
->GetAddressByteSize();
579 m_order
= process_sp
->GetByteOrder();
580 return m_hashtable
.Update(valobj_sp
->GetValueAsUnsigned(0), m_exe_ctx_ref
)
581 ? lldb::ChildCacheState::eReuse
582 : lldb::ChildCacheState::eRefetch
;
585 bool lldb_private::formatters::NSCFSetSyntheticFrontEnd::MightHaveChildren() {
590 lldb_private::formatters::NSCFSetSyntheticFrontEnd::GetChildAtIndex(
592 lldb::addr_t m_values_ptr
= m_hashtable
.GetValuePointer();
594 const uint32_t num_children
= CalculateNumChildrenIgnoringErrors();
596 if (idx
>= num_children
)
597 return lldb::ValueObjectSP();
599 if (m_children
.empty()) {
600 ProcessSP process_sp
= m_exe_ctx_ref
.GetProcessSP();
602 return lldb::ValueObjectSP();
605 lldb::addr_t val_at_idx
= 0;
608 uint32_t test_idx
= 0;
610 // Iterate over inferior memory, reading value pointers by shifting the
611 // cursor by test_index * m_ptr_size. Returns an empty ValueObject if a read
612 // fails, otherwise, continue until the number of tries matches the number
614 while (tries
< num_children
) {
615 val_at_idx
= m_values_ptr
+ (test_idx
* m_ptr_size
);
617 val_at_idx
= process_sp
->ReadPointerFromMemory(val_at_idx
, error
);
619 return lldb::ValueObjectSP();
627 SetItemDescriptor descriptor
= {val_at_idx
, lldb::ValueObjectSP()};
629 m_children
.push_back(descriptor
);
633 if (idx
>= m_children
.size()) // should never happen
634 return lldb::ValueObjectSP();
636 SetItemDescriptor
&set_item
= m_children
[idx
];
637 if (!set_item
.valobj_sp
) {
639 WritableDataBufferSP
buffer_sp(new DataBufferHeap(m_ptr_size
, 0));
641 switch (m_ptr_size
) {
642 case 0: // architecture has no clue - fail
643 return lldb::ValueObjectSP();
645 *reinterpret_cast<uint32_t *>(buffer_sp
->GetBytes()) =
646 static_cast<uint32_t>(set_item
.item_ptr
);
649 *reinterpret_cast<uint64_t *>(buffer_sp
->GetBytes()) =
650 static_cast<uint64_t>(set_item
.item_ptr
);
653 lldbassert(false && "pointer size is not 4 nor 8");
655 StreamString idx_name
;
656 idx_name
.Printf("[%" PRIu64
"]", (uint64_t)idx
);
658 DataExtractor
data(buffer_sp
, m_order
, m_ptr_size
);
660 set_item
.valobj_sp
= CreateValueObjectFromData(
661 idx_name
.GetString(), data
, m_exe_ctx_ref
,
662 m_backend
.GetCompilerType().GetBasicTypeFromAST(
663 lldb::eBasicTypeObjCID
));
666 return set_item
.valobj_sp
;
669 template <typename D32
, typename D64
>
670 lldb_private::formatters::GenericNSSetMSyntheticFrontEnd
<
671 D32
, D64
>::GenericNSSetMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp
)
672 : SyntheticChildrenFrontEnd(*valobj_sp
), m_exe_ctx_ref(),
673 m_data_32(nullptr), m_data_64(nullptr) {
678 template <typename D32
, typename D64
>
679 lldb_private::formatters::GenericNSSetMSyntheticFrontEnd
<D32
, D64
>::
680 GenericNSSetMSyntheticFrontEnd::~GenericNSSetMSyntheticFrontEnd() {
687 template <typename D32
, typename D64
>
689 lldb_private::formatters::
690 GenericNSSetMSyntheticFrontEnd
<D32
, D64
>::GetIndexOfChildWithName(
692 const char *item_name
= name
.GetCString();
693 uint32_t idx
= ExtractIndexFromString(item_name
);
694 if (idx
< UINT32_MAX
&& idx
>= CalculateNumChildrenIgnoringErrors())
699 template <typename D32
, typename D64
>
700 llvm::Expected
<uint32_t>
701 lldb_private::formatters::GenericNSSetMSyntheticFrontEnd
<
702 D32
, D64
>::CalculateNumChildren() {
703 if (!m_data_32
&& !m_data_64
)
705 return (m_data_32
? (uint32_t)m_data_32
->_used
: (uint32_t)m_data_64
->_used
);
708 template <typename D32
, typename D64
>
709 lldb::ChildCacheState
710 lldb_private::formatters::GenericNSSetMSyntheticFrontEnd
<D32
, D64
>::Update() {
712 ValueObjectSP valobj_sp
= m_backend
.GetSP();
719 return lldb::ChildCacheState::eRefetch
;
721 return lldb::ChildCacheState::eRefetch
;
722 m_exe_ctx_ref
= valobj_sp
->GetExecutionContextRef();
723 lldb::ProcessSP
process_sp(valobj_sp
->GetProcessSP());
725 return lldb::ChildCacheState::eRefetch
;
726 m_ptr_size
= process_sp
->GetAddressByteSize();
727 uint64_t data_location
= valobj_sp
->GetValueAsUnsigned(0) + m_ptr_size
;
729 if (m_ptr_size
== 4) {
730 m_data_32
= new D32();
731 process_sp
->ReadMemory(data_location
, m_data_32
, sizeof(D32
),
734 m_data_64
= new D64();
735 process_sp
->ReadMemory(data_location
, m_data_64
, sizeof(D64
),
738 return error
.Success() ? lldb::ChildCacheState::eReuse
739 : lldb::ChildCacheState::eRefetch
;
742 template <typename D32
, typename D64
>
744 lldb_private::formatters::
745 GenericNSSetMSyntheticFrontEnd
<D32
, D64
>::MightHaveChildren() {
749 template <typename D32
, typename D64
>
751 lldb_private::formatters::
752 GenericNSSetMSyntheticFrontEnd
<D32
, D64
>::GetChildAtIndex(uint32_t idx
) {
753 lldb::addr_t m_objs_addr
=
754 (m_data_32
? m_data_32
->_objs_addr
: m_data_64
->_objs_addr
);
756 uint32_t num_children
= CalculateNumChildrenIgnoringErrors();
758 if (idx
>= num_children
)
759 return lldb::ValueObjectSP();
761 ProcessSP process_sp
= m_exe_ctx_ref
.GetProcessSP();
763 return lldb::ValueObjectSP();
765 if (m_children
.empty()) {
767 lldb::addr_t obj_at_idx
= 0;
770 uint32_t test_idx
= 0;
772 while (tries
< num_children
) {
773 obj_at_idx
= m_objs_addr
+ (test_idx
* m_ptr_size
);
775 return lldb::ValueObjectSP();
777 obj_at_idx
= process_sp
->ReadPointerFromMemory(obj_at_idx
, error
);
779 return lldb::ValueObjectSP();
787 SetItemDescriptor descriptor
= {obj_at_idx
, lldb::ValueObjectSP()};
789 m_children
.push_back(descriptor
);
793 if (idx
>= m_children
.size()) // should never happen
794 return lldb::ValueObjectSP();
796 SetItemDescriptor
&set_item
= m_children
[idx
];
797 if (!set_item
.valobj_sp
) {
798 auto ptr_size
= process_sp
->GetAddressByteSize();
799 DataBufferHeap
buffer(ptr_size
, 0);
801 case 0: // architecture has no clue?? - fail
802 return lldb::ValueObjectSP();
804 *((uint32_t *)buffer
.GetBytes()) = (uint32_t)set_item
.item_ptr
;
807 *((uint64_t *)buffer
.GetBytes()) = (uint64_t)set_item
.item_ptr
;
810 assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
812 StreamString idx_name
;
813 idx_name
.Printf("[%" PRIu64
"]", (uint64_t)idx
);
815 DataExtractor
data(buffer
.GetBytes(), buffer
.GetByteSize(),
816 process_sp
->GetByteOrder(),
817 process_sp
->GetAddressByteSize());
819 set_item
.valobj_sp
= CreateValueObjectFromData(
820 idx_name
.GetString(), data
, m_exe_ctx_ref
,
821 m_backend
.GetCompilerType().GetBasicTypeFromAST(
822 lldb::eBasicTypeObjCID
));
824 return set_item
.valobj_sp
;
827 template bool lldb_private::formatters::NSSetSummaryProvider
<true>(
828 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
);
830 template bool lldb_private::formatters::NSSetSummaryProvider
<false>(
831 ValueObject
&valobj
, Stream
&stream
, const TypeSummaryOptions
&options
);