1 //===-- NSArray.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 #include "clang/AST/ASTContext.h" 14 15 // Project includes 16 #include "Cocoa.h" 17 18 #include "lldb/Core/DataBufferHeap.h" 19 #include "lldb/Core/Error.h" 20 #include "lldb/Core/Stream.h" 21 #include "lldb/Core/ValueObject.h" 22 #include "lldb/Core/ValueObjectConstResult.h" 23 #include "lldb/DataFormatters/FormattersHelpers.h" 24 #include "lldb/Expression/FunctionCaller.h" 25 #include "lldb/Host/Endian.h" 26 #include "lldb/Symbol/ClangASTContext.h" 27 #include "lldb/Target/Language.h" 28 #include "lldb/Target/ObjCLanguageRuntime.h" 29 #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" 30 #include "lldb/Target/Target.h" 31 32 using namespace lldb; 33 using namespace lldb_private; 34 using namespace lldb_private::formatters; 35 36 namespace lldb_private { 37 namespace formatters { 38 class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd 39 { 40 public: 41 NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 42 43 ~NSArrayMSyntheticFrontEnd() override = default; 44 45 size_t 46 CalculateNumChildren() override; 47 48 lldb::ValueObjectSP 49 GetChildAtIndex(size_t idx) override; 50 51 bool 52 Update() override = 0; 53 54 bool 55 MightHaveChildren() override; 56 57 size_t 58 GetIndexOfChildWithName(const ConstString &name) override; 59 60 protected: 61 virtual lldb::addr_t 62 GetDataAddress () = 0; 63 64 virtual uint64_t 65 GetUsedCount () = 0; 66 67 virtual uint64_t 68 GetOffset () = 0; 69 70 virtual uint64_t 71 GetSize () = 0; 72 73 ExecutionContextRef m_exe_ctx_ref; 74 uint8_t m_ptr_size; 75 CompilerType m_id_type; 76 std::vector<lldb::ValueObjectSP> m_children; 77 }; 78 79 class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd 80 { 81 public: 82 NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp); 83 84 ~NSArrayMSyntheticFrontEnd_109() override; 85 86 bool 87 Update() override; 88 89 protected: 90 lldb::addr_t 91 GetDataAddress() override; 92 93 uint64_t 94 GetUsedCount() override; 95 96 uint64_t 97 GetOffset() override; 98 99 uint64_t 100 GetSize() override; 101 102 private: 103 struct DataDescriptor_32 104 { 105 uint32_t _used; 106 uint32_t _priv1 : 2 ; 107 uint32_t _size : 30; 108 uint32_t _priv2 : 2; 109 uint32_t _offset : 30; 110 uint32_t _priv3; 111 uint32_t _data; 112 }; 113 114 struct DataDescriptor_64 115 { 116 uint64_t _used; 117 uint64_t _priv1 : 2 ; 118 uint64_t _size : 62; 119 uint64_t _priv2 : 2; 120 uint64_t _offset : 62; 121 uint32_t _priv3; 122 uint64_t _data; 123 }; 124 125 DataDescriptor_32 *m_data_32; 126 DataDescriptor_64 *m_data_64; 127 }; 128 129 class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd 130 { 131 public: 132 NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp); 133 134 ~NSArrayMSyntheticFrontEnd_1010() override; 135 136 bool 137 Update() override; 138 139 protected: 140 lldb::addr_t 141 GetDataAddress() override; 142 143 uint64_t 144 GetUsedCount() override; 145 146 uint64_t 147 GetOffset() override; 148 149 uint64_t 150 GetSize() override; 151 152 private: 153 struct DataDescriptor_32 154 { 155 uint32_t _used; 156 uint32_t _offset; 157 uint32_t _size : 28; 158 uint64_t _priv1 : 4; 159 uint32_t _priv2; 160 uint32_t _data; 161 }; 162 163 struct DataDescriptor_64 164 { 165 uint64_t _used; 166 uint64_t _offset; 167 uint64_t _size : 60; 168 uint64_t _priv1 : 4; 169 uint32_t _priv2; 170 uint64_t _data; 171 }; 172 173 DataDescriptor_32 *m_data_32; 174 DataDescriptor_64 *m_data_64; 175 }; 176 177 class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd 178 { 179 public: 180 NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 181 182 ~NSArrayISyntheticFrontEnd() override = default; 183 184 size_t 185 CalculateNumChildren() override; 186 187 lldb::ValueObjectSP 188 GetChildAtIndex(size_t idx) override; 189 190 bool 191 Update() override; 192 193 bool 194 MightHaveChildren() override; 195 196 size_t 197 GetIndexOfChildWithName(const ConstString &name) override; 198 199 private: 200 ExecutionContextRef m_exe_ctx_ref; 201 uint8_t m_ptr_size; 202 uint64_t m_items; 203 lldb::addr_t m_data_ptr; 204 CompilerType m_id_type; 205 std::vector<lldb::ValueObjectSP> m_children; 206 }; 207 208 class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd 209 { 210 public: 211 NSArray0SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 212 213 ~NSArray0SyntheticFrontEnd() override = default; 214 215 size_t 216 CalculateNumChildren() override; 217 218 lldb::ValueObjectSP 219 GetChildAtIndex(size_t idx) override; 220 221 bool 222 Update() override; 223 224 bool 225 MightHaveChildren() override; 226 227 size_t 228 GetIndexOfChildWithName(const ConstString &name) override; 229 }; 230 231 class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd 232 { 233 public: 234 NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 235 236 ~NSArrayCodeRunningSyntheticFrontEnd() override = default; 237 238 size_t 239 CalculateNumChildren() override; 240 241 lldb::ValueObjectSP 242 GetChildAtIndex(size_t idx) override; 243 244 bool 245 Update() override; 246 247 bool 248 MightHaveChildren() override; 249 250 size_t 251 GetIndexOfChildWithName(const ConstString &name) override; 252 }; 253 } // namespace formatters 254 } // namespace lldb_private 255 256 bool 257 lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) 258 { 259 static ConstString g_TypeHint("NSArray"); 260 261 ProcessSP process_sp = valobj.GetProcessSP(); 262 if (!process_sp) 263 return false; 264 265 ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); 266 267 if (!runtime) 268 return false; 269 270 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); 271 272 if (!descriptor.get() || !descriptor->IsValid()) 273 return false; 274 275 uint32_t ptr_size = process_sp->GetAddressByteSize(); 276 277 lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 278 279 if (!valobj_addr) 280 return false; 281 282 uint64_t value = 0; 283 284 const char* class_name = descriptor->GetClassName().GetCString(); 285 286 if (!class_name || !*class_name) 287 return false; 288 289 if (!strcmp(class_name,"__NSArrayI")) 290 { 291 Error error; 292 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); 293 if (error.Fail()) 294 return false; 295 } 296 else if (!strcmp(class_name,"__NSArrayM")) 297 { 298 Error error; 299 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); 300 if (error.Fail()) 301 return false; 302 } 303 else if (!strcmp(class_name,"__NSArray0")) 304 { 305 value = 0; 306 } 307 else if (!strcmp(class_name,"__NSCFArray")) 308 { 309 Error error; 310 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size, ptr_size, 0, error); 311 if (error.Fail()) 312 return false; 313 } 314 else 315 { 316 if (!ExtractValueFromObjCExpression(valobj, "int", "count", value)) 317 return false; 318 } 319 320 std::string prefix,suffix; 321 if (Language* language = Language::FindPlugin(options.GetLanguage())) 322 { 323 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) 324 { 325 prefix.clear(); 326 suffix.clear(); 327 } 328 } 329 330 stream.Printf("%s%" PRIu64 " %s%s%s", 331 prefix.c_str(), 332 value, 333 "element", 334 value == 1 ? "" : "s", 335 suffix.c_str()); 336 return true; 337 } 338 339 lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 340 SyntheticChildrenFrontEnd(*valobj_sp), 341 m_exe_ctx_ref(), 342 m_ptr_size(8), 343 m_id_type(), 344 m_children() 345 { 346 if (valobj_sp) 347 { 348 clang::ASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext()->getASTContext(); 349 if (ast) 350 m_id_type = CompilerType(ast, ast->ObjCBuiltinIdTy); 351 if (valobj_sp->GetProcessSP()) 352 m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize(); 353 } 354 } 355 356 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp) : 357 NSArrayMSyntheticFrontEnd(valobj_sp), 358 m_data_32(NULL), 359 m_data_64(NULL) 360 { 361 } 362 363 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp) : 364 NSArrayMSyntheticFrontEnd(valobj_sp), 365 m_data_32(NULL), 366 m_data_64(NULL) 367 { 368 } 369 370 size_t 371 lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren () 372 { 373 return GetUsedCount(); 374 } 375 376 lldb::ValueObjectSP 377 lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx) 378 { 379 if (idx >= CalculateNumChildren()) 380 return lldb::ValueObjectSP(); 381 lldb::addr_t object_at_idx = GetDataAddress(); 382 size_t pyhs_idx = idx; 383 pyhs_idx += GetOffset(); 384 if (GetSize() <= pyhs_idx) 385 pyhs_idx -= GetSize(); 386 object_at_idx += (pyhs_idx * m_ptr_size); 387 StreamString idx_name; 388 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 389 lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(), 390 object_at_idx, 391 m_exe_ctx_ref, 392 m_id_type); 393 m_children.push_back(retval_sp); 394 return retval_sp; 395 } 396 397 bool 398 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::Update() 399 { 400 m_children.clear(); 401 ValueObjectSP valobj_sp = m_backend.GetSP(); 402 m_ptr_size = 0; 403 delete m_data_32; 404 m_data_32 = NULL; 405 delete m_data_64; 406 m_data_64 = NULL; 407 if (!valobj_sp) 408 return false; 409 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 410 Error error; 411 error.Clear(); 412 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 413 if (!process_sp) 414 return false; 415 m_ptr_size = process_sp->GetAddressByteSize(); 416 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 417 if (m_ptr_size == 4) 418 { 419 m_data_32 = new DataDescriptor_32(); 420 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); 421 } 422 else 423 { 424 m_data_64 = new DataDescriptor_64(); 425 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); 426 } 427 if (error.Fail()) 428 return false; 429 return false; 430 } 431 432 bool 433 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update() 434 { 435 m_children.clear(); 436 ValueObjectSP valobj_sp = m_backend.GetSP(); 437 m_ptr_size = 0; 438 delete m_data_32; 439 m_data_32 = NULL; 440 delete m_data_64; 441 m_data_64 = NULL; 442 if (!valobj_sp) 443 return false; 444 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 445 Error error; 446 error.Clear(); 447 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 448 if (!process_sp) 449 return false; 450 m_ptr_size = process_sp->GetAddressByteSize(); 451 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 452 if (m_ptr_size == 4) 453 { 454 m_data_32 = new DataDescriptor_32(); 455 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); 456 } 457 else 458 { 459 m_data_64 = new DataDescriptor_64(); 460 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); 461 } 462 if (error.Fail()) 463 return false; 464 return false; 465 } 466 467 bool 468 lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren () 469 { 470 return true; 471 } 472 473 size_t 474 lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 475 { 476 const char* item_name = name.GetCString(); 477 uint32_t idx = ExtractIndexFromString(item_name); 478 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 479 return UINT32_MAX; 480 return idx; 481 } 482 483 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::~NSArrayMSyntheticFrontEnd_109() 484 { 485 delete m_data_32; 486 m_data_32 = NULL; 487 delete m_data_64; 488 m_data_64 = NULL; 489 } 490 491 lldb::addr_t 492 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress () 493 { 494 if (!m_data_32 && !m_data_64) 495 return LLDB_INVALID_ADDRESS; 496 return m_data_32 ? m_data_32->_data : 497 m_data_64->_data; 498 } 499 500 uint64_t 501 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetUsedCount () 502 { 503 if (!m_data_32 && !m_data_64) 504 return 0; 505 return m_data_32 ? m_data_32->_used : 506 m_data_64->_used; 507 } 508 509 uint64_t 510 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetOffset () 511 { 512 if (!m_data_32 && !m_data_64) 513 return 0; 514 return m_data_32 ? m_data_32->_offset : 515 m_data_64->_offset; 516 } 517 518 uint64_t 519 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize () 520 { 521 if (!m_data_32 && !m_data_64) 522 return 0; 523 return m_data_32 ? m_data_32->_size : 524 m_data_64->_size; 525 } 526 527 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::~NSArrayMSyntheticFrontEnd_1010() 528 { 529 delete m_data_32; 530 m_data_32 = NULL; 531 delete m_data_64; 532 m_data_64 = NULL; 533 } 534 535 lldb::addr_t 536 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetDataAddress () 537 { 538 if (!m_data_32 && !m_data_64) 539 return LLDB_INVALID_ADDRESS; 540 return m_data_32 ? m_data_32->_data : 541 m_data_64->_data; 542 } 543 544 uint64_t 545 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetUsedCount () 546 { 547 if (!m_data_32 && !m_data_64) 548 return 0; 549 return m_data_32 ? m_data_32->_used : 550 m_data_64->_used; 551 } 552 553 uint64_t 554 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetOffset () 555 { 556 if (!m_data_32 && !m_data_64) 557 return 0; 558 return m_data_32 ? m_data_32->_offset : 559 m_data_64->_offset; 560 } 561 562 uint64_t 563 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize () 564 { 565 if (!m_data_32 && !m_data_64) 566 return 0; 567 return m_data_32 ? m_data_32->_size : 568 m_data_64->_size; 569 } 570 571 lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 572 SyntheticChildrenFrontEnd (*valobj_sp.get()), 573 m_exe_ctx_ref (), 574 m_ptr_size (8), 575 m_items (0), 576 m_data_ptr (0) 577 { 578 if (valobj_sp) 579 { 580 CompilerType type = valobj_sp->GetCompilerType(); 581 if (type) 582 { 583 ClangASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext(); 584 if (ast) 585 m_id_type = CompilerType(ast->getASTContext(), ast->getASTContext()->ObjCBuiltinIdTy); 586 } 587 } 588 } 589 590 size_t 591 lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 592 { 593 const char* item_name = name.GetCString(); 594 uint32_t idx = ExtractIndexFromString(item_name); 595 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 596 return UINT32_MAX; 597 return idx; 598 } 599 600 size_t 601 lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren () 602 { 603 return m_items; 604 } 605 606 bool 607 lldb_private::formatters::NSArrayISyntheticFrontEnd::Update() 608 { 609 m_ptr_size = 0; 610 m_items = 0; 611 m_data_ptr = 0; 612 m_children.clear(); 613 ValueObjectSP valobj_sp = m_backend.GetSP(); 614 if (!valobj_sp) 615 return false; 616 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 617 Error error; 618 error.Clear(); 619 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 620 if (!process_sp) 621 return false; 622 m_ptr_size = process_sp->GetAddressByteSize(); 623 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 624 m_items = process_sp->ReadPointerFromMemory(data_location, error); 625 if (error.Fail()) 626 return false; 627 m_data_ptr = data_location+m_ptr_size; 628 return false; 629 } 630 631 bool 632 lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren () 633 { 634 return true; 635 } 636 637 lldb::ValueObjectSP 638 lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx) 639 { 640 if (idx >= CalculateNumChildren()) 641 return lldb::ValueObjectSP(); 642 lldb::addr_t object_at_idx = m_data_ptr; 643 object_at_idx += (idx * m_ptr_size); 644 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 645 if (!process_sp) 646 return lldb::ValueObjectSP(); 647 Error error; 648 if (error.Fail()) 649 return lldb::ValueObjectSP(); 650 StreamString idx_name; 651 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 652 lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(), 653 object_at_idx, 654 m_exe_ctx_ref, 655 m_id_type); 656 m_children.push_back(retval_sp); 657 return retval_sp; 658 } 659 660 lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 661 SyntheticChildrenFrontEnd (*valobj_sp.get()) 662 { 663 } 664 665 size_t 666 lldb_private::formatters::NSArray0SyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 667 { 668 return UINT32_MAX; 669 } 670 671 size_t 672 lldb_private::formatters::NSArray0SyntheticFrontEnd::CalculateNumChildren () 673 { 674 return 0; 675 } 676 677 bool 678 lldb_private::formatters::NSArray0SyntheticFrontEnd::Update() 679 { 680 return false; 681 } 682 683 bool 684 lldb_private::formatters::NSArray0SyntheticFrontEnd::MightHaveChildren () 685 { 686 return false; 687 } 688 689 lldb::ValueObjectSP 690 lldb_private::formatters::NSArray0SyntheticFrontEnd::GetChildAtIndex (size_t idx) 691 { 692 return lldb::ValueObjectSP(); 693 } 694 695 SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 696 { 697 if (!valobj_sp) 698 return nullptr; 699 700 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); 701 if (!process_sp) 702 return NULL; 703 AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(process_sp->GetObjCLanguageRuntime()); 704 if (!runtime) 705 return NULL; 706 707 CompilerType valobj_type(valobj_sp->GetCompilerType()); 708 Flags flags(valobj_type.GetTypeInfo()); 709 710 if (flags.IsClear(eTypeIsPointer)) 711 { 712 Error error; 713 valobj_sp = valobj_sp->AddressOf(error); 714 if (error.Fail() || !valobj_sp) 715 return NULL; 716 } 717 718 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); 719 720 if (!descriptor.get() || !descriptor->IsValid()) 721 return NULL; 722 723 const char* class_name = descriptor->GetClassName().GetCString(); 724 725 if (!class_name || !*class_name) 726 return NULL; 727 728 if (!strcmp(class_name,"__NSArrayI")) 729 { 730 return (new NSArrayISyntheticFrontEnd(valobj_sp)); 731 } 732 else if (!strcmp(class_name,"__NSArray0")) 733 { 734 return (new NSArray0SyntheticFrontEnd(valobj_sp)); 735 } 736 else if (!strcmp(class_name,"__NSArrayM")) 737 { 738 if (runtime->GetFoundationVersion() >= 1100) 739 return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp)); 740 else 741 return (new NSArrayMSyntheticFrontEnd_109(valobj_sp)); 742 } 743 else 744 { 745 return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp)); 746 } 747 } 748 749 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 750 SyntheticChildrenFrontEnd(*valobj_sp.get()) 751 {} 752 753 size_t 754 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::CalculateNumChildren () 755 { 756 uint64_t count = 0; 757 if (ExtractValueFromObjCExpression(m_backend, "int", "count", count)) 758 return count; 759 return 0; 760 } 761 762 lldb::ValueObjectSP 763 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx) 764 { 765 StreamString idx_name; 766 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 767 lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx); 768 if (valobj_sp) 769 { 770 valobj_sp->SetPreferredDisplayLanguage(m_backend.GetPreferredDisplayLanguage()); 771 valobj_sp->SetName(ConstString(idx_name.GetData())); 772 } 773 return valobj_sp; 774 } 775 776 bool 777 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::Update() 778 { 779 return false; 780 } 781 782 bool 783 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::MightHaveChildren () 784 { 785 return true; 786 } 787 788 size_t 789 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 790 { 791 return 0; 792 } 793