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