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