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