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 #include "Cocoa.h" 11 12 #include "lldb/Core/DataBufferHeap.h" 13 #include "lldb/Core/Error.h" 14 #include "lldb/Core/Stream.h" 15 #include "lldb/Core/ValueObject.h" 16 #include "lldb/Core/ValueObjectConstResult.h" 17 #include "lldb/DataFormatters/FormattersHelpers.h" 18 #include "lldb/Expression/FunctionCaller.h" 19 #include "lldb/Host/Endian.h" 20 #include "lldb/Symbol/ClangASTContext.h" 21 #include "lldb/Target/Language.h" 22 #include "lldb/Target/ObjCLanguageRuntime.h" 23 #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" 24 #include "lldb/Target/Target.h" 25 26 #include "clang/AST/ASTContext.h" 27 28 using namespace lldb; 29 using namespace lldb_private; 30 using namespace lldb_private::formatters; 31 32 namespace lldb_private { 33 namespace formatters { 34 class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd 35 { 36 public: 37 NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 38 39 virtual size_t 40 CalculateNumChildren (); 41 42 virtual lldb::ValueObjectSP 43 GetChildAtIndex (size_t idx); 44 45 virtual bool 46 Update() = 0; 47 48 virtual bool 49 MightHaveChildren (); 50 51 virtual size_t 52 GetIndexOfChildWithName (const ConstString &name); 53 54 virtual 55 ~NSArrayMSyntheticFrontEnd () {} 56 57 protected: 58 virtual lldb::addr_t 59 GetDataAddress () = 0; 60 61 virtual uint64_t 62 GetUsedCount () = 0; 63 64 virtual uint64_t 65 GetOffset () = 0; 66 67 virtual uint64_t 68 GetSize () = 0; 69 70 ExecutionContextRef m_exe_ctx_ref; 71 uint8_t m_ptr_size; 72 CompilerType m_id_type; 73 std::vector<lldb::ValueObjectSP> m_children; 74 }; 75 76 class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd 77 { 78 private: 79 struct DataDescriptor_32 80 { 81 uint32_t _used; 82 uint32_t _priv1 : 2 ; 83 uint32_t _size : 30; 84 uint32_t _priv2 : 2; 85 uint32_t _offset : 30; 86 uint32_t _priv3; 87 uint32_t _data; 88 }; 89 struct DataDescriptor_64 90 { 91 uint64_t _used; 92 uint64_t _priv1 : 2 ; 93 uint64_t _size : 62; 94 uint64_t _priv2 : 2; 95 uint64_t _offset : 62; 96 uint32_t _priv3; 97 uint64_t _data; 98 }; 99 public: 100 NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp); 101 102 virtual bool 103 Update(); 104 105 virtual 106 ~NSArrayMSyntheticFrontEnd_109 (); 107 108 protected: 109 virtual lldb::addr_t 110 GetDataAddress (); 111 112 virtual uint64_t 113 GetUsedCount (); 114 115 virtual uint64_t 116 GetOffset (); 117 118 virtual uint64_t 119 GetSize (); 120 121 private: 122 DataDescriptor_32 *m_data_32; 123 DataDescriptor_64 *m_data_64; 124 }; 125 126 class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd 127 { 128 private: 129 struct DataDescriptor_32 130 { 131 uint32_t _used; 132 uint32_t _offset; 133 uint32_t _size : 28; 134 uint64_t _priv1 : 4; 135 uint32_t _priv2; 136 uint32_t _data; 137 }; 138 struct DataDescriptor_64 139 { 140 uint64_t _used; 141 uint64_t _offset; 142 uint64_t _size : 60; 143 uint64_t _priv1 : 4; 144 uint32_t _priv2; 145 uint64_t _data; 146 }; 147 public: 148 NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp); 149 150 virtual bool 151 Update(); 152 153 virtual 154 ~NSArrayMSyntheticFrontEnd_1010 (); 155 156 protected: 157 virtual lldb::addr_t 158 GetDataAddress (); 159 160 virtual uint64_t 161 GetUsedCount (); 162 163 virtual uint64_t 164 GetOffset (); 165 166 virtual uint64_t 167 GetSize (); 168 169 private: 170 DataDescriptor_32 *m_data_32; 171 DataDescriptor_64 *m_data_64; 172 }; 173 174 class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd 175 { 176 public: 177 NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 178 179 virtual size_t 180 CalculateNumChildren (); 181 182 virtual lldb::ValueObjectSP 183 GetChildAtIndex (size_t idx); 184 185 virtual bool 186 Update(); 187 188 virtual bool 189 MightHaveChildren (); 190 191 virtual size_t 192 GetIndexOfChildWithName (const ConstString &name); 193 194 virtual 195 ~NSArrayISyntheticFrontEnd (); 196 private: 197 ExecutionContextRef m_exe_ctx_ref; 198 uint8_t m_ptr_size; 199 uint64_t m_items; 200 lldb::addr_t m_data_ptr; 201 CompilerType m_id_type; 202 std::vector<lldb::ValueObjectSP> m_children; 203 }; 204 205 class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd 206 { 207 public: 208 NSArray0SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 209 210 virtual size_t 211 CalculateNumChildren (); 212 213 virtual lldb::ValueObjectSP 214 GetChildAtIndex (size_t idx); 215 216 virtual bool 217 Update(); 218 219 virtual bool 220 MightHaveChildren (); 221 222 virtual size_t 223 GetIndexOfChildWithName (const ConstString &name); 224 225 virtual 226 ~NSArray0SyntheticFrontEnd (); 227 private: 228 }; 229 230 class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd 231 { 232 public: 233 NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 234 235 virtual size_t 236 CalculateNumChildren (); 237 238 virtual lldb::ValueObjectSP 239 GetChildAtIndex (size_t idx); 240 241 virtual bool 242 Update(); 243 244 virtual bool 245 MightHaveChildren (); 246 247 virtual size_t 248 GetIndexOfChildWithName (const ConstString &name); 249 250 virtual 251 ~NSArrayCodeRunningSyntheticFrontEnd (); 252 }; 253 } 254 } 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::addr_t 484 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress () 485 { 486 if (!m_data_32 && !m_data_64) 487 return LLDB_INVALID_ADDRESS; 488 return m_data_32 ? m_data_32->_data : 489 m_data_64->_data; 490 } 491 492 uint64_t 493 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetUsedCount () 494 { 495 if (!m_data_32 && !m_data_64) 496 return 0; 497 return m_data_32 ? m_data_32->_used : 498 m_data_64->_used; 499 } 500 501 uint64_t 502 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetOffset () 503 { 504 if (!m_data_32 && !m_data_64) 505 return 0; 506 return m_data_32 ? m_data_32->_offset : 507 m_data_64->_offset; 508 } 509 510 uint64_t 511 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize () 512 { 513 if (!m_data_32 && !m_data_64) 514 return 0; 515 return m_data_32 ? m_data_32->_size : 516 m_data_64->_size; 517 } 518 519 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::~NSArrayMSyntheticFrontEnd_109 () 520 { 521 delete m_data_32; 522 m_data_32 = NULL; 523 delete m_data_64; 524 m_data_64 = NULL; 525 } 526 527 lldb::addr_t 528 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetDataAddress () 529 { 530 if (!m_data_32 && !m_data_64) 531 return LLDB_INVALID_ADDRESS; 532 return m_data_32 ? m_data_32->_data : 533 m_data_64->_data; 534 } 535 536 uint64_t 537 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetUsedCount () 538 { 539 if (!m_data_32 && !m_data_64) 540 return 0; 541 return m_data_32 ? m_data_32->_used : 542 m_data_64->_used; 543 } 544 545 uint64_t 546 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetOffset () 547 { 548 if (!m_data_32 && !m_data_64) 549 return 0; 550 return m_data_32 ? m_data_32->_offset : 551 m_data_64->_offset; 552 } 553 554 uint64_t 555 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize () 556 { 557 if (!m_data_32 && !m_data_64) 558 return 0; 559 return m_data_32 ? m_data_32->_size : 560 m_data_64->_size; 561 } 562 563 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::~NSArrayMSyntheticFrontEnd_1010 () 564 { 565 delete m_data_32; 566 m_data_32 = NULL; 567 delete m_data_64; 568 m_data_64 = NULL; 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 lldb_private::formatters::NSArrayISyntheticFrontEnd::~NSArrayISyntheticFrontEnd () 591 { 592 } 593 594 size_t 595 lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 596 { 597 const char* item_name = name.GetCString(); 598 uint32_t idx = ExtractIndexFromString(item_name); 599 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 600 return UINT32_MAX; 601 return idx; 602 } 603 604 size_t 605 lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren () 606 { 607 return m_items; 608 } 609 610 bool 611 lldb_private::formatters::NSArrayISyntheticFrontEnd::Update() 612 { 613 m_ptr_size = 0; 614 m_items = 0; 615 m_data_ptr = 0; 616 m_children.clear(); 617 ValueObjectSP valobj_sp = m_backend.GetSP(); 618 if (!valobj_sp) 619 return false; 620 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 621 Error error; 622 error.Clear(); 623 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 624 if (!process_sp) 625 return false; 626 m_ptr_size = process_sp->GetAddressByteSize(); 627 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 628 m_items = process_sp->ReadPointerFromMemory(data_location, error); 629 if (error.Fail()) 630 return false; 631 m_data_ptr = data_location+m_ptr_size; 632 return false; 633 } 634 635 bool 636 lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren () 637 { 638 return true; 639 } 640 641 lldb::ValueObjectSP 642 lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx) 643 { 644 if (idx >= CalculateNumChildren()) 645 return lldb::ValueObjectSP(); 646 lldb::addr_t object_at_idx = m_data_ptr; 647 object_at_idx += (idx * m_ptr_size); 648 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 649 if (!process_sp) 650 return lldb::ValueObjectSP(); 651 Error error; 652 if (error.Fail()) 653 return lldb::ValueObjectSP(); 654 StreamString idx_name; 655 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 656 lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(), 657 object_at_idx, 658 m_exe_ctx_ref, 659 m_id_type); 660 m_children.push_back(retval_sp); 661 return retval_sp; 662 } 663 664 lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 665 SyntheticChildrenFrontEnd (*valobj_sp.get()) 666 { 667 } 668 669 lldb_private::formatters::NSArray0SyntheticFrontEnd::~NSArray0SyntheticFrontEnd () 670 { 671 } 672 673 size_t 674 lldb_private::formatters::NSArray0SyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 675 { 676 return UINT32_MAX; 677 } 678 679 size_t 680 lldb_private::formatters::NSArray0SyntheticFrontEnd::CalculateNumChildren () 681 { 682 return 0; 683 } 684 685 bool 686 lldb_private::formatters::NSArray0SyntheticFrontEnd::Update() 687 { 688 return false; 689 } 690 691 bool 692 lldb_private::formatters::NSArray0SyntheticFrontEnd::MightHaveChildren () 693 { 694 return false; 695 } 696 697 lldb::ValueObjectSP 698 lldb_private::formatters::NSArray0SyntheticFrontEnd::GetChildAtIndex (size_t idx) 699 { 700 return lldb::ValueObjectSP(); 701 } 702 703 SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 704 { 705 if (!valobj_sp) 706 return nullptr; 707 708 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); 709 if (!process_sp) 710 return NULL; 711 AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(process_sp->GetObjCLanguageRuntime()); 712 if (!runtime) 713 return NULL; 714 715 CompilerType valobj_type(valobj_sp->GetCompilerType()); 716 Flags flags(valobj_type.GetTypeInfo()); 717 718 if (flags.IsClear(eTypeIsPointer)) 719 { 720 Error error; 721 valobj_sp = valobj_sp->AddressOf(error); 722 if (error.Fail() || !valobj_sp) 723 return NULL; 724 } 725 726 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); 727 728 if (!descriptor.get() || !descriptor->IsValid()) 729 return NULL; 730 731 const char* class_name = descriptor->GetClassName().GetCString(); 732 733 if (!class_name || !*class_name) 734 return NULL; 735 736 if (!strcmp(class_name,"__NSArrayI")) 737 { 738 return (new NSArrayISyntheticFrontEnd(valobj_sp)); 739 } 740 else if (!strcmp(class_name,"__NSArray0")) 741 { 742 return (new NSArray0SyntheticFrontEnd(valobj_sp)); 743 } 744 else if (!strcmp(class_name,"__NSArrayM")) 745 { 746 if (runtime->GetFoundationVersion() >= 1100) 747 return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp)); 748 else 749 return (new NSArrayMSyntheticFrontEnd_109(valobj_sp)); 750 } 751 else 752 { 753 return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp)); 754 } 755 } 756 757 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 758 SyntheticChildrenFrontEnd(*valobj_sp.get()) 759 {} 760 761 size_t 762 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::CalculateNumChildren () 763 { 764 uint64_t count = 0; 765 if (ExtractValueFromObjCExpression(m_backend, "int", "count", count)) 766 return count; 767 return 0; 768 } 769 770 lldb::ValueObjectSP 771 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx) 772 { 773 StreamString idx_name; 774 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 775 lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx); 776 if (valobj_sp) 777 { 778 valobj_sp->SetPreferredDisplayLanguage(m_backend.GetPreferredDisplayLanguage()); 779 valobj_sp->SetName(ConstString(idx_name.GetData())); 780 } 781 return valobj_sp; 782 } 783 784 bool 785 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::Update() 786 { 787 return false; 788 } 789 790 bool 791 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::MightHaveChildren () 792 { 793 return true; 794 } 795 796 size_t 797 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 798 { 799 return 0; 800 } 801 802 lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::~NSArrayCodeRunningSyntheticFrontEnd () 803 {} 804