1292932Sdim//===-- NSArray.cpp ---------------------------------------------*- C++ -*-===// 2292932Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6292932Sdim// 7292932Sdim//===----------------------------------------------------------------------===// 8292932Sdim 9292932Sdim#include "clang/AST/ASTContext.h" 10292932Sdim 11292932Sdim#include "Cocoa.h" 12292932Sdim 13314564Sdim#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" 14353358Sdim 15292932Sdim#include "lldb/Core/ValueObject.h" 16292932Sdim#include "lldb/Core/ValueObjectConstResult.h" 17292932Sdim#include "lldb/DataFormatters/FormattersHelpers.h" 18292932Sdim#include "lldb/Expression/FunctionCaller.h" 19292932Sdim#include "lldb/Symbol/ClangASTContext.h" 20292932Sdim#include "lldb/Target/Language.h" 21292932Sdim#include "lldb/Target/Target.h" 22321369Sdim#include "lldb/Utility/DataBufferHeap.h" 23321369Sdim#include "lldb/Utility/Endian.h" 24321369Sdim#include "lldb/Utility/Status.h" 25321369Sdim#include "lldb/Utility/Stream.h" 26292932Sdim 27292932Sdimusing namespace lldb; 28292932Sdimusing namespace lldb_private; 29292932Sdimusing namespace lldb_private::formatters; 30292932Sdim 31314564Sdimnamespace lldb_private { 32314564Sdimnamespace formatters { 33314564Sdimstd::map<ConstString, CXXFunctionSummaryFormat::Callback> & 34314564SdimNSArray_Additionals::GetAdditionalSummaries() { 35314564Sdim static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map; 36314564Sdim return g_map; 37314564Sdim} 38292932Sdim 39314564Sdimstd::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> & 40314564SdimNSArray_Additionals::GetAdditionalSynthetics() { 41314564Sdim static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> 42314564Sdim g_map; 43314564Sdim return g_map; 44314564Sdim} 45292932Sdim 46327952Sdimclass NSArrayMSyntheticFrontEndBase : public SyntheticChildrenFrontEnd { 47314564Sdimpublic: 48327952Sdim NSArrayMSyntheticFrontEndBase(lldb::ValueObjectSP valobj_sp); 49292932Sdim 50327952Sdim ~NSArrayMSyntheticFrontEndBase() override = default; 51292932Sdim 52314564Sdim size_t CalculateNumChildren() override; 53292932Sdim 54314564Sdim lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 55292932Sdim 56314564Sdim bool Update() override = 0; 57292932Sdim 58314564Sdim bool MightHaveChildren() override; 59292932Sdim 60353358Sdim size_t GetIndexOfChildWithName(ConstString name) override; 61292932Sdim 62314564Sdimprotected: 63314564Sdim virtual lldb::addr_t GetDataAddress() = 0; 64292932Sdim 65314564Sdim virtual uint64_t GetUsedCount() = 0; 66292932Sdim 67314564Sdim virtual uint64_t GetOffset() = 0; 68292932Sdim 69314564Sdim virtual uint64_t GetSize() = 0; 70292932Sdim 71314564Sdim ExecutionContextRef m_exe_ctx_ref; 72314564Sdim uint8_t m_ptr_size; 73314564Sdim CompilerType m_id_type; 74314564Sdim}; 75292932Sdim 76327952Sdimtemplate <typename D32, typename D64> 77327952Sdimclass GenericNSArrayMSyntheticFrontEnd : public NSArrayMSyntheticFrontEndBase { 78314564Sdimpublic: 79327952Sdim GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 80292932Sdim 81327952Sdim ~GenericNSArrayMSyntheticFrontEnd() override; 82309124Sdim 83314564Sdim bool Update() override; 84314564Sdim 85314564Sdimprotected: 86314564Sdim lldb::addr_t GetDataAddress() override; 87314564Sdim 88314564Sdim uint64_t GetUsedCount() override; 89314564Sdim 90314564Sdim uint64_t GetOffset() override; 91314564Sdim 92314564Sdim uint64_t GetSize() override; 93314564Sdim 94314564Sdimprivate: 95327952Sdim D32 *m_data_32; 96327952Sdim D64 *m_data_64; 97327952Sdim}; 98327952Sdim 99327952Sdimnamespace Foundation1010 { 100314564Sdim struct DataDescriptor_32 { 101314564Sdim uint32_t _used; 102314564Sdim uint32_t _offset; 103314564Sdim uint32_t _size : 28; 104314564Sdim uint64_t _priv1 : 4; 105314564Sdim uint32_t _priv2; 106314564Sdim uint32_t _data; 107314564Sdim }; 108327952Sdim 109314564Sdim struct DataDescriptor_64 { 110314564Sdim uint64_t _used; 111314564Sdim uint64_t _offset; 112314564Sdim uint64_t _size : 60; 113314564Sdim uint64_t _priv1 : 4; 114314564Sdim uint32_t _priv2; 115314564Sdim uint64_t _data; 116314564Sdim }; 117327952Sdim 118327952Sdim using NSArrayMSyntheticFrontEnd = 119327952Sdim GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; 120327952Sdim} 121327952Sdim 122327952Sdimnamespace Foundation1428 { 123321369Sdim struct DataDescriptor_32 { 124327952Sdim uint32_t _used; 125327952Sdim uint32_t _offset; 126327952Sdim uint32_t _size; 127327952Sdim uint32_t _data; 128321369Sdim }; 129327952Sdim 130321369Sdim struct DataDescriptor_64 { 131327952Sdim uint64_t _used; 132327952Sdim uint64_t _offset; 133327952Sdim uint64_t _size; 134327952Sdim uint64_t _data; 135321369Sdim }; 136327952Sdim 137327952Sdim using NSArrayMSyntheticFrontEnd = 138327952Sdim GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; 139327952Sdim} 140327952Sdim 141327952Sdimnamespace Foundation1437 { 142327952Sdim template <typename PtrType> 143327952Sdim struct DataDescriptor { 144327952Sdim PtrType _cow; 145327952Sdim // __deque 146327952Sdim PtrType _data; 147327952Sdim uint32_t _offset; 148327952Sdim uint32_t _size; 149353358Sdim uint32_t _muts; 150353358Sdim uint32_t _used; 151327952Sdim }; 152327952Sdim 153327952Sdim using NSArrayMSyntheticFrontEnd = 154327952Sdim GenericNSArrayMSyntheticFrontEnd< 155327952Sdim DataDescriptor<uint32_t>, DataDescriptor<uint64_t>>; 156327952Sdim 157327952Sdim template <typename DD> 158327952Sdim uint64_t 159327952Sdim __NSArrayMSize_Impl(lldb_private::Process &process, 160327952Sdim lldb::addr_t valobj_addr, Status &error) { 161327952Sdim const lldb::addr_t start_of_descriptor = 162327952Sdim valobj_addr + process.GetAddressByteSize(); 163327952Sdim DD descriptor = DD(); 164327952Sdim process.ReadMemory(start_of_descriptor, &descriptor, 165327952Sdim sizeof(descriptor), error); 166327952Sdim if (error.Fail()) { 167327952Sdim return 0; 168327952Sdim } 169327952Sdim return descriptor._used; 170327952Sdim } 171327952Sdim 172327952Sdim uint64_t 173327952Sdim __NSArrayMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, 174327952Sdim Status &error) { 175327952Sdim if (process.GetAddressByteSize() == 4) { 176327952Sdim return __NSArrayMSize_Impl<DataDescriptor<uint32_t>>(process, valobj_addr, 177327952Sdim error); 178327952Sdim } else { 179327952Sdim return __NSArrayMSize_Impl<DataDescriptor<uint64_t>>(process, valobj_addr, 180327952Sdim error); 181327952Sdim } 182327952Sdim } 183321369Sdim 184327952Sdim} 185321369Sdim 186344779Sdimnamespace CallStackArray { 187344779Sdimstruct DataDescriptor_32 { 188344779Sdim uint32_t _data; 189344779Sdim uint32_t _used; 190344779Sdim uint32_t _offset; 191344779Sdim const uint32_t _size = 0; 192344779Sdim}; 193344779Sdim 194344779Sdimstruct DataDescriptor_64 { 195344779Sdim uint64_t _data; 196344779Sdim uint64_t _used; 197344779Sdim uint64_t _offset; 198344779Sdim const uint64_t _size = 0; 199344779Sdim}; 200344779Sdim 201344779Sdimusing NSCallStackArraySyntheticFrontEnd = 202344779Sdim GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; 203344779Sdim} // namespace CallStackArray 204344779Sdim 205327952Sdimtemplate <typename D32, typename D64, bool Inline> 206327952Sdimclass GenericNSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd { 207321369Sdimpublic: 208327952Sdim GenericNSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 209321369Sdim 210327952Sdim ~GenericNSArrayISyntheticFrontEnd() override; 211321369Sdim 212314564Sdim size_t CalculateNumChildren() override; 213314564Sdim 214314564Sdim lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 215314564Sdim 216314564Sdim bool Update() override; 217314564Sdim 218314564Sdim bool MightHaveChildren() override; 219314564Sdim 220353358Sdim size_t GetIndexOfChildWithName(ConstString name) override; 221314564Sdim 222314564Sdimprivate: 223314564Sdim ExecutionContextRef m_exe_ctx_ref; 224314564Sdim uint8_t m_ptr_size; 225327952Sdim 226327952Sdim D32 *m_data_32; 227327952Sdim D64 *m_data_64; 228314564Sdim CompilerType m_id_type; 229314564Sdim}; 230327952Sdim 231327952Sdimnamespace Foundation1300 { 232327952Sdim struct IDD32 { 233327952Sdim uint32_t used; 234327952Sdim uint32_t list; 235327952Sdim }; 236327952Sdim 237327952Sdim struct IDD64 { 238327952Sdim uint64_t used; 239327952Sdim uint64_t list; 240327952Sdim }; 241327952Sdim 242327952Sdim using NSArrayISyntheticFrontEnd = 243327952Sdim GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, true>; 244327952Sdim} 245314564Sdim 246327952Sdimnamespace Foundation1430 { 247327952Sdim using NSArrayISyntheticFrontEnd = 248327952Sdim Foundation1428::NSArrayMSyntheticFrontEnd; 249327952Sdim} 250321369Sdim 251327952Sdimnamespace Foundation1436 { 252327952Sdim struct IDD32 { 253327952Sdim uint32_t used; 254327952Sdim uint32_t list; // in Inline cases, this is the first element 255327952Sdim }; 256327952Sdim 257327952Sdim struct IDD64 { 258327952Sdim uint64_t used; 259327952Sdim uint64_t list; // in Inline cases, this is the first element 260327952Sdim }; 261327952Sdim 262327952Sdim using NSArrayI_TransferSyntheticFrontEnd = 263327952Sdim GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, false>; 264321369Sdim 265327952Sdim using NSArrayISyntheticFrontEnd = 266327952Sdim GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, true>; 267327952Sdim 268327952Sdim using NSFrozenArrayMSyntheticFrontEnd = 269327952Sdim Foundation1437::NSArrayMSyntheticFrontEnd; 270321369Sdim 271327952Sdim uint64_t 272327952Sdim __NSFrozenArrayMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, 273327952Sdim Status &error) { 274327952Sdim return Foundation1437::__NSArrayMSize(process, valobj_addr, error); 275327952Sdim } 276327952Sdim} 277321369Sdim 278314564Sdimclass NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd { 279314564Sdimpublic: 280314564Sdim NSArray0SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 281314564Sdim 282314564Sdim ~NSArray0SyntheticFrontEnd() override = default; 283314564Sdim 284314564Sdim size_t CalculateNumChildren() override; 285314564Sdim 286314564Sdim lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 287314564Sdim 288314564Sdim bool Update() override; 289314564Sdim 290314564Sdim bool MightHaveChildren() override; 291314564Sdim 292353358Sdim size_t GetIndexOfChildWithName(ConstString name) override; 293314564Sdim}; 294314564Sdim 295314564Sdimclass NSArray1SyntheticFrontEnd : public SyntheticChildrenFrontEnd { 296314564Sdimpublic: 297314564Sdim NSArray1SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); 298314564Sdim 299314564Sdim ~NSArray1SyntheticFrontEnd() override = default; 300314564Sdim 301314564Sdim size_t CalculateNumChildren() override; 302314564Sdim 303314564Sdim lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; 304314564Sdim 305314564Sdim bool Update() override; 306314564Sdim 307314564Sdim bool MightHaveChildren() override; 308314564Sdim 309353358Sdim size_t GetIndexOfChildWithName(ConstString name) override; 310314564Sdim}; 311314564Sdim} // namespace formatters 312292932Sdim} // namespace lldb_private 313292932Sdim 314314564Sdimbool lldb_private::formatters::NSArraySummaryProvider( 315314564Sdim ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { 316314564Sdim static ConstString g_TypeHint("NSArray"); 317314564Sdim 318314564Sdim ProcessSP process_sp = valobj.GetProcessSP(); 319314564Sdim if (!process_sp) 320314564Sdim return false; 321314564Sdim 322353358Sdim ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp); 323314564Sdim 324314564Sdim if (!runtime) 325314564Sdim return false; 326314564Sdim 327314564Sdim ObjCLanguageRuntime::ClassDescriptorSP descriptor( 328314564Sdim runtime->GetClassDescriptor(valobj)); 329314564Sdim 330314564Sdim if (!descriptor || !descriptor->IsValid()) 331314564Sdim return false; 332314564Sdim 333314564Sdim uint32_t ptr_size = process_sp->GetAddressByteSize(); 334314564Sdim 335314564Sdim lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); 336314564Sdim 337314564Sdim if (!valobj_addr) 338314564Sdim return false; 339314564Sdim 340314564Sdim uint64_t value = 0; 341314564Sdim 342314564Sdim ConstString class_name(descriptor->GetClassName()); 343314564Sdim 344314564Sdim static const ConstString g_NSArrayI("__NSArrayI"); 345314564Sdim static const ConstString g_NSArrayM("__NSArrayM"); 346327952Sdim static const ConstString g_NSArrayI_Transfer("__NSArrayI_Transfer"); 347327952Sdim static const ConstString g_NSFrozenArrayM("__NSFrozenArrayM"); 348314564Sdim static const ConstString g_NSArray0("__NSArray0"); 349314564Sdim static const ConstString g_NSArray1("__NSSingleObjectArrayI"); 350314564Sdim static const ConstString g_NSArrayCF("__NSCFArray"); 351321369Sdim static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy"); 352321369Sdim static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable"); 353344779Sdim static const ConstString g_NSCallStackArray("_NSCallStackArray"); 354314564Sdim 355314564Sdim if (class_name.IsEmpty()) 356314564Sdim return false; 357314564Sdim 358314564Sdim if (class_name == g_NSArrayI) { 359321369Sdim Status error; 360314564Sdim value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 361314564Sdim ptr_size, 0, error); 362314564Sdim if (error.Fail()) 363314564Sdim return false; 364314564Sdim } else if (class_name == g_NSArrayM) { 365327952Sdim AppleObjCRuntime *apple_runtime = 366327952Sdim llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); 367321369Sdim Status error; 368327952Sdim if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { 369327952Sdim value = Foundation1437::__NSArrayMSize(*process_sp, valobj_addr, error); 370327952Sdim } else { 371327952Sdim value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 372327952Sdim ptr_size, 0, error); 373327952Sdim } 374327952Sdim if (error.Fail()) 375327952Sdim return false; 376327952Sdim } else if (class_name == g_NSArrayI_Transfer) { 377327952Sdim Status error; 378314564Sdim value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 379314564Sdim ptr_size, 0, error); 380314564Sdim if (error.Fail()) 381314564Sdim return false; 382327952Sdim } else if (class_name == g_NSFrozenArrayM) { 383327952Sdim Status error; 384327952Sdim value = Foundation1436::__NSFrozenArrayMSize(*process_sp, valobj_addr, error); 385327952Sdim if (error.Fail()) 386327952Sdim return false; 387321369Sdim } else if (class_name == g_NSArrayMLegacy) { 388321369Sdim Status error; 389321369Sdim value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 390321369Sdim ptr_size, 0, error); 391321369Sdim if (error.Fail()) 392321369Sdim return false; 393321369Sdim } else if (class_name == g_NSArrayMImmutable) { 394321369Sdim Status error; 395321369Sdim value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 396321369Sdim ptr_size, 0, error); 397321369Sdim if (error.Fail()) 398321369Sdim return false; 399314564Sdim } else if (class_name == g_NSArray0) { 400314564Sdim value = 0; 401314564Sdim } else if (class_name == g_NSArray1) { 402314564Sdim value = 1; 403344779Sdim } else if (class_name == g_NSArrayCF || class_name == g_NSCallStackArray) { 404344779Sdim // __NSCFArray and _NSCallStackArray store the number of elements as a 405344779Sdim // pointer-sized value at offset `2 * ptr_size`. 406321369Sdim Status error; 407314564Sdim value = process_sp->ReadUnsignedIntegerFromMemory( 408314564Sdim valobj_addr + 2 * ptr_size, ptr_size, 0, error); 409314564Sdim if (error.Fail()) 410314564Sdim return false; 411314564Sdim } else { 412314564Sdim auto &map(NSArray_Additionals::GetAdditionalSummaries()); 413314564Sdim auto iter = map.find(class_name), end = map.end(); 414314564Sdim if (iter != end) 415314564Sdim return iter->second(valobj, stream, options); 416292932Sdim else 417314564Sdim return false; 418314564Sdim } 419292932Sdim 420314564Sdim std::string prefix, suffix; 421314564Sdim if (Language *language = Language::FindPlugin(options.GetLanguage())) { 422314564Sdim if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, 423314564Sdim suffix)) { 424314564Sdim prefix.clear(); 425314564Sdim suffix.clear(); 426292932Sdim } 427314564Sdim } 428292932Sdim 429314564Sdim stream.Printf("%s%" PRIu64 " %s%s%s", prefix.c_str(), value, "element", 430314564Sdim value == 1 ? "" : "s", suffix.c_str()); 431314564Sdim return true; 432292932Sdim} 433292932Sdim 434327952Sdimlldb_private::formatters::NSArrayMSyntheticFrontEndBase::NSArrayMSyntheticFrontEndBase( 435314564Sdim lldb::ValueObjectSP valobj_sp) 436314564Sdim : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), 437314564Sdim m_id_type() { 438314564Sdim if (valobj_sp) { 439360784Sdim auto *clang_ast_context = ClangASTContext::GetScratch( 440360784Sdim *valobj_sp->GetExecutionContextRef().GetTargetSP()); 441360784Sdim if (clang_ast_context) 442360784Sdim m_id_type = CompilerType( 443360784Sdim clang_ast_context, 444360784Sdim clang_ast_context->getASTContext().ObjCBuiltinIdTy.getAsOpaquePtr()); 445314564Sdim if (valobj_sp->GetProcessSP()) 446314564Sdim m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize(); 447314564Sdim } 448292932Sdim} 449292932Sdim 450327952Sdimtemplate <typename D32, typename D64> 451327952Sdimlldb_private::formatters:: 452327952Sdim GenericNSArrayMSyntheticFrontEnd<D32, D64>:: 453327952Sdim GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) 454327952Sdim : NSArrayMSyntheticFrontEndBase(valobj_sp), m_data_32(nullptr), 455314564Sdim m_data_64(nullptr) {} 456314564Sdim 457292932Sdimsize_t 458327952Sdimlldb_private::formatters::NSArrayMSyntheticFrontEndBase::CalculateNumChildren() { 459314564Sdim return GetUsedCount(); 460292932Sdim} 461292932Sdim 462292932Sdimlldb::ValueObjectSP 463327952Sdimlldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetChildAtIndex( 464314564Sdim size_t idx) { 465314564Sdim if (idx >= CalculateNumChildren()) 466314564Sdim return lldb::ValueObjectSP(); 467314564Sdim lldb::addr_t object_at_idx = GetDataAddress(); 468314564Sdim size_t pyhs_idx = idx; 469314564Sdim pyhs_idx += GetOffset(); 470314564Sdim if (GetSize() <= pyhs_idx) 471314564Sdim pyhs_idx -= GetSize(); 472314564Sdim object_at_idx += (pyhs_idx * m_ptr_size); 473314564Sdim StreamString idx_name; 474314564Sdim idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 475314564Sdim return CreateValueObjectFromAddress(idx_name.GetString(), object_at_idx, 476314564Sdim m_exe_ctx_ref, m_id_type); 477292932Sdim} 478292932Sdim 479327952Sdimtemplate <typename D32, typename D64> 480327952Sdimbool 481327952Sdimlldb_private::formatters:: 482327952Sdim GenericNSArrayMSyntheticFrontEnd<D32, D64>::Update() { 483314564Sdim ValueObjectSP valobj_sp = m_backend.GetSP(); 484314564Sdim m_ptr_size = 0; 485314564Sdim delete m_data_32; 486314564Sdim m_data_32 = nullptr; 487314564Sdim delete m_data_64; 488314564Sdim m_data_64 = nullptr; 489314564Sdim if (!valobj_sp) 490292932Sdim return false; 491314564Sdim m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 492321369Sdim Status error; 493314564Sdim error.Clear(); 494314564Sdim lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 495314564Sdim if (!process_sp) 496314564Sdim return false; 497314564Sdim m_ptr_size = process_sp->GetAddressByteSize(); 498314564Sdim uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 499314564Sdim if (m_ptr_size == 4) { 500327952Sdim m_data_32 = new D32(); 501327952Sdim process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), 502314564Sdim error); 503314564Sdim } else { 504327952Sdim m_data_64 = new D64(); 505327952Sdim process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), 506314564Sdim error); 507314564Sdim } 508314564Sdim if (error.Fail()) 509314564Sdim return false; 510314564Sdim return false; 511292932Sdim} 512292932Sdim 513327952Sdimbool 514327952Sdimlldb_private::formatters::NSArrayMSyntheticFrontEndBase::MightHaveChildren() { 515314564Sdim return true; 516292932Sdim} 517292932Sdim 518292932Sdimsize_t 519327952Sdimlldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetIndexOfChildWithName( 520353358Sdim ConstString name) { 521314564Sdim const char *item_name = name.GetCString(); 522314564Sdim uint32_t idx = ExtractIndexFromString(item_name); 523314564Sdim if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 524314564Sdim return UINT32_MAX; 525314564Sdim return idx; 526292932Sdim} 527292932Sdim 528327952Sdimtemplate <typename D32, typename D64> 529327952Sdimlldb_private::formatters:: 530327952Sdim GenericNSArrayMSyntheticFrontEnd<D32, D64>:: 531327952Sdim ~GenericNSArrayMSyntheticFrontEnd() { 532314564Sdim delete m_data_32; 533314564Sdim m_data_32 = nullptr; 534314564Sdim delete m_data_64; 535314564Sdim m_data_64 = nullptr; 536292932Sdim} 537292932Sdim 538327952Sdimtemplate <typename D32, typename D64> 539292932Sdimlldb::addr_t 540327952Sdimlldb_private::formatters:: 541327952Sdim GenericNSArrayMSyntheticFrontEnd<D32, D64>:: 542327952Sdim GenericNSArrayMSyntheticFrontEnd::GetDataAddress() { 543314564Sdim if (!m_data_32 && !m_data_64) 544314564Sdim return LLDB_INVALID_ADDRESS; 545314564Sdim return m_data_32 ? m_data_32->_data : m_data_64->_data; 546292932Sdim} 547292932Sdim 548327952Sdimtemplate <typename D32, typename D64> 549292932Sdimuint64_t 550327952Sdimlldb_private::formatters:: 551327952Sdim GenericNSArrayMSyntheticFrontEnd<D32, D64>:: 552327952Sdim GenericNSArrayMSyntheticFrontEnd::GetUsedCount() { 553314564Sdim if (!m_data_32 && !m_data_64) 554314564Sdim return 0; 555314564Sdim return m_data_32 ? m_data_32->_used : m_data_64->_used; 556292932Sdim} 557292932Sdim 558327952Sdimtemplate <typename D32, typename D64> 559327952Sdimuint64_t 560327952Sdimlldb_private::formatters:: 561327952Sdim GenericNSArrayMSyntheticFrontEnd<D32, D64>:: 562327952Sdim GenericNSArrayMSyntheticFrontEnd::GetOffset() { 563314564Sdim if (!m_data_32 && !m_data_64) 564314564Sdim return 0; 565314564Sdim return m_data_32 ? m_data_32->_offset : m_data_64->_offset; 566292932Sdim} 567292932Sdim 568327952Sdimtemplate <typename D32, typename D64> 569292932Sdimuint64_t 570327952Sdimlldb_private::formatters:: 571327952Sdim GenericNSArrayMSyntheticFrontEnd<D32, D64>:: 572327952Sdim GenericNSArrayMSyntheticFrontEnd::GetSize() { 573314564Sdim if (!m_data_32 && !m_data_64) 574314564Sdim return 0; 575314564Sdim return m_data_32 ? m_data_32->_size : m_data_64->_size; 576292932Sdim} 577292932Sdim 578327952Sdimtemplate <typename D32, typename D64, bool Inline> 579327952Sdimlldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: 580327952Sdim GenericNSArrayISyntheticFrontEnd( 581314564Sdim lldb::ValueObjectSP valobj_sp) 582314564Sdim : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), 583321369Sdim m_data_32(nullptr), m_data_64(nullptr) { 584321369Sdim if (valobj_sp) { 585321369Sdim CompilerType type = valobj_sp->GetCompilerType(); 586321369Sdim if (type) { 587360784Sdim auto *clang_ast_context = ClangASTContext::GetScratch( 588360784Sdim *valobj_sp->GetExecutionContextRef().GetTargetSP()); 589360784Sdim if (clang_ast_context) 590360784Sdim m_id_type = clang_ast_context->GetType( 591360784Sdim clang_ast_context->getASTContext().ObjCBuiltinIdTy); 592321369Sdim } 593321369Sdim } 594321369Sdim} 595321369Sdim 596327952Sdimtemplate <typename D32, typename D64, bool Inline> 597327952Sdimlldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: 598327952Sdim ~GenericNSArrayISyntheticFrontEnd() { 599321369Sdim delete m_data_32; 600321369Sdim m_data_32 = nullptr; 601321369Sdim delete m_data_64; 602321369Sdim m_data_64 = nullptr; 603321369Sdim} 604321369Sdim 605327952Sdimtemplate <typename D32, typename D64, bool Inline> 606321369Sdimsize_t 607327952Sdimlldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: 608353358Sdim GetIndexOfChildWithName(ConstString name) { 609321369Sdim const char *item_name = name.GetCString(); 610321369Sdim uint32_t idx = ExtractIndexFromString(item_name); 611321369Sdim if (idx < UINT32_MAX && idx >= CalculateNumChildren()) 612321369Sdim return UINT32_MAX; 613321369Sdim return idx; 614321369Sdim} 615321369Sdim 616327952Sdimtemplate <typename D32, typename D64, bool Inline> 617321369Sdimsize_t 618327952Sdimlldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: 619327952Sdim CalculateNumChildren() { 620321369Sdim return m_data_32 ? m_data_32->used : m_data_64->used; 621321369Sdim} 622321369Sdim 623327952Sdimtemplate <typename D32, typename D64, bool Inline> 624327952Sdimbool 625327952Sdimlldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: 626327952Sdim Update() { 627321369Sdim ValueObjectSP valobj_sp = m_backend.GetSP(); 628321369Sdim m_ptr_size = 0; 629321369Sdim delete m_data_32; 630321369Sdim m_data_32 = nullptr; 631321369Sdim delete m_data_64; 632321369Sdim m_data_64 = nullptr; 633321369Sdim if (!valobj_sp) 634321369Sdim return false; 635321369Sdim m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); 636321369Sdim Status error; 637321369Sdim error.Clear(); 638321369Sdim lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 639321369Sdim if (!process_sp) 640321369Sdim return false; 641321369Sdim m_ptr_size = process_sp->GetAddressByteSize(); 642321369Sdim uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; 643321369Sdim if (m_ptr_size == 4) { 644327952Sdim m_data_32 = new D32(); 645327952Sdim process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), 646321369Sdim error); 647321369Sdim } else { 648327952Sdim m_data_64 = new D64(); 649327952Sdim process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), 650321369Sdim error); 651321369Sdim } 652321369Sdim if (error.Fail()) 653321369Sdim return false; 654321369Sdim return false; 655321369Sdim} 656321369Sdim 657327952Sdimtemplate <typename D32, typename D64, bool Inline> 658327952Sdimbool 659327952Sdimlldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: 660327952Sdim MightHaveChildren() { 661321369Sdim return true; 662321369Sdim} 663321369Sdim 664327952Sdimtemplate <typename D32, typename D64, bool Inline> 665321369Sdimlldb::ValueObjectSP 666327952Sdimlldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: 667327952Sdim GetChildAtIndex(size_t idx) { 668321369Sdim if (idx >= CalculateNumChildren()) 669321369Sdim return lldb::ValueObjectSP(); 670327952Sdim lldb::addr_t object_at_idx; 671327952Sdim if (Inline) { 672327952Sdim object_at_idx = m_backend.GetSP()->GetValueAsUnsigned(0) + m_ptr_size; 673327952Sdim object_at_idx += m_ptr_size == 4 ? sizeof(D32) : sizeof(D64); // skip the data header 674327952Sdim object_at_idx -= m_ptr_size; // we treat the last entry in the data header as the first pointer 675327952Sdim } else { 676327952Sdim object_at_idx = m_data_32 ? m_data_32->list : m_data_64->list; 677327952Sdim } 678321369Sdim object_at_idx += (idx * m_ptr_size); 679327952Sdim 680321369Sdim ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); 681321369Sdim if (!process_sp) 682321369Sdim return lldb::ValueObjectSP(); 683321369Sdim Status error; 684321369Sdim if (error.Fail()) 685321369Sdim return lldb::ValueObjectSP(); 686321369Sdim StreamString idx_name; 687321369Sdim idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); 688321369Sdim return CreateValueObjectFromAddress(idx_name.GetString(), object_at_idx, 689321369Sdim m_exe_ctx_ref, m_id_type); 690321369Sdim} 691321369Sdim 692314564Sdimlldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd( 693314564Sdim lldb::ValueObjectSP valobj_sp) 694314564Sdim : SyntheticChildrenFrontEnd(*valobj_sp) {} 695292932Sdim 696292932Sdimsize_t 697314564Sdimlldb_private::formatters::NSArray0SyntheticFrontEnd::GetIndexOfChildWithName( 698353358Sdim ConstString name) { 699314564Sdim return UINT32_MAX; 700292932Sdim} 701292932Sdim 702292932Sdimsize_t 703314564Sdimlldb_private::formatters::NSArray0SyntheticFrontEnd::CalculateNumChildren() { 704314564Sdim return 0; 705292932Sdim} 706292932Sdim 707314564Sdimbool lldb_private::formatters::NSArray0SyntheticFrontEnd::Update() { 708314564Sdim return false; 709292932Sdim} 710292932Sdim 711314564Sdimbool lldb_private::formatters::NSArray0SyntheticFrontEnd::MightHaveChildren() { 712314564Sdim return false; 713292932Sdim} 714292932Sdim 715292932Sdimlldb::ValueObjectSP 716314564Sdimlldb_private::formatters::NSArray0SyntheticFrontEnd::GetChildAtIndex( 717314564Sdim size_t idx) { 718314564Sdim return lldb::ValueObjectSP(); 719292932Sdim} 720292932Sdim 721314564Sdimlldb_private::formatters::NSArray1SyntheticFrontEnd::NSArray1SyntheticFrontEnd( 722314564Sdim lldb::ValueObjectSP valobj_sp) 723314564Sdim : SyntheticChildrenFrontEnd(*valobj_sp.get()) {} 724309124Sdim 725309124Sdimsize_t 726314564Sdimlldb_private::formatters::NSArray1SyntheticFrontEnd::GetIndexOfChildWithName( 727353358Sdim ConstString name) { 728314564Sdim static const ConstString g_zero("[0]"); 729314564Sdim 730314564Sdim if (name == g_zero) 731314564Sdim return 0; 732314564Sdim 733314564Sdim return UINT32_MAX; 734309124Sdim} 735309124Sdim 736309124Sdimsize_t 737314564Sdimlldb_private::formatters::NSArray1SyntheticFrontEnd::CalculateNumChildren() { 738314564Sdim return 1; 739309124Sdim} 740309124Sdim 741314564Sdimbool lldb_private::formatters::NSArray1SyntheticFrontEnd::Update() { 742314564Sdim return false; 743309124Sdim} 744309124Sdim 745314564Sdimbool lldb_private::formatters::NSArray1SyntheticFrontEnd::MightHaveChildren() { 746314564Sdim return true; 747309124Sdim} 748309124Sdim 749309124Sdimlldb::ValueObjectSP 750314564Sdimlldb_private::formatters::NSArray1SyntheticFrontEnd::GetChildAtIndex( 751314564Sdim size_t idx) { 752314564Sdim static const ConstString g_zero("[0]"); 753314564Sdim 754314564Sdim if (idx == 0) { 755360784Sdim auto *clang_ast_context = 756360784Sdim ClangASTContext::GetScratch(*m_backend.GetTargetSP()); 757360784Sdim if (clang_ast_context) { 758360784Sdim CompilerType id_type( 759360784Sdim clang_ast_context->GetBasicType(lldb::eBasicTypeObjCID)); 760360784Sdim return m_backend.GetSyntheticChildAtOffset( 761360784Sdim m_backend.GetProcessSP()->GetAddressByteSize(), id_type, true, 762360784Sdim g_zero); 763360784Sdim } 764314564Sdim } 765314564Sdim return lldb::ValueObjectSP(); 766309124Sdim} 767309124Sdim 768314564SdimSyntheticChildrenFrontEnd * 769314564Sdimlldb_private::formatters::NSArraySyntheticFrontEndCreator( 770314564Sdim CXXSyntheticChildren *synth, lldb::ValueObjectSP valobj_sp) { 771314564Sdim if (!valobj_sp) 772314564Sdim return nullptr; 773314564Sdim 774314564Sdim lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); 775314564Sdim if (!process_sp) 776314564Sdim return nullptr; 777314564Sdim AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>( 778353358Sdim ObjCLanguageRuntime::Get(*process_sp)); 779314564Sdim if (!runtime) 780314564Sdim return nullptr; 781314564Sdim 782314564Sdim CompilerType valobj_type(valobj_sp->GetCompilerType()); 783314564Sdim Flags flags(valobj_type.GetTypeInfo()); 784314564Sdim 785314564Sdim if (flags.IsClear(eTypeIsPointer)) { 786321369Sdim Status error; 787314564Sdim valobj_sp = valobj_sp->AddressOf(error); 788314564Sdim if (error.Fail() || !valobj_sp) 789314564Sdim return nullptr; 790314564Sdim } 791314564Sdim 792314564Sdim ObjCLanguageRuntime::ClassDescriptorSP descriptor( 793314564Sdim runtime->GetClassDescriptor(*valobj_sp)); 794314564Sdim 795314564Sdim if (!descriptor || !descriptor->IsValid()) 796314564Sdim return nullptr; 797314564Sdim 798314564Sdim ConstString class_name(descriptor->GetClassName()); 799314564Sdim 800314564Sdim static const ConstString g_NSArrayI("__NSArrayI"); 801327952Sdim static const ConstString g_NSArrayI_Transfer("__NSArrayI_Transfer"); 802327952Sdim static const ConstString g_NSFrozenArrayM("__NSFrozenArrayM"); 803314564Sdim static const ConstString g_NSArrayM("__NSArrayM"); 804314564Sdim static const ConstString g_NSArray0("__NSArray0"); 805314564Sdim static const ConstString g_NSArray1("__NSSingleObjectArrayI"); 806321369Sdim static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy"); 807321369Sdim static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable"); 808344779Sdim static const ConstString g_NSCallStackArray("_NSCallStackArray"); 809314564Sdim 810314564Sdim if (class_name.IsEmpty()) 811314564Sdim return nullptr; 812314564Sdim 813314564Sdim if (class_name == g_NSArrayI) { 814327952Sdim if (runtime->GetFoundationVersion() >= 1436) 815327952Sdim return (new Foundation1436::NSArrayISyntheticFrontEnd(valobj_sp)); 816327952Sdim if (runtime->GetFoundationVersion() >= 1430) 817327952Sdim return (new Foundation1430::NSArrayISyntheticFrontEnd(valobj_sp)); 818327952Sdim else 819327952Sdim return (new Foundation1300::NSArrayISyntheticFrontEnd(valobj_sp)); 820327952Sdim } else if (class_name == g_NSArrayI_Transfer) { 821327952Sdim return (new Foundation1436::NSArrayI_TransferSyntheticFrontEnd(valobj_sp)); 822314564Sdim } else if (class_name == g_NSArray0) { 823327952Sdim } else if (class_name == g_NSFrozenArrayM) { 824327952Sdim return (new Foundation1436::NSFrozenArrayMSyntheticFrontEnd(valobj_sp)); 825327952Sdim } else if (class_name == g_NSArray0) { 826314564Sdim return (new NSArray0SyntheticFrontEnd(valobj_sp)); 827314564Sdim } else if (class_name == g_NSArray1) { 828314564Sdim return (new NSArray1SyntheticFrontEnd(valobj_sp)); 829314564Sdim } else if (class_name == g_NSArrayM) { 830327952Sdim if (runtime->GetFoundationVersion() >= 1437) 831327952Sdim return (new Foundation1437::NSArrayMSyntheticFrontEnd(valobj_sp)); 832327952Sdim if (runtime->GetFoundationVersion() >= 1428) 833327952Sdim return (new Foundation1428::NSArrayMSyntheticFrontEnd(valobj_sp)); 834314564Sdim if (runtime->GetFoundationVersion() >= 1100) 835327952Sdim return (new Foundation1010::NSArrayMSyntheticFrontEnd(valobj_sp)); 836344779Sdim } else if (class_name == g_NSCallStackArray) { 837344779Sdim return (new CallStackArray::NSCallStackArraySyntheticFrontEnd(valobj_sp)); 838314564Sdim } else { 839314564Sdim auto &map(NSArray_Additionals::GetAdditionalSynthetics()); 840314564Sdim auto iter = map.find(class_name), end = map.end(); 841314564Sdim if (iter != end) 842314564Sdim return iter->second(synth, valobj_sp); 843314564Sdim } 844314564Sdim 845314564Sdim return nullptr; 846292932Sdim} 847