1 //===-- NSSet.cpp -----------------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "NSSet.h"
11
12 #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
13 #include "lldb/Core/ValueObject.h"
14 #include "lldb/Core/ValueObjectConstResult.h"
15 #include "lldb/DataFormatters/FormattersHelpers.h"
16 #include "lldb/Symbol/ClangASTContext.h"
17 #include "lldb/Target/Language.h"
18 #include "lldb/Target/ObjCLanguageRuntime.h"
19 #include "lldb/Target/Target.h"
20 #include "lldb/Utility/DataBufferHeap.h"
21 #include "lldb/Utility/Endian.h"
22 #include "lldb/Utility/Status.h"
23 #include "lldb/Utility/Stream.h"
24
25 using namespace lldb;
26 using namespace lldb_private;
27 using namespace lldb_private::formatters;
28
29 std::map<ConstString, CXXFunctionSummaryFormat::Callback> &
GetAdditionalSummaries()30 NSSet_Additionals::GetAdditionalSummaries() {
31 static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
32 return g_map;
33 }
34
35 std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> &
GetAdditionalSynthetics()36 NSSet_Additionals::GetAdditionalSynthetics() {
37 static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>
38 g_map;
39 return g_map;
40 }
41
42 namespace lldb_private {
43 namespace formatters {
44 class NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd {
45 public:
46 NSSetISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
47
48 ~NSSetISyntheticFrontEnd() override;
49
50 size_t CalculateNumChildren() override;
51
52 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
53
54 bool Update() override;
55
56 bool MightHaveChildren() override;
57
58 size_t GetIndexOfChildWithName(const ConstString &name) override;
59
60 private:
61 struct DataDescriptor_32 {
62 uint32_t _used : 26;
63 uint32_t _szidx : 6;
64 };
65
66 struct DataDescriptor_64 {
67 uint64_t _used : 58;
68 uint32_t _szidx : 6;
69 };
70
71 struct SetItemDescriptor {
72 lldb::addr_t item_ptr;
73 lldb::ValueObjectSP valobj_sp;
74 };
75
76 ExecutionContextRef m_exe_ctx_ref;
77 uint8_t m_ptr_size;
78 DataDescriptor_32 *m_data_32;
79 DataDescriptor_64 *m_data_64;
80 lldb::addr_t m_data_ptr;
81 std::vector<SetItemDescriptor> m_children;
82 };
83
84 template <typename D32, typename D64>
85 class GenericNSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
86 public:
87 GenericNSSetMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
88
89 ~GenericNSSetMSyntheticFrontEnd() override;
90
91 size_t CalculateNumChildren() override;
92
93 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
94
95 bool Update() override;
96
97 bool MightHaveChildren() override;
98
99 size_t GetIndexOfChildWithName(const ConstString &name) override;
100
101 private:
102
103 struct SetItemDescriptor {
104 lldb::addr_t item_ptr;
105 lldb::ValueObjectSP valobj_sp;
106 };
107
108 ExecutionContextRef m_exe_ctx_ref;
109 uint8_t m_ptr_size;
110 D32 *m_data_32;
111 D64 *m_data_64;
112 std::vector<SetItemDescriptor> m_children;
113 };
114
115 namespace Foundation1300 {
116 struct DataDescriptor_32 {
117 uint32_t _used : 26;
118 uint32_t _size;
119 uint32_t _mutations;
120 uint32_t _objs_addr;
121 };
122
123 struct DataDescriptor_64 {
124 uint64_t _used : 58;
125 uint64_t _size;
126 uint64_t _mutations;
127 uint64_t _objs_addr;
128 };
129
130 using NSSetMSyntheticFrontEnd =
131 GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
132 }
133
134 namespace Foundation1428 {
135 struct DataDescriptor_32 {
136 uint32_t _used : 26;
137 uint32_t _size;
138 uint32_t _objs_addr;
139 uint32_t _mutations;
140 };
141
142 struct DataDescriptor_64 {
143 uint64_t _used : 58;
144 uint64_t _size;
145 uint64_t _objs_addr;
146 uint64_t _mutations;
147 };
148
149 using NSSetMSyntheticFrontEnd =
150 GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
151 }
152
153 namespace Foundation1437 {
154 struct DataDescriptor_32 {
155 uint32_t _cow;
156 // __table storage
157 uint32_t _objs_addr;
158 union {
159 uint32_t _mutations;
160 struct {
161 uint32_t _muts;
162 uint32_t _used : 26;
163 uint32_t _szidx : 6;
164 };
165 };
166 };
167
168 struct DataDescriptor_64 {
169 uint64_t _cow;
170 // __Table storage
171 uint64_t _objs_addr;
172 union {
173 uint64_t _mutations;
174 struct {
175 uint32_t _muts;
176 uint32_t _used : 26;
177 uint32_t _szidx : 6;
178 };
179 };
180 };
181
182 using NSSetMSyntheticFrontEnd =
183 GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
184
185 template <typename DD>
186 uint64_t
__NSSetMSize_Impl(lldb_private::Process & process,lldb::addr_t valobj_addr,Status & error)187 __NSSetMSize_Impl(lldb_private::Process &process, lldb::addr_t valobj_addr,
188 Status &error) {
189 const lldb::addr_t start_of_descriptor =
190 valobj_addr + process.GetAddressByteSize();
191 DD descriptor = DD();
192 process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor),
193 error);
194 if (error.Fail()) {
195 return 0;
196 }
197 return descriptor._used;
198 }
199
200 uint64_t
__NSSetMSize(lldb_private::Process & process,lldb::addr_t valobj_addr,Status & error)201 __NSSetMSize(lldb_private::Process &process, lldb::addr_t valobj_addr,
202 Status &error) {
203 if (process.GetAddressByteSize() == 4) {
204 return __NSSetMSize_Impl<DataDescriptor_32>(process, valobj_addr, error);
205 } else {
206 return __NSSetMSize_Impl<DataDescriptor_64>(process, valobj_addr, error);
207 }
208 }
209 }
210
211 class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
212 public:
213 NSSetCodeRunningSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
214
215 ~NSSetCodeRunningSyntheticFrontEnd() override;
216
217 size_t CalculateNumChildren() override;
218
219 lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
220
221 bool Update() override;
222
223 bool MightHaveChildren() override;
224
225 size_t GetIndexOfChildWithName(const ConstString &name) override;
226 };
227 } // namespace formatters
228 } // namespace lldb_private
229
230 template <bool cf_style>
NSSetSummaryProvider(ValueObject & valobj,Stream & stream,const TypeSummaryOptions & options)231 bool lldb_private::formatters::NSSetSummaryProvider(
232 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
233 static ConstString g_TypeHint("NSSet");
234
235 ProcessSP process_sp = valobj.GetProcessSP();
236 if (!process_sp)
237 return false;
238
239 ObjCLanguageRuntime *runtime =
240 (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime(
241 lldb::eLanguageTypeObjC);
242
243 if (!runtime)
244 return false;
245
246 ObjCLanguageRuntime::ClassDescriptorSP descriptor(
247 runtime->GetClassDescriptor(valobj));
248
249 if (!descriptor || !descriptor->IsValid())
250 return false;
251
252 uint32_t ptr_size = process_sp->GetAddressByteSize();
253 bool is_64bit = (ptr_size == 8);
254
255 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
256
257 if (!valobj_addr)
258 return false;
259
260 uint64_t value = 0;
261
262 ConstString class_name_cs = descriptor->GetClassName();
263 const char *class_name = class_name_cs.GetCString();
264
265 if (!class_name || !*class_name)
266 return false;
267
268 if (!strcmp(class_name, "__NSSetI") ||
269 !strcmp(class_name, "__NSOrderedSetI")) {
270 Status error;
271 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
272 ptr_size, 0, error);
273 if (error.Fail())
274 return false;
275 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
276 } else if (!strcmp(class_name, "__NSSetM")) {
277 AppleObjCRuntime *apple_runtime =
278 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
279 Status error;
280 if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) {
281 value = Foundation1437::__NSSetMSize(*process_sp, valobj_addr, error);
282 } else {
283 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
284 ptr_size, 0, error);
285 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
286 }
287 if (error.Fail())
288 return false;
289 } else {
290 auto &map(NSSet_Additionals::GetAdditionalSummaries());
291 auto iter = map.find(class_name_cs), end = map.end();
292 if (iter != end)
293 return iter->second(valobj, stream, options);
294 else
295 return false;
296 }
297
298 std::string prefix, suffix;
299 if (Language *language = Language::FindPlugin(options.GetLanguage())) {
300 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix,
301 suffix)) {
302 prefix.clear();
303 suffix.clear();
304 }
305 }
306
307 stream.Printf("%s%" PRIu64 " %s%s%s", prefix.c_str(), value, "element",
308 value == 1 ? "" : "s", suffix.c_str());
309 return true;
310 }
311
312 SyntheticChildrenFrontEnd *
NSSetSyntheticFrontEndCreator(CXXSyntheticChildren * synth,lldb::ValueObjectSP valobj_sp)313 lldb_private::formatters::NSSetSyntheticFrontEndCreator(
314 CXXSyntheticChildren *synth, lldb::ValueObjectSP valobj_sp) {
315 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
316 if (!process_sp)
317 return nullptr;
318 ObjCLanguageRuntime *runtime =
319 (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime(
320 lldb::eLanguageTypeObjC);
321 if (!runtime)
322 return nullptr;
323
324 CompilerType valobj_type(valobj_sp->GetCompilerType());
325 Flags flags(valobj_type.GetTypeInfo());
326
327 if (flags.IsClear(eTypeIsPointer)) {
328 Status error;
329 valobj_sp = valobj_sp->AddressOf(error);
330 if (error.Fail() || !valobj_sp)
331 return nullptr;
332 }
333
334 ObjCLanguageRuntime::ClassDescriptorSP descriptor(
335 runtime->GetClassDescriptor(*valobj_sp));
336
337 if (!descriptor || !descriptor->IsValid())
338 return nullptr;
339
340 ConstString class_name_cs = descriptor->GetClassName();
341 const char *class_name = class_name_cs.GetCString();
342
343 if (!class_name || !*class_name)
344 return nullptr;
345
346 if (!strcmp(class_name, "__NSSetI") ||
347 !strcmp(class_name, "__NSOrderedSetI")) {
348 return (new NSSetISyntheticFrontEnd(valobj_sp));
349 } else if (!strcmp(class_name, "__NSSetM")) {
350 AppleObjCRuntime *apple_runtime =
351 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
352 if (apple_runtime) {
353 if (apple_runtime->GetFoundationVersion() >= 1437)
354 return (new Foundation1437::NSSetMSyntheticFrontEnd(valobj_sp));
355 else if (apple_runtime->GetFoundationVersion() >= 1428)
356 return (new Foundation1428::NSSetMSyntheticFrontEnd(valobj_sp));
357 else
358 return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp));
359 } else {
360 return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp));
361 }
362 } else {
363 auto &map(NSSet_Additionals::GetAdditionalSynthetics());
364 auto iter = map.find(class_name_cs), end = map.end();
365 if (iter != end)
366 return iter->second(synth, valobj_sp);
367 return nullptr;
368 }
369 }
370
NSSetISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)371 lldb_private::formatters::NSSetISyntheticFrontEnd::NSSetISyntheticFrontEnd(
372 lldb::ValueObjectSP valobj_sp)
373 : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
374 m_data_32(nullptr), m_data_64(nullptr) {
375 if (valobj_sp)
376 Update();
377 }
378
~NSSetISyntheticFrontEnd()379 lldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd() {
380 delete m_data_32;
381 m_data_32 = nullptr;
382 delete m_data_64;
383 m_data_64 = nullptr;
384 }
385
386 size_t
GetIndexOfChildWithName(const ConstString & name)387 lldb_private::formatters::NSSetISyntheticFrontEnd::GetIndexOfChildWithName(
388 const ConstString &name) {
389 const char *item_name = name.GetCString();
390 uint32_t idx = ExtractIndexFromString(item_name);
391 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
392 return UINT32_MAX;
393 return idx;
394 }
395
396 size_t
CalculateNumChildren()397 lldb_private::formatters::NSSetISyntheticFrontEnd::CalculateNumChildren() {
398 if (!m_data_32 && !m_data_64)
399 return 0;
400 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
401 }
402
Update()403 bool lldb_private::formatters::NSSetISyntheticFrontEnd::Update() {
404 m_children.clear();
405 delete m_data_32;
406 m_data_32 = nullptr;
407 delete m_data_64;
408 m_data_64 = nullptr;
409 m_ptr_size = 0;
410 ValueObjectSP valobj_sp = m_backend.GetSP();
411 if (!valobj_sp)
412 return false;
413 if (!valobj_sp)
414 return false;
415 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
416 Status error;
417 if (valobj_sp->IsPointerType()) {
418 valobj_sp = valobj_sp->Dereference(error);
419 if (error.Fail() || !valobj_sp)
420 return false;
421 }
422 error.Clear();
423 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
424 if (!process_sp)
425 return false;
426 m_ptr_size = process_sp->GetAddressByteSize();
427 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
428 if (m_ptr_size == 4) {
429 m_data_32 = new DataDescriptor_32();
430 process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
431 error);
432 } else {
433 m_data_64 = new DataDescriptor_64();
434 process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
435 error);
436 }
437 if (error.Fail())
438 return false;
439 m_data_ptr = data_location + m_ptr_size;
440 return false;
441 }
442
MightHaveChildren()443 bool lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren() {
444 return true;
445 }
446
447 lldb::ValueObjectSP
GetChildAtIndex(size_t idx)448 lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex(size_t idx) {
449 uint32_t num_children = CalculateNumChildren();
450
451 if (idx >= num_children)
452 return lldb::ValueObjectSP();
453
454 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
455 if (!process_sp)
456 return lldb::ValueObjectSP();
457
458 if (m_children.empty()) {
459 // do the scan phase
460 lldb::addr_t obj_at_idx = 0;
461
462 uint32_t tries = 0;
463 uint32_t test_idx = 0;
464
465 while (tries < num_children) {
466 obj_at_idx = m_data_ptr + (test_idx * m_ptr_size);
467 if (!process_sp)
468 return lldb::ValueObjectSP();
469 Status error;
470 obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error);
471 if (error.Fail())
472 return lldb::ValueObjectSP();
473
474 test_idx++;
475
476 if (!obj_at_idx)
477 continue;
478 tries++;
479
480 SetItemDescriptor descriptor = {obj_at_idx, lldb::ValueObjectSP()};
481
482 m_children.push_back(descriptor);
483 }
484 }
485
486 if (idx >= m_children.size()) // should never happen
487 return lldb::ValueObjectSP();
488
489 SetItemDescriptor &set_item = m_children[idx];
490 if (!set_item.valobj_sp) {
491 auto ptr_size = process_sp->GetAddressByteSize();
492 DataBufferHeap buffer(ptr_size, 0);
493 switch (ptr_size) {
494 case 0: // architecture has no clue?? - fail
495 return lldb::ValueObjectSP();
496 case 4:
497 *((uint32_t *)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
498 break;
499 case 8:
500 *((uint64_t *)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
501 break;
502 default:
503 assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
504 }
505 StreamString idx_name;
506 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
507
508 DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(),
509 process_sp->GetByteOrder(),
510 process_sp->GetAddressByteSize());
511
512 set_item.valobj_sp = CreateValueObjectFromData(
513 idx_name.GetString(), data, m_exe_ctx_ref,
514 m_backend.GetCompilerType().GetBasicTypeFromAST(
515 lldb::eBasicTypeObjCID));
516 }
517 return set_item.valobj_sp;
518 }
519
520 template <typename D32, typename D64>
521 lldb_private::formatters::
GenericNSSetMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)522 GenericNSSetMSyntheticFrontEnd<D32, D64>::GenericNSSetMSyntheticFrontEnd(
523 lldb::ValueObjectSP valobj_sp)
524 : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
525 m_data_32(nullptr), m_data_64(nullptr) {
526 if (valobj_sp)
527 Update();
528 }
529
530 template <typename D32, typename D64>
531 lldb_private::formatters::
~GenericNSSetMSyntheticFrontEnd()532 GenericNSSetMSyntheticFrontEnd<D32, D64>::~GenericNSSetMSyntheticFrontEnd() {
533 delete m_data_32;
534 m_data_32 = nullptr;
535 delete m_data_64;
536 m_data_64 = nullptr;
537 }
538
539 template <typename D32, typename D64>
540 size_t
541 lldb_private::formatters::
GetIndexOfChildWithName(const ConstString & name)542 GenericNSSetMSyntheticFrontEnd<D32, D64>::GetIndexOfChildWithName(
543 const ConstString &name) {
544 const char *item_name = name.GetCString();
545 uint32_t idx = ExtractIndexFromString(item_name);
546 if (idx < UINT32_MAX && idx >= CalculateNumChildren())
547 return UINT32_MAX;
548 return idx;
549 }
550
551 template <typename D32, typename D64>
552 size_t
553 lldb_private::formatters::
CalculateNumChildren()554 GenericNSSetMSyntheticFrontEnd<D32, D64>::CalculateNumChildren() {
555 if (!m_data_32 && !m_data_64)
556 return 0;
557 return (m_data_32 ? m_data_32->_used : m_data_64->_used);
558 }
559
560 template <typename D32, typename D64>
561 bool
562 lldb_private::formatters::
Update()563 GenericNSSetMSyntheticFrontEnd<D32, D64>::Update() {
564 m_children.clear();
565 ValueObjectSP valobj_sp = m_backend.GetSP();
566 m_ptr_size = 0;
567 delete m_data_32;
568 m_data_32 = nullptr;
569 delete m_data_64;
570 m_data_64 = nullptr;
571 if (!valobj_sp)
572 return false;
573 if (!valobj_sp)
574 return false;
575 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
576 Status error;
577 if (valobj_sp->IsPointerType()) {
578 valobj_sp = valobj_sp->Dereference(error);
579 if (error.Fail() || !valobj_sp)
580 return false;
581 }
582 error.Clear();
583 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
584 if (!process_sp)
585 return false;
586 m_ptr_size = process_sp->GetAddressByteSize();
587 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
588 if (m_ptr_size == 4) {
589 m_data_32 = new D32();
590 process_sp->ReadMemory(data_location, m_data_32, sizeof(D32),
591 error);
592 } else {
593 m_data_64 = new D64();
594 process_sp->ReadMemory(data_location, m_data_64, sizeof(D64),
595 error);
596 }
597 if (error.Fail())
598 return false;
599 return false;
600 }
601
602 template <typename D32, typename D64>
603 bool
604 lldb_private::formatters::
MightHaveChildren()605 GenericNSSetMSyntheticFrontEnd<D32, D64>::MightHaveChildren() {
606 return true;
607 }
608
609 template <typename D32, typename D64>
610 lldb::ValueObjectSP
611 lldb_private::formatters::
GetChildAtIndex(size_t idx)612 GenericNSSetMSyntheticFrontEnd<D32, D64>::GetChildAtIndex(size_t idx) {
613 lldb::addr_t m_objs_addr =
614 (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
615
616 uint32_t num_children = CalculateNumChildren();
617
618 if (idx >= num_children)
619 return lldb::ValueObjectSP();
620
621 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
622 if (!process_sp)
623 return lldb::ValueObjectSP();
624
625 if (m_children.empty()) {
626 // do the scan phase
627 lldb::addr_t obj_at_idx = 0;
628
629 uint32_t tries = 0;
630 uint32_t test_idx = 0;
631
632 while (tries < num_children) {
633 obj_at_idx = m_objs_addr + (test_idx * m_ptr_size);
634 if (!process_sp)
635 return lldb::ValueObjectSP();
636 Status error;
637 obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error);
638 if (error.Fail())
639 return lldb::ValueObjectSP();
640
641 test_idx++;
642
643 if (!obj_at_idx)
644 continue;
645 tries++;
646
647 SetItemDescriptor descriptor = {obj_at_idx, lldb::ValueObjectSP()};
648
649 m_children.push_back(descriptor);
650 }
651 }
652
653 if (idx >= m_children.size()) // should never happen
654 return lldb::ValueObjectSP();
655
656 SetItemDescriptor &set_item = m_children[idx];
657 if (!set_item.valobj_sp) {
658 auto ptr_size = process_sp->GetAddressByteSize();
659 DataBufferHeap buffer(ptr_size, 0);
660 switch (ptr_size) {
661 case 0: // architecture has no clue?? - fail
662 return lldb::ValueObjectSP();
663 case 4:
664 *((uint32_t *)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
665 break;
666 case 8:
667 *((uint64_t *)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
668 break;
669 default:
670 assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
671 }
672 StreamString idx_name;
673 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
674
675 DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(),
676 process_sp->GetByteOrder(),
677 process_sp->GetAddressByteSize());
678
679 set_item.valobj_sp = CreateValueObjectFromData(
680 idx_name.GetString(), data, m_exe_ctx_ref,
681 m_backend.GetCompilerType().GetBasicTypeFromAST(
682 lldb::eBasicTypeObjCID));
683 }
684 return set_item.valobj_sp;
685 }
686
687 template bool lldb_private::formatters::NSSetSummaryProvider<true>(
688 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options);
689
690 template bool lldb_private::formatters::NSSetSummaryProvider<false>(
691 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options);
692