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 NSArray1SyntheticFrontEnd : public SyntheticChildrenFrontEnd 232 { 233 public: 234 NSArray1SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); 235 236 ~NSArray1SyntheticFrontEnd() 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 || !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 ConstString class_name(descriptor->GetClassName()); 285 286 static const ConstString g_NSArrayI("__NSArrayI"); 287 static const ConstString g_NSArrayM("__NSArrayM"); 288 static const ConstString g_NSArray0("__NSArray0"); 289 static const ConstString g_NSArray1("__NSSingleObjectArrayI"); 290 static const ConstString g_NSArrayCF("__NSCFArray"); 291 292 if (class_name.IsEmpty()) 293 return false; 294 295 if (class_name == g_NSArrayI) 296 { 297 Error error; 298 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); 299 if (error.Fail()) 300 return false; 301 } 302 else if (class_name == g_NSArrayM) 303 { 304 Error error; 305 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); 306 if (error.Fail()) 307 return false; 308 } 309 else if (class_name == g_NSArray0) 310 { 311 value = 0; 312 } 313 else if (class_name == g_NSArray1) 314 { 315 value = 1; 316 } 317 else if (class_name == g_NSArrayCF) 318 { 319 Error error; 320 value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size, ptr_size, 0, error); 321 if (error.Fail()) 322 return false; 323 } 324 else 325 return false; 326 327 std::string prefix,suffix; 328 if (Language* language = Language::FindPlugin(options.GetLanguage())) 329 { 330 if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) 331 { 332 prefix.clear(); 333 suffix.clear(); 334 } 335 } 336 337 stream.Printf("%s%" PRIu64 " %s%s%s", 338 prefix.c_str(), 339 value, 340 "element", 341 value == 1 ? "" : "s", 342 suffix.c_str()); 343 return true; 344 } 345 346 lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 347 SyntheticChildrenFrontEnd(*valobj_sp), 348 m_exe_ctx_ref(), 349 m_ptr_size(8), 350 m_id_type(), 351 m_children() 352 { 353 if (valobj_sp) 354 { 355 clang::ASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext()->getASTContext(); 356 if (ast) 357 m_id_type = CompilerType(ast, ast->ObjCBuiltinIdTy); 358 if (valobj_sp->GetProcessSP()) 359 m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize(); 360 } 361 } 362 363 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp) : 364 NSArrayMSyntheticFrontEnd(valobj_sp), 365 m_data_32(nullptr), 366 m_data_64(nullptr) 367 { 368 } 369 370 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp) : 371 NSArrayMSyntheticFrontEnd(valobj_sp), 372 m_data_32(nullptr), 373 m_data_64(nullptr) 374 { 375 } 376 377 size_t 378 lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren () 379 { 380 return GetUsedCount(); 381 } 382 383 lldb::ValueObjectSP 384 lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx) 385 { 386 if (idx >= CalculateNumChildren()) 387 return lldb::ValueObjectSP(); 388 lldb::addr_t object_at_idx = GetDataAddress(); 389 size_t pyhs_idx = idx; 390 pyhs_idx += GetOffset(); 391 if (GetSize() <= pyhs_idx) 392 pyhs_idx -= GetSize(); 393 object_at_idx += (pyhs_idx * m_ptr_size); 394 StreamString idx_name; 395 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 396 lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(), 397 object_at_idx, 398 m_exe_ctx_ref, 399 m_id_type); 400 m_children.push_back(retval_sp); 401 return retval_sp; 402 } 403 404 bool 405 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::Update() 406 { 407 m_children.clear(); 408 ValueObjectSP valobj_sp = m_backend.GetSP(); 409 m_ptr_size = 0; 410 delete m_data_32; 411 m_data_32 = nullptr; 412 delete m_data_64; 413 m_data_64 = nullptr; 414 if (!valobj_sp) 415 return false; 416 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 417 Error error; 418 error.Clear(); 419 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 420 if (!process_sp) 421 return false; 422 m_ptr_size = process_sp->GetAddressByteSize(); 423 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 424 if (m_ptr_size == 4) 425 { 426 m_data_32 = new DataDescriptor_32(); 427 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); 428 } 429 else 430 { 431 m_data_64 = new DataDescriptor_64(); 432 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); 433 } 434 if (error.Fail()) 435 return false; 436 return false; 437 } 438 439 bool 440 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update() 441 { 442 m_children.clear(); 443 ValueObjectSP valobj_sp = m_backend.GetSP(); 444 m_ptr_size = 0; 445 delete m_data_32; 446 m_data_32 = nullptr; 447 delete m_data_64; 448 m_data_64 = nullptr; 449 if (!valobj_sp) 450 return false; 451 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 452 Error error; 453 error.Clear(); 454 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 455 if (!process_sp) 456 return false; 457 m_ptr_size = process_sp->GetAddressByteSize(); 458 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 459 if (m_ptr_size == 4) 460 { 461 m_data_32 = new DataDescriptor_32(); 462 process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); 463 } 464 else 465 { 466 m_data_64 = new DataDescriptor_64(); 467 process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); 468 } 469 if (error.Fail()) 470 return false; 471 return false; 472 } 473 474 bool 475 lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren () 476 { 477 return true; 478 } 479 480 size_t 481 lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 482 { 483 const char* item_name = name.GetCString(); 484 uint32_t idx = ExtractIndexFromString(item_name); 485 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 486 return UINT32_MAX; 487 return idx; 488 } 489 490 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::~NSArrayMSyntheticFrontEnd_109() 491 { 492 delete m_data_32; 493 m_data_32 = nullptr; 494 delete m_data_64; 495 m_data_64 = nullptr; 496 } 497 498 lldb::addr_t 499 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress () 500 { 501 if (!m_data_32 && !m_data_64) 502 return LLDB_INVALID_ADDRESS; 503 return m_data_32 ? m_data_32->_data : 504 m_data_64->_data; 505 } 506 507 uint64_t 508 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetUsedCount () 509 { 510 if (!m_data_32 && !m_data_64) 511 return 0; 512 return m_data_32 ? m_data_32->_used : 513 m_data_64->_used; 514 } 515 516 uint64_t 517 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetOffset () 518 { 519 if (!m_data_32 && !m_data_64) 520 return 0; 521 return m_data_32 ? m_data_32->_offset : 522 m_data_64->_offset; 523 } 524 525 uint64_t 526 lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize () 527 { 528 if (!m_data_32 && !m_data_64) 529 return 0; 530 return m_data_32 ? m_data_32->_size : 531 m_data_64->_size; 532 } 533 534 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::~NSArrayMSyntheticFrontEnd_1010() 535 { 536 delete m_data_32; 537 m_data_32 = nullptr; 538 delete m_data_64; 539 m_data_64 = nullptr; 540 } 541 542 lldb::addr_t 543 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetDataAddress () 544 { 545 if (!m_data_32 && !m_data_64) 546 return LLDB_INVALID_ADDRESS; 547 return m_data_32 ? m_data_32->_data : 548 m_data_64->_data; 549 } 550 551 uint64_t 552 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetUsedCount () 553 { 554 if (!m_data_32 && !m_data_64) 555 return 0; 556 return m_data_32 ? m_data_32->_used : 557 m_data_64->_used; 558 } 559 560 uint64_t 561 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetOffset () 562 { 563 if (!m_data_32 && !m_data_64) 564 return 0; 565 return m_data_32 ? m_data_32->_offset : 566 m_data_64->_offset; 567 } 568 569 uint64_t 570 lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize () 571 { 572 if (!m_data_32 && !m_data_64) 573 return 0; 574 return m_data_32 ? m_data_32->_size : 575 m_data_64->_size; 576 } 577 578 lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 579 SyntheticChildrenFrontEnd(*valobj_sp), 580 m_exe_ctx_ref(), 581 m_ptr_size(8), 582 m_items(0), 583 m_data_ptr(0) 584 { 585 if (valobj_sp) 586 { 587 CompilerType type = valobj_sp->GetCompilerType(); 588 if (type) 589 { 590 ClangASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext(); 591 if (ast) 592 m_id_type = CompilerType(ast->getASTContext(), ast->getASTContext()->ObjCBuiltinIdTy); 593 } 594 } 595 } 596 597 size_t 598 lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 599 { 600 const char* item_name = name.GetCString(); 601 uint32_t idx = ExtractIndexFromString(item_name); 602 if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 603 return UINT32_MAX; 604 return idx; 605 } 606 607 size_t 608 lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren () 609 { 610 return m_items; 611 } 612 613 bool 614 lldb_private::formatters::NSArrayISyntheticFrontEnd::Update() 615 { 616 m_ptr_size = 0; 617 m_items = 0; 618 m_data_ptr = 0; 619 m_children.clear(); 620 ValueObjectSP valobj_sp = m_backend.GetSP(); 621 if (!valobj_sp) 622 return false; 623 m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 624 Error error; 625 error.Clear(); 626 lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 627 if (!process_sp) 628 return false; 629 m_ptr_size = process_sp->GetAddressByteSize(); 630 uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 631 m_items = process_sp->ReadPointerFromMemory(data_location, error); 632 if (error.Fail()) 633 return false; 634 m_data_ptr = data_location+m_ptr_size; 635 return false; 636 } 637 638 bool 639 lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren () 640 { 641 return true; 642 } 643 644 lldb::ValueObjectSP 645 lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx) 646 { 647 if (idx >= CalculateNumChildren()) 648 return lldb::ValueObjectSP(); 649 lldb::addr_t object_at_idx = m_data_ptr; 650 object_at_idx += (idx * m_ptr_size); 651 ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 652 if (!process_sp) 653 return lldb::ValueObjectSP(); 654 Error error; 655 if (error.Fail()) 656 return lldb::ValueObjectSP(); 657 StreamString idx_name; 658 idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 659 lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(), 660 object_at_idx, 661 m_exe_ctx_ref, 662 m_id_type); 663 m_children.push_back(retval_sp); 664 return retval_sp; 665 } 666 667 lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 668 SyntheticChildrenFrontEnd(*valobj_sp) 669 { 670 } 671 672 size_t 673 lldb_private::formatters::NSArray0SyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 674 { 675 return UINT32_MAX; 676 } 677 678 size_t 679 lldb_private::formatters::NSArray0SyntheticFrontEnd::CalculateNumChildren () 680 { 681 return 0; 682 } 683 684 bool 685 lldb_private::formatters::NSArray0SyntheticFrontEnd::Update() 686 { 687 return false; 688 } 689 690 bool 691 lldb_private::formatters::NSArray0SyntheticFrontEnd::MightHaveChildren () 692 { 693 return false; 694 } 695 696 lldb::ValueObjectSP 697 lldb_private::formatters::NSArray0SyntheticFrontEnd::GetChildAtIndex (size_t idx) 698 { 699 return lldb::ValueObjectSP(); 700 } 701 702 lldb_private::formatters::NSArray1SyntheticFrontEnd::NSArray1SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : 703 SyntheticChildrenFrontEnd (*valobj_sp.get()) 704 { 705 } 706 707 size_t 708 lldb_private::formatters::NSArray1SyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) 709 { 710 static const ConstString g_zero("[0]"); 711 712 if (name == g_zero) 713 return 0; 714 715 return UINT32_MAX; 716 } 717 718 size_t 719 lldb_private::formatters::NSArray1SyntheticFrontEnd::CalculateNumChildren () 720 { 721 return 1; 722 } 723 724 bool 725 lldb_private::formatters::NSArray1SyntheticFrontEnd::Update() 726 { 727 return false; 728 } 729 730 bool 731 lldb_private::formatters::NSArray1SyntheticFrontEnd::MightHaveChildren () 732 { 733 return true; 734 } 735 736 lldb::ValueObjectSP 737 lldb_private::formatters::NSArray1SyntheticFrontEnd::GetChildAtIndex (size_t idx) 738 { 739 static const ConstString g_zero("[0]"); 740 741 if (idx == 0) 742 { 743 CompilerType id_type(m_backend.GetTargetSP()->GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeObjCID)); 744 return m_backend.GetSyntheticChildAtOffset(m_backend.GetProcessSP()->GetAddressByteSize(), id_type, true, g_zero); 745 } 746 return lldb::ValueObjectSP(); 747 } 748 749 SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) 750 { 751 if (!valobj_sp) 752 return nullptr; 753 754 lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); 755 if (!process_sp) 756 return nullptr; 757 AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(process_sp->GetObjCLanguageRuntime()); 758 if (!runtime) 759 return nullptr; 760 761 CompilerType valobj_type(valobj_sp->GetCompilerType()); 762 Flags flags(valobj_type.GetTypeInfo()); 763 764 if (flags.IsClear(eTypeIsPointer)) 765 { 766 Error error; 767 valobj_sp = valobj_sp->AddressOf(error); 768 if (error.Fail() || !valobj_sp) 769 return nullptr; 770 } 771 772 ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp)); 773 774 if (!descriptor || !descriptor->IsValid()) 775 return nullptr; 776 777 ConstString class_name(descriptor->GetClassName()); 778 779 static const ConstString g_NSArrayI("__NSArrayI"); 780 static const ConstString g_NSArrayM("__NSArrayM"); 781 static const ConstString g_NSArray0("__NSArray0"); 782 static const ConstString g_NSArray1("__NSSingleObjectArrayI"); 783 784 if (class_name.IsEmpty()) 785 return nullptr; 786 787 if (class_name == g_NSArrayI) 788 { 789 return (new NSArrayISyntheticFrontEnd(valobj_sp)); 790 } 791 else if (class_name == g_NSArray0) 792 { 793 return (new NSArray0SyntheticFrontEnd(valobj_sp)); 794 } 795 else if (class_name == g_NSArray1) 796 { 797 return (new NSArray1SyntheticFrontEnd(valobj_sp)); 798 } 799 else if (class_name == g_NSArrayM) 800 { 801 if (runtime->GetFoundationVersion() >= 1100) 802 return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp)); 803 else 804 return (new NSArrayMSyntheticFrontEnd_109(valobj_sp)); 805 } 806 807 return nullptr; 808 } 809