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