Loading lldb/include/lldb/DataFormatters/CXXFormatterFunctions.h +2 −0 Original line number Diff line number Diff line Loading @@ -474,6 +474,8 @@ namespace lldb_private { SyntheticChildrenFrontEnd* NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); class LibcxxVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: Loading lldb/lldb.xcodeproj/project.pbxproj +4 −0 Original line number Diff line number Diff line Loading @@ -648,6 +648,7 @@ 941BCC8114E48C4000BB969C /* SBTypeSummary.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568814E355F2003A195C /* SBTypeSummary.h */; settings = {ATTRIBUTES = (Public, ); }; }; 941BCC8214E48C4000BB969C /* SBTypeSynthetic.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568914E355F2003A195C /* SBTypeSynthetic.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94380B8219940B0A00BFE4A8 /* StringLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94380B8119940B0A00BFE4A8 /* StringLexer.cpp */; }; 9439FB1A19EF140C006FD6A4 /* NSIndexPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9439FB1919EF140C006FD6A4 /* NSIndexPath.cpp */; }; 944372DC171F6B4300E57C32 /* RegisterContextDummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 944372DA171F6B4300E57C32 /* RegisterContextDummy.cpp */; }; 944372DD171F6B4300E57C32 /* RegisterContextDummy.h in Headers */ = {isa = PBXBuildFile; fileRef = 944372DB171F6B4300E57C32 /* RegisterContextDummy.h */; }; 9443B122140C18C40013457C /* SBData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9443B121140C18C10013457C /* SBData.cpp */; }; Loading Loading @@ -1985,6 +1986,7 @@ 94145430175D7FDE00284436 /* lldb-versioning.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-versioning.h"; path = "include/lldb/lldb-versioning.h"; sourceTree = "<group>"; }; 94380B8019940B0300BFE4A8 /* StringLexer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StringLexer.h; path = include/lldb/Utility/StringLexer.h; sourceTree = "<group>"; }; 94380B8119940B0A00BFE4A8 /* StringLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringLexer.cpp; path = source/Utility/StringLexer.cpp; sourceTree = "<group>"; }; 9439FB1919EF140C006FD6A4 /* NSIndexPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSIndexPath.cpp; path = source/DataFormatters/NSIndexPath.cpp; sourceTree = "<group>"; }; 944372DA171F6B4300E57C32 /* RegisterContextDummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextDummy.cpp; path = Utility/RegisterContextDummy.cpp; sourceTree = "<group>"; }; 944372DB171F6B4300E57C32 /* RegisterContextDummy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextDummy.h; path = Utility/RegisterContextDummy.h; sourceTree = "<group>"; }; 9443B120140C18A90013457C /* SBData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBData.h; path = include/lldb/API/SBData.h; sourceTree = "<group>"; }; Loading Loading @@ -4327,6 +4329,7 @@ 94D0B10B16D5535900EA9C70 /* LibStdcpp.cpp */, 94D6A0A716CEB55F00833B6E /* NSArray.cpp */, 94D6A0A816CEB55F00833B6E /* NSDictionary.cpp */, 9439FB1919EF140C006FD6A4 /* NSIndexPath.cpp */, 94D6A0A916CEB55F00833B6E /* NSSet.cpp */, 94CB256816B096F90059775D /* TypeCategory.h */, 94CB256416B096F10059775D /* TypeCategory.cpp */, Loading Loading @@ -5079,6 +5082,7 @@ 94D0B10D16D5535900EA9C70 /* LibStdcpp.cpp in Sources */, AF0E22F018A09FB20009B7D1 /* AppleGetItemInfoHandler.cpp in Sources */, 2689004E13353E0400698AC0 /* Stream.cpp in Sources */, 9439FB1A19EF140C006FD6A4 /* NSIndexPath.cpp in Sources */, 2689004F13353E0400698AC0 /* StreamFile.cpp in Sources */, 2689005013353E0400698AC0 /* StreamString.cpp in Sources */, 2689005113353E0400698AC0 /* StringList.cpp in Sources */, lldb/source/Core/ValueObjectConstResult.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope { m_value = value; m_value.GetData(m_data); m_name = name; } ValueObjectConstResult::~ValueObjectConstResult() Loading lldb/source/DataFormatters/FormatManager.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -1395,6 +1395,8 @@ FormatManager::LoadObjCFormatters() AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), ScriptedSyntheticChildren::Flags()); AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), ScriptedSyntheticChildren::Flags()); AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, "NSIndexPath synthetic children", ConstString("NSIndexPath"), ScriptedSyntheticChildren::Flags()); AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFBagRef"), appkit_flags); AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("__CFBag"), appkit_flags); AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("const struct __CFBag"), appkit_flags); Loading lldb/source/DataFormatters/NSIndexPath.cpp 0 → 100644 +306 −0 Original line number Diff line number Diff line //===-- NSIndexPath.cpp ------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/DataFormatters/CXXFormatterFunctions.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/DataFormatters/TypeSynthetic.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Symbol/ClangASTContext.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd (*valobj_sp.get()), m_ptr_size(0), m_ast_ctx(nullptr), m_uint_star_type() { m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize(); } virtual size_t CalculateNumChildren () { return m_impl.GetNumIndexes(); } virtual lldb::ValueObjectSP GetChildAtIndex (size_t idx) { return m_impl.GetIndexAtIndex(idx, m_uint_star_type); } virtual bool Update() { m_impl.m_mode = Mode::Invalid; m_ast_ctx = ClangASTContext::GetASTContext(m_backend.GetClangType().GetASTContext()); if (!m_ast_ctx) return false; m_uint_star_type = m_ast_ctx->GetPointerSizedIntType(false); static ConstString g__indexes("_indexes"); static ConstString g__length("_length"); ProcessSP process_sp = m_backend.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(m_backend)); if (!descriptor.get() || !descriptor->IsValid()) return false; uint64_t info_bits(0),value_bits(0),payload(0); if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload)) { m_impl.m_mode = Mode::Inlined; m_impl.m_inlined.SetIndexes(payload, *process_sp); } else { ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id; ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id; bool has_indexes(false),has_length(false); for (auto x = 0; x < descriptor->GetNumIVars(); x++) { const auto& ivar = descriptor->GetIVarAtIndex(x); if (ivar.m_name == g__indexes) { _indexes_id = ivar; has_indexes = true; } else if (ivar.m_name == g__length) { _length_id = ivar; has_length = true; } if (has_length && has_indexes) break; } if (has_length && has_indexes) { m_impl.m_outsourced.m_indexes = m_backend.GetSyntheticChildAtOffset(_indexes_id.m_offset, m_uint_star_type.GetPointerType(), true).get(); ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(_length_id.m_offset, m_uint_star_type, true)); if (length_sp) { m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0); if (m_impl.m_outsourced.m_indexes) m_impl.m_mode = Mode::Outsourced; } } } return false; } virtual bool MightHaveChildren () { if (m_impl.m_mode == Mode::Invalid) return false; return true; } virtual size_t GetIndexOfChildWithName (const ConstString &name) { const char* item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); if (idx < UINT32_MAX && idx >= CalculateNumChildren()) return UINT32_MAX; return idx; } virtual lldb::ValueObjectSP GetSyntheticValue () { return nullptr; } virtual ~NSIndexPathSyntheticFrontEnd () {} protected: ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp; enum class Mode { Inlined, Outsourced, Invalid }; struct Impl { Mode m_mode; size_t GetNumIndexes () { switch (m_mode) { case Mode::Inlined: return m_inlined.GetNumIndexes(); case Mode::Outsourced: return m_outsourced.m_count; default: return 0; } } lldb::ValueObjectSP GetIndexAtIndex (size_t idx, const ClangASTType& desired_type) { if (idx >= GetNumIndexes()) return nullptr; switch (m_mode) { default: return nullptr; case Mode::Inlined: return m_inlined.GetIndexAtIndex (idx, desired_type); case Mode::Outsourced: return m_outsourced.GetIndexAtIndex (idx); } } union { struct { public: void SetIndexes(uint64_t value, Process& p) { m_indexes = value; _lengthForInlinePayload(p.GetAddressByteSize()); m_process = &p; } size_t GetNumIndexes () { return m_count; } lldb::ValueObjectSP GetIndexAtIndex (size_t idx, const ClangASTType& desired_type) { std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx)); if (!value.second) return nullptr; Value v; if (m_ptr_size == 8) { Scalar scalar( (unsigned long long)value.first ); v = Value(scalar); } else { Scalar scalar( (unsigned int)value.first ); v = Value(scalar); } v.SetClangType(desired_type); StreamString idx_name; idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData())); } private: uint64_t m_indexes; size_t m_count; uint32_t m_ptr_size; Process *m_process; // cfr. Foundation for the details of this code size_t _lengthForInlinePayload(uint32_t ptr_size) { m_ptr_size = ptr_size; if (m_ptr_size == 8) m_count = ((m_indexes >> 3) & 0x7); else m_count = ((m_indexes >> 3) & 0x3); return m_count; } std::pair<uint64_t, bool> _indexAtPositionForInlinePayload(size_t pos) { if (m_ptr_size == 8) { switch (pos) { case 5: return {((m_indexes >> 51) & 0x1ff),true}; case 4: return {((m_indexes >> 42) & 0x1ff),true}; case 3: return {((m_indexes >> 33) & 0x1ff),true}; case 2: return {((m_indexes >> 24) & 0x1ff),true}; case 1: return {((m_indexes >> 15) & 0x1ff),true}; case 0: return {((m_indexes >> 6) & 0x1ff),true}; } } else { switch (pos) { case 2: return {((m_indexes >> 23) & 0x1ff),true}; case 1: return {((m_indexes >> 14) & 0x1ff),true}; case 0: return {((m_indexes >> 5) & 0x1ff),true}; } } return {0,false}; } } m_inlined; struct { ValueObject *m_indexes; size_t m_count; lldb::ValueObjectSP GetIndexAtIndex (size_t idx) { if (m_indexes) { ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMemberFromPointer(idx, true)); return index_sp; } return nullptr; } } m_outsourced; }; } m_impl; uint32_t m_ptr_size; ClangASTContext* m_ast_ctx; ClangASTType m_uint_star_type; }; namespace lldb_private { namespace formatters { SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) { if (valobj_sp) return new NSIndexPathSyntheticFrontEnd(valobj_sp); return nullptr; } } } Loading
lldb/include/lldb/DataFormatters/CXXFormatterFunctions.h +2 −0 Original line number Diff line number Diff line Loading @@ -474,6 +474,8 @@ namespace lldb_private { SyntheticChildrenFrontEnd* NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); class LibcxxVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: Loading
lldb/lldb.xcodeproj/project.pbxproj +4 −0 Original line number Diff line number Diff line Loading @@ -648,6 +648,7 @@ 941BCC8114E48C4000BB969C /* SBTypeSummary.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568814E355F2003A195C /* SBTypeSummary.h */; settings = {ATTRIBUTES = (Public, ); }; }; 941BCC8214E48C4000BB969C /* SBTypeSynthetic.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568914E355F2003A195C /* SBTypeSynthetic.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94380B8219940B0A00BFE4A8 /* StringLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94380B8119940B0A00BFE4A8 /* StringLexer.cpp */; }; 9439FB1A19EF140C006FD6A4 /* NSIndexPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9439FB1919EF140C006FD6A4 /* NSIndexPath.cpp */; }; 944372DC171F6B4300E57C32 /* RegisterContextDummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 944372DA171F6B4300E57C32 /* RegisterContextDummy.cpp */; }; 944372DD171F6B4300E57C32 /* RegisterContextDummy.h in Headers */ = {isa = PBXBuildFile; fileRef = 944372DB171F6B4300E57C32 /* RegisterContextDummy.h */; }; 9443B122140C18C40013457C /* SBData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9443B121140C18C10013457C /* SBData.cpp */; }; Loading Loading @@ -1985,6 +1986,7 @@ 94145430175D7FDE00284436 /* lldb-versioning.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-versioning.h"; path = "include/lldb/lldb-versioning.h"; sourceTree = "<group>"; }; 94380B8019940B0300BFE4A8 /* StringLexer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StringLexer.h; path = include/lldb/Utility/StringLexer.h; sourceTree = "<group>"; }; 94380B8119940B0A00BFE4A8 /* StringLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringLexer.cpp; path = source/Utility/StringLexer.cpp; sourceTree = "<group>"; }; 9439FB1919EF140C006FD6A4 /* NSIndexPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSIndexPath.cpp; path = source/DataFormatters/NSIndexPath.cpp; sourceTree = "<group>"; }; 944372DA171F6B4300E57C32 /* RegisterContextDummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextDummy.cpp; path = Utility/RegisterContextDummy.cpp; sourceTree = "<group>"; }; 944372DB171F6B4300E57C32 /* RegisterContextDummy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextDummy.h; path = Utility/RegisterContextDummy.h; sourceTree = "<group>"; }; 9443B120140C18A90013457C /* SBData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBData.h; path = include/lldb/API/SBData.h; sourceTree = "<group>"; }; Loading Loading @@ -4327,6 +4329,7 @@ 94D0B10B16D5535900EA9C70 /* LibStdcpp.cpp */, 94D6A0A716CEB55F00833B6E /* NSArray.cpp */, 94D6A0A816CEB55F00833B6E /* NSDictionary.cpp */, 9439FB1919EF140C006FD6A4 /* NSIndexPath.cpp */, 94D6A0A916CEB55F00833B6E /* NSSet.cpp */, 94CB256816B096F90059775D /* TypeCategory.h */, 94CB256416B096F10059775D /* TypeCategory.cpp */, Loading Loading @@ -5079,6 +5082,7 @@ 94D0B10D16D5535900EA9C70 /* LibStdcpp.cpp in Sources */, AF0E22F018A09FB20009B7D1 /* AppleGetItemInfoHandler.cpp in Sources */, 2689004E13353E0400698AC0 /* Stream.cpp in Sources */, 9439FB1A19EF140C006FD6A4 /* NSIndexPath.cpp in Sources */, 2689004F13353E0400698AC0 /* StreamFile.cpp in Sources */, 2689005013353E0400698AC0 /* StreamString.cpp in Sources */, 2689005113353E0400698AC0 /* StringList.cpp in Sources */,
lldb/source/Core/ValueObjectConstResult.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope { m_value = value; m_value.GetData(m_data); m_name = name; } ValueObjectConstResult::~ValueObjectConstResult() Loading
lldb/source/DataFormatters/FormatManager.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -1395,6 +1395,8 @@ FormatManager::LoadObjCFormatters() AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), ScriptedSyntheticChildren::Flags()); AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), ScriptedSyntheticChildren::Flags()); AddCXXSynthetic(appkit_category_sp, lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, "NSIndexPath synthetic children", ConstString("NSIndexPath"), ScriptedSyntheticChildren::Flags()); AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFBagRef"), appkit_flags); AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("__CFBag"), appkit_flags); AddCXXSummary(corefoundation_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("const struct __CFBag"), appkit_flags); Loading
lldb/source/DataFormatters/NSIndexPath.cpp 0 → 100644 +306 −0 Original line number Diff line number Diff line //===-- NSIndexPath.cpp ------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/DataFormatters/CXXFormatterFunctions.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/DataFormatters/TypeSynthetic.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Symbol/ClangASTContext.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd (*valobj_sp.get()), m_ptr_size(0), m_ast_ctx(nullptr), m_uint_star_type() { m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize(); } virtual size_t CalculateNumChildren () { return m_impl.GetNumIndexes(); } virtual lldb::ValueObjectSP GetChildAtIndex (size_t idx) { return m_impl.GetIndexAtIndex(idx, m_uint_star_type); } virtual bool Update() { m_impl.m_mode = Mode::Invalid; m_ast_ctx = ClangASTContext::GetASTContext(m_backend.GetClangType().GetASTContext()); if (!m_ast_ctx) return false; m_uint_star_type = m_ast_ctx->GetPointerSizedIntType(false); static ConstString g__indexes("_indexes"); static ConstString g__length("_length"); ProcessSP process_sp = m_backend.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(m_backend)); if (!descriptor.get() || !descriptor->IsValid()) return false; uint64_t info_bits(0),value_bits(0),payload(0); if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload)) { m_impl.m_mode = Mode::Inlined; m_impl.m_inlined.SetIndexes(payload, *process_sp); } else { ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id; ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id; bool has_indexes(false),has_length(false); for (auto x = 0; x < descriptor->GetNumIVars(); x++) { const auto& ivar = descriptor->GetIVarAtIndex(x); if (ivar.m_name == g__indexes) { _indexes_id = ivar; has_indexes = true; } else if (ivar.m_name == g__length) { _length_id = ivar; has_length = true; } if (has_length && has_indexes) break; } if (has_length && has_indexes) { m_impl.m_outsourced.m_indexes = m_backend.GetSyntheticChildAtOffset(_indexes_id.m_offset, m_uint_star_type.GetPointerType(), true).get(); ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(_length_id.m_offset, m_uint_star_type, true)); if (length_sp) { m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0); if (m_impl.m_outsourced.m_indexes) m_impl.m_mode = Mode::Outsourced; } } } return false; } virtual bool MightHaveChildren () { if (m_impl.m_mode == Mode::Invalid) return false; return true; } virtual size_t GetIndexOfChildWithName (const ConstString &name) { const char* item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); if (idx < UINT32_MAX && idx >= CalculateNumChildren()) return UINT32_MAX; return idx; } virtual lldb::ValueObjectSP GetSyntheticValue () { return nullptr; } virtual ~NSIndexPathSyntheticFrontEnd () {} protected: ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp; enum class Mode { Inlined, Outsourced, Invalid }; struct Impl { Mode m_mode; size_t GetNumIndexes () { switch (m_mode) { case Mode::Inlined: return m_inlined.GetNumIndexes(); case Mode::Outsourced: return m_outsourced.m_count; default: return 0; } } lldb::ValueObjectSP GetIndexAtIndex (size_t idx, const ClangASTType& desired_type) { if (idx >= GetNumIndexes()) return nullptr; switch (m_mode) { default: return nullptr; case Mode::Inlined: return m_inlined.GetIndexAtIndex (idx, desired_type); case Mode::Outsourced: return m_outsourced.GetIndexAtIndex (idx); } } union { struct { public: void SetIndexes(uint64_t value, Process& p) { m_indexes = value; _lengthForInlinePayload(p.GetAddressByteSize()); m_process = &p; } size_t GetNumIndexes () { return m_count; } lldb::ValueObjectSP GetIndexAtIndex (size_t idx, const ClangASTType& desired_type) { std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx)); if (!value.second) return nullptr; Value v; if (m_ptr_size == 8) { Scalar scalar( (unsigned long long)value.first ); v = Value(scalar); } else { Scalar scalar( (unsigned int)value.first ); v = Value(scalar); } v.SetClangType(desired_type); StreamString idx_name; idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData())); } private: uint64_t m_indexes; size_t m_count; uint32_t m_ptr_size; Process *m_process; // cfr. Foundation for the details of this code size_t _lengthForInlinePayload(uint32_t ptr_size) { m_ptr_size = ptr_size; if (m_ptr_size == 8) m_count = ((m_indexes >> 3) & 0x7); else m_count = ((m_indexes >> 3) & 0x3); return m_count; } std::pair<uint64_t, bool> _indexAtPositionForInlinePayload(size_t pos) { if (m_ptr_size == 8) { switch (pos) { case 5: return {((m_indexes >> 51) & 0x1ff),true}; case 4: return {((m_indexes >> 42) & 0x1ff),true}; case 3: return {((m_indexes >> 33) & 0x1ff),true}; case 2: return {((m_indexes >> 24) & 0x1ff),true}; case 1: return {((m_indexes >> 15) & 0x1ff),true}; case 0: return {((m_indexes >> 6) & 0x1ff),true}; } } else { switch (pos) { case 2: return {((m_indexes >> 23) & 0x1ff),true}; case 1: return {((m_indexes >> 14) & 0x1ff),true}; case 0: return {((m_indexes >> 5) & 0x1ff),true}; } } return {0,false}; } } m_inlined; struct { ValueObject *m_indexes; size_t m_count; lldb::ValueObjectSP GetIndexAtIndex (size_t idx) { if (m_indexes) { ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMemberFromPointer(idx, true)); return index_sp; } return nullptr; } } m_outsourced; }; } m_impl; uint32_t m_ptr_size; ClangASTContext* m_ast_ctx; ClangASTType m_uint_star_type; }; namespace lldb_private { namespace formatters { SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) { if (valobj_sp) return new NSIndexPathSyntheticFrontEnd(valobj_sp); return nullptr; } } }