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 !strcmp(class_name, "__NSOrderedSetI")) { 274 Status error; 275 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 276 ptr_size, 0, error); 277 if (error.Fail()) 278 return false; 279 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 280 } else if (!strcmp(class_name, "__NSSetM")) { 281 AppleObjCRuntime *apple_runtime = 282 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); 283 Status error; 284 if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { 285 value = Foundation1437::__NSSetMSize(*process_sp, valobj_addr, error); 286 } else { 287 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 288 ptr_size, 0, error); 289 value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); 290 } 291 if (error.Fail()) 292 return false; 293 } else { 294 auto &map(NSSet_Additionals::GetAdditionalSummaries()); 295 auto iter = map.find(class_name_cs), end = map.end(); 296 if (iter != end) 297 return iter->second(valobj, stream, options); 298 else 299 return false; 300 } 301 302 std::string prefix, suffix; 303 if (Language *language = Language::FindPlugin(options.GetLanguage())) { 304 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, 305 suffix)) { 306 prefix.clear(); 307 suffix.clear(); 308 } 309 } 310 311 stream.Printf("%s%" PRIu64 " %s%s%s", prefix.c_str(), value, "element", 312 value == 1 ? "" : "s", suffix.c_str()); 313 return true; 314 } 315 316 SyntheticChildrenFrontEnd * 317 lldb_private::formatters::NSSetSyntheticFrontEndCreator( 318 CXXSyntheticChildren *synth, lldb::ValueObjectSP valobj_sp) { 319 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 320 if (!process_sp) 321 return nullptr; 322 ObjCLanguageRuntime *runtime = 323 (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime( 324 lldb::eLanguageTypeObjC); 325 if (!runtime) 326 return nullptr; 327 328 CompilerType valobj_type(valobj_sp->GetCompilerType()); 329 Flags flags(valobj_type.GetTypeInfo()); 330 331 if (flags.IsClear(eTypeIsPointer)) { 332 Status error; 333 valobj_sp = valobj_sp->AddressOf(error); 334 if (error.Fail() || !valobj_sp) 335 return nullptr; 336 } 337 338 ObjCLanguageRuntime::ClassDescriptorSP descriptor( 339 runtime->GetClassDescriptor(*valobj_sp)); 340 341 if (!descriptor || !descriptor->IsValid()) 342 return nullptr; 343 344 ConstString class_name_cs = descriptor->GetClassName(); 345 const char *class_name = class_name_cs.GetCString(); 346 347 if (!class_name || !*class_name) 348 return nullptr; 349 350 if (!strcmp(class_name, "__NSSetI") || 351 !strcmp(class_name, "__NSOrderedSetI")) { 352 return (new NSSetISyntheticFrontEnd(valobj_sp)); 353 } else if (!strcmp(class_name, "__NSSetM")) { 354 AppleObjCRuntime *apple_runtime = 355 llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); 356 if (apple_runtime) { 357 if (apple_runtime->GetFoundationVersion() >= 1437) 358 return (new Foundation1437::NSSetMSyntheticFrontEnd(valobj_sp)); 359 else if (apple_runtime->GetFoundationVersion() >= 1428) 360 return (new Foundation1428::NSSetMSyntheticFrontEnd(valobj_sp)); 361 else 362 return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp)); 363 } else { 364 return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp)); 365 } 366 } else { 367 auto &map(NSSet_Additionals::GetAdditionalSynthetics()); 368 auto iter = map.find(class_name_cs), end = map.end(); 369 if (iter != end) 370 return iter->second(synth, valobj_sp); 371 return nullptr; 372 } 373 } 374 375 lldb_private::formatters::NSSetISyntheticFrontEnd::NSSetISyntheticFrontEnd( 376 lldb::ValueObjectSP valobj_sp) 377 : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), 378 m_data_32(nullptr), m_data_64(nullptr) { 379 if (valobj_sp) 380 Update(); 381 } 382 383 lldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd() { 384 delete m_data_32; 385 m_data_32 = nullptr; 386 delete m_data_64; 387 m_data_64 = nullptr; 388 } 389 390 size_t 391 lldb_private::formatters::NSSetISyntheticFrontEnd::GetIndexOfChildWithName( 392 const ConstString &name) { 393 const char *item_name = name.GetCString(); 394 uint32_t idx = ExtractIndexFromString(item_name); 395 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 396 return UINT32_MAX; 397 return idx; 398 } 399 400 size_t 401 lldb_private::formatters::NSSetISyntheticFrontEnd::CalculateNumChildren() { 402 if (!m_data_32 && !m_data_64) 403 return 0; 404 return (m_data_32 ? m_data_32->_used : m_data_64->_used); 405 } 406 407 bool lldb_private::formatters::NSSetISyntheticFrontEnd::Update() { 408 m_children.clear(); 409 delete m_data_32; 410 m_data_32 = nullptr; 411 delete m_data_64; 412 m_data_64 = nullptr; 413 m_ptr_size = 0; 414 ValueObjectSP valobj_sp = m_backend.GetSP(); 415 if (!valobj_sp) 416 return false; 417 if (!valobj_sp) 418 return false; 419 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 420 Status error; 421 if (valobj_sp->IsPointerType()) { 422 valobj_sp = valobj_sp->Dereference(error); 423 if (error.Fail() || !valobj_sp) 424 return false; 425 } 426 error.Clear(); 427 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 428 if (!process_sp) 429 return false; 430 m_ptr_size = process_sp->GetAddressByteSize(); 431 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size; 432 if (m_ptr_size == 4) { 433 m_data_32 = new DataDescriptor_32(); 434 process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), 435 error); 436 } else { 437 m_data_64 = new DataDescriptor_64(); 438 process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), 439 error); 440 } 441 if (error.Fail()) 442 return false; 443 m_data_ptr = data_location + m_ptr_size; 444 return false; 445 } 446 447 bool lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren() { 448 return true; 449 } 450 451 lldb::ValueObjectSP 452 lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex(size_t idx) { 453 uint32_t num_children = CalculateNumChildren(); 454 455 if (idx >= num_children) 456 return lldb::ValueObjectSP(); 457 458 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 459 if (!process_sp) 460 return lldb::ValueObjectSP(); 461 462 if (m_children.empty()) { 463 // do the scan phase 464 lldb::addr_t obj_at_idx = 0; 465 466 uint32_t tries = 0; 467 uint32_t test_idx = 0; 468 469 while (tries < num_children) { 470 obj_at_idx = m_data_ptr + (test_idx * m_ptr_size); 471 if (!process_sp) 472 return lldb::ValueObjectSP(); 473 Status error; 474 obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error); 475 if (error.Fail()) 476 return lldb::ValueObjectSP(); 477 478 test_idx++; 479 480 if (!obj_at_idx) 481 continue; 482 tries++; 483 484 SetItemDescriptor descriptor = {obj_at_idx, lldb::ValueObjectSP()}; 485 486 m_children.push_back(descriptor); 487 } 488 } 489 490 if (idx >= m_children.size()) // should never happen 491 return lldb::ValueObjectSP(); 492 493 SetItemDescriptor &set_item = m_children[idx]; 494 if (!set_item.valobj_sp) { 495 auto ptr_size = process_sp->GetAddressByteSize(); 496 DataBufferHeap buffer(ptr_size, 0); 497 switch (ptr_size) { 498 case 0: // architecture has no clue?? - fail 499 return lldb::ValueObjectSP(); 500 case 4: 501 *((uint32_t *)buffer.GetBytes()) = (uint32_t)set_item.item_ptr; 502 break; 503 case 8: 504 *((uint64_t *)buffer.GetBytes()) = (uint64_t)set_item.item_ptr; 505 break; 506 default: 507 assert(false && "pointer size is not 4 nor 8 - get out of here ASAP"); 508 } 509 StreamString idx_name; 510 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 511 512 DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), 513 process_sp->GetByteOrder(), 514 process_sp->GetAddressByteSize()); 515 516 set_item.valobj_sp = CreateValueObjectFromData( 517 idx_name.GetString(), data, m_exe_ctx_ref, 518 m_backend.GetCompilerType().GetBasicTypeFromAST( 519 lldb::eBasicTypeObjCID)); 520 } 521 return set_item.valobj_sp; 522 } 523 524 template <typename D32, typename D64> 525 lldb_private::formatters:: 526 GenericNSSetMSyntheticFrontEnd<D32, D64>::GenericNSSetMSyntheticFrontEnd( 527 lldb::ValueObjectSP valobj_sp) 528 : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), 529 m_data_32(nullptr), m_data_64(nullptr) { 530 if (valobj_sp) 531 Update(); 532 } 533 534 template <typename D32, typename D64> 535 lldb_private::formatters:: 536 GenericNSSetMSyntheticFrontEnd<D32, D64>::~GenericNSSetMSyntheticFrontEnd() { 537 delete m_data_32; 538 m_data_32 = nullptr; 539 delete m_data_64; 540 m_data_64 = nullptr; 541 } 542 543 template <typename D32, typename D64> 544 size_t 545 lldb_private::formatters:: 546 GenericNSSetMSyntheticFrontEnd<D32, D64>::GetIndexOfChildWithName( 547 const ConstString &name) { 548 const char *item_name = name.GetCString(); 549 uint32_t idx = ExtractIndexFromString(item_name); 550 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 551 return UINT32_MAX; 552 return idx; 553 } 554 555 template <typename D32, typename D64> 556 size_t 557 lldb_private::formatters:: 558 GenericNSSetMSyntheticFrontEnd<D32, D64>::CalculateNumChildren() { 559 if (!m_data_32 && !m_data_64) 560 return 0; 561 return (m_data_32 ? m_data_32->_used : m_data_64->_used); 562 } 563 564 template <typename D32, typename D64> 565 bool 566 lldb_private::formatters:: 567 GenericNSSetMSyntheticFrontEnd<D32, D64>::Update() { 568 m_children.clear(); 569 ValueObjectSP valobj_sp = m_backend.GetSP(); 570 m_ptr_size = 0; 571 delete m_data_32; 572 m_data_32 = nullptr; 573 delete m_data_64; 574 m_data_64 = nullptr; 575 if (!valobj_sp) 576 return false; 577 if (!valobj_sp) 578 return false; 579 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 580 Status error; 581 if (valobj_sp->IsPointerType()) { 582 valobj_sp = valobj_sp->Dereference(error); 583 if (error.Fail() || !valobj_sp) 584 return false; 585 } 586 error.Clear(); 587 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 588 if (!process_sp) 589 return false; 590 m_ptr_size = process_sp->GetAddressByteSize(); 591 uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size; 592 if (m_ptr_size == 4) { 593 m_data_32 = new D32(); 594 process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), 595 error); 596 } else { 597 m_data_64 = new D64(); 598 process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), 599 error); 600 } 601 if (error.Fail()) 602 return false; 603 return false; 604 } 605 606 template <typename D32, typename D64> 607 bool 608 lldb_private::formatters:: 609 GenericNSSetMSyntheticFrontEnd<D32, D64>::MightHaveChildren() { 610 return true; 611 } 612 613 template <typename D32, typename D64> 614 lldb::ValueObjectSP 615 lldb_private::formatters:: 616 GenericNSSetMSyntheticFrontEnd<D32, D64>::GetChildAtIndex(size_t idx) { 617 lldb::addr_t m_objs_addr = 618 (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr); 619 620 uint32_t num_children = CalculateNumChildren(); 621 622 if (idx >= num_children) 623 return lldb::ValueObjectSP(); 624 625 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 626 if (!process_sp) 627 return lldb::ValueObjectSP(); 628 629 if (m_children.empty()) { 630 // do the scan phase 631 lldb::addr_t obj_at_idx = 0; 632 633 uint32_t tries = 0; 634 uint32_t test_idx = 0; 635 636 while (tries < num_children) { 637 obj_at_idx = m_objs_addr + (test_idx * m_ptr_size); 638 if (!process_sp) 639 return lldb::ValueObjectSP(); 640 Status error; 641 obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error); 642 if (error.Fail()) 643 return lldb::ValueObjectSP(); 644 645 test_idx++; 646 647 if (!obj_at_idx) 648 continue; 649 tries++; 650 651 SetItemDescriptor descriptor = {obj_at_idx, lldb::ValueObjectSP()}; 652 653 m_children.push_back(descriptor); 654 } 655 } 656 657 if (idx >= m_children.size()) // should never happen 658 return lldb::ValueObjectSP(); 659 660 SetItemDescriptor &set_item = m_children[idx]; 661 if (!set_item.valobj_sp) { 662 auto ptr_size = process_sp->GetAddressByteSize(); 663 DataBufferHeap buffer(ptr_size, 0); 664 switch (ptr_size) { 665 case 0: // architecture has no clue?? - fail 666 return lldb::ValueObjectSP(); 667 case 4: 668 *((uint32_t *)buffer.GetBytes()) = (uint32_t)set_item.item_ptr; 669 break; 670 case 8: 671 *((uint64_t *)buffer.GetBytes()) = (uint64_t)set_item.item_ptr; 672 break; 673 default: 674 assert(false && "pointer size is not 4 nor 8 - get out of here ASAP"); 675 } 676 StreamString idx_name; 677 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 678 679 DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), 680 process_sp->GetByteOrder(), 681 process_sp->GetAddressByteSize()); 682 683 set_item.valobj_sp = CreateValueObjectFromData( 684 idx_name.GetString(), data, m_exe_ctx_ref, 685 m_backend.GetCompilerType().GetBasicTypeFromAST( 686 lldb::eBasicTypeObjCID)); 687 } 688 return set_item.valobj_sp; 689 } 690 691 template bool lldb_private::formatters::NSSetSummaryProvider<true>( 692 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); 693 694 template bool lldb_private::formatters::NSSetSummaryProvider<false>( 695 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); 696