diff options
Diffstat (limited to 'source/Plugins/Language')
-rw-r--r-- | source/Plugins/Language/ObjC/Cocoa.cpp | 116 | ||||
-rw-r--r-- | source/Plugins/Language/ObjC/NSArray.cpp | 280 | ||||
-rw-r--r-- | source/Plugins/Language/ObjC/NSDictionary.cpp | 230 | ||||
-rw-r--r-- | source/Plugins/Language/ObjC/ObjCLanguage.cpp | 5 |
4 files changed, 599 insertions, 32 deletions
diff --git a/source/Plugins/Language/ObjC/Cocoa.cpp b/source/Plugins/Language/ObjC/Cocoa.cpp index dd3dc434f753..6aaf66cbb486 100644 --- a/source/Plugins/Language/ObjC/Cocoa.cpp +++ b/source/Plugins/Language/ObjC/Cocoa.cpp @@ -31,6 +31,8 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" +#include "llvm/ADT/APInt.h" + #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" #include "NSString.h" @@ -369,6 +371,28 @@ static void NSNumber_FormatLong(ValueObject &valobj, Stream &stream, stream.Printf("%s%" PRId64 "%s", prefix.c_str(), value, suffix.c_str()); } +static void NSNumber_FormatInt128(ValueObject &valobj, Stream &stream, + const llvm::APInt &value, + lldb::LanguageType lang) { + static ConstString g_TypeHint("NSNumber:int128_t"); + + std::string prefix, suffix; + if (Language *language = Language::FindPlugin(lang)) { + if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, + suffix)) { + prefix.clear(); + suffix.clear(); + } + } + + stream.PutCString(prefix.c_str()); + const int radix = 10; + const bool isSigned = true; + std::string str = value.toString(radix, isSigned); + stream.PutCString(str.c_str()); + stream.PutCString(suffix.c_str()); +} + static void NSNumber_FormatFloat(ValueObject &valobj, Stream &stream, float value, lldb::LanguageType lang) { static ConstString g_TypeHint("NSNumber:float"); @@ -462,22 +486,72 @@ bool lldb_private::formatters::NSNumberSummaryProvider( return true; } else { Status error; - uint8_t data_type = (process_sp->ReadUnsignedIntegerFromMemory( - valobj_addr + ptr_size, 1, 0, error) & - 0x1F); + + AppleObjCRuntime *runtime = + llvm::dyn_cast_or_null<AppleObjCRuntime>( + process_sp->GetObjCLanguageRuntime()); + + const bool new_format = + (runtime && runtime->GetFoundationVersion() >= 1400); + + enum class TypeCodes : int { + sint8 = 0x0, + sint16 = 0x1, + sint32 = 0x2, + sint64 = 0x3, + f32 = 0x4, + f64 = 0x5, + sint128 = 0x6 + }; + uint64_t data_location = valobj_addr + 2 * ptr_size; + TypeCodes type_code; + + if (new_format) { + uint64_t cfinfoa = + process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + + if (error.Fail()) + return false; + + bool is_preserved_number = cfinfoa & 0x8; + if (is_preserved_number) { + lldbassert(!"We should handle preserved numbers!"); + return false; + } + + type_code = (TypeCodes)(cfinfoa & 0x7); + } else { + uint8_t data_type = + process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 1, + 0, error) & 0x1F; + + if (error.Fail()) + return false; + + switch (data_type) { + case 1: type_code = TypeCodes::sint8; break; + case 2: type_code = TypeCodes::sint16; break; + case 3: type_code = TypeCodes::sint32; break; + case 17: data_location += 8; LLVM_FALLTHROUGH; + case 4: type_code = TypeCodes::sint64; break; + case 5: type_code = TypeCodes::f32; break; + case 6: type_code = TypeCodes::f64; break; + default: return false; + } + } + uint64_t value = 0; - if (error.Fail()) - return false; - switch (data_type) { - case 1: // 0B00001 + switch (type_code) { + case TypeCodes::sint8: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0, error); if (error.Fail()) return false; NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage()); break; - case 2: // 0B0010 + case TypeCodes::sint16: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0, error); if (error.Fail()) @@ -485,24 +559,21 @@ bool lldb_private::formatters::NSNumberSummaryProvider( NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage()); break; - case 3: // 0B0011 + case TypeCodes::sint32: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error); if (error.Fail()) return false; NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage()); break; - case 17: // 0B10001 - data_location += 8; - LLVM_FALLTHROUGH; - case 4: // 0B0100 + case TypeCodes::sint64: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error); if (error.Fail()) return false; NSNumber_FormatLong(valobj, stream, value, options.GetLanguage()); break; - case 5: // 0B0101 + case TypeCodes::f32: { uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory( data_location, 4, 0, error); @@ -513,7 +584,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( NSNumber_FormatFloat(valobj, stream, flt_value, options.GetLanguage()); break; } - case 6: // 0B0110 + case TypeCodes::f64: { uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory( data_location, 8, 0, error); @@ -524,6 +595,21 @@ bool lldb_private::formatters::NSNumberSummaryProvider( NSNumber_FormatDouble(valobj, stream, dbl_value, options.GetLanguage()); break; } + case TypeCodes::sint128: // internally, this is the same + { + uint64_t words[2]; + words[1] = process_sp->ReadUnsignedIntegerFromMemory( + data_location, 8, 0, error); + if (error.Fail()) + return false; + words[0] = process_sp->ReadUnsignedIntegerFromMemory( + data_location + 8, 8, 0, error); + if (error.Fail()) + return false; + llvm::APInt i128_value(128, words); + NSNumber_FormatInt128(valobj, stream, i128_value, options.GetLanguage()); + break; + } default: return false; } diff --git a/source/Plugins/Language/ObjC/NSArray.cpp b/source/Plugins/Language/ObjC/NSArray.cpp index b07b9ba5888f..27cb9558c482 100644 --- a/source/Plugins/Language/ObjC/NSArray.cpp +++ b/source/Plugins/Language/ObjC/NSArray.cpp @@ -160,11 +160,47 @@ private: DataDescriptor_64 *m_data_64; }; -class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd { +class NSArrayMSyntheticFrontEnd_1400 : public NSArrayMSyntheticFrontEnd { public: - NSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + NSArrayMSyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp); - ~NSArrayISyntheticFrontEnd() override = default; + ~NSArrayMSyntheticFrontEnd_1400() override; + + bool Update() override; + +protected: + lldb::addr_t GetDataAddress() override; + + uint64_t GetUsedCount() override; + + uint64_t GetOffset() override; + + uint64_t GetSize() override; + +private: + struct DataDescriptor_32 { + uint32_t used; + uint32_t offset; + uint32_t size; + uint32_t list; + }; + + struct DataDescriptor_64 { + uint64_t used; + uint64_t offset; + uint64_t size; + uint64_t list; + }; + + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; +}; + +class NSArrayISyntheticFrontEnd_1300 : public SyntheticChildrenFrontEnd { +public: + NSArrayISyntheticFrontEnd_1300(lldb::ValueObjectSP valobj_sp); + + ~NSArrayISyntheticFrontEnd_1300() override = default; size_t CalculateNumChildren() override; @@ -184,6 +220,45 @@ private: CompilerType m_id_type; }; +class NSArrayISyntheticFrontEnd_1400 : public SyntheticChildrenFrontEnd { +public: + NSArrayISyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp); + + ~NSArrayISyntheticFrontEnd_1400() override; + + size_t CalculateNumChildren() override; + + lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; + + bool Update() override; + + bool MightHaveChildren() override; + + size_t GetIndexOfChildWithName(const ConstString &name) override; + +private: + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + + struct DataDescriptor_32 { + uint32_t used; + uint32_t offset; + uint32_t size; + uint32_t list; + }; + + struct DataDescriptor_64 { + uint64_t used; + uint64_t offset; + uint64_t size; + uint64_t list; + }; + + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + CompilerType m_id_type; +}; + class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: NSArray0SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); @@ -257,6 +332,8 @@ bool lldb_private::formatters::NSArraySummaryProvider( static const ConstString g_NSArray0("__NSArray0"); static const ConstString g_NSArray1("__NSSingleObjectArrayI"); static const ConstString g_NSArrayCF("__NSCFArray"); + static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy"); + static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable"); if (class_name.IsEmpty()) return false; @@ -273,6 +350,18 @@ bool lldb_private::formatters::NSArraySummaryProvider( ptr_size, 0, error); if (error.Fail()) return false; + } else if (class_name == g_NSArrayMLegacy) { + Status error; + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + if (error.Fail()) + return false; + } else if (class_name == g_NSArrayMImmutable) { + Status error; + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + if (error.Fail()) + return false; } else if (class_name == g_NSArray0) { value = 0; } else if (class_name == g_NSArray1) { @@ -332,6 +421,11 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010:: : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr), m_data_64(nullptr) {} +lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400:: + NSArrayMSyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp) + : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr), + m_data_64(nullptr) {} + size_t lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren() { return GetUsedCount(); @@ -416,6 +510,37 @@ bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update() { return false; } +bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::Update() { + ValueObjectSP valobj_sp = m_backend.GetSP(); + m_ptr_size = 0; + delete m_data_32; + m_data_32 = nullptr; + delete m_data_64; + m_data_64 = nullptr; + if (!valobj_sp) + return false; + m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); + Status error; + error.Clear(); + lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); + if (!process_sp) + return false; + m_ptr_size = process_sp->GetAddressByteSize(); + uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; + if (m_ptr_size == 4) { + m_data_32 = new DataDescriptor_32(); + process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), + error); + } else { + m_data_64 = new DataDescriptor_64(); + process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), + error); + } + if (error.Fail()) + return false; + return false; +} + bool lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren() { return true; } @@ -498,7 +623,42 @@ uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize() { return m_data_32 ? m_data_32->_size : m_data_64->_size; } -lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd( +lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400:: + ~NSArrayMSyntheticFrontEnd_1400() { + delete m_data_32; + m_data_32 = nullptr; + delete m_data_64; + m_data_64 = nullptr; +} + +lldb::addr_t +lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetDataAddress() { + if (!m_data_32 && !m_data_64) + return LLDB_INVALID_ADDRESS; + return m_data_32 ? m_data_32->list : m_data_64->list; +} + +uint64_t +lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetUsedCount() { + if (!m_data_32 && !m_data_64) + return 0; + return m_data_32 ? m_data_32->used : m_data_64->used; +} + +uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetOffset() { + if (!m_data_32 && !m_data_64) + return 0; + return m_data_32 ? m_data_32->offset : m_data_64->offset; +} + +uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetSize() { + if (!m_data_32 && !m_data_64) + return 0; + return m_data_32 ? m_data_32->size : m_data_64->size; +} + + +lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::NSArrayISyntheticFrontEnd_1300( lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_items(0), m_data_ptr(0) { @@ -516,7 +676,7 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd( } size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName( +lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetIndexOfChildWithName( const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); @@ -526,11 +686,11 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName( } size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren() { +lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::CalculateNumChildren() { return m_items; } -bool lldb_private::formatters::NSArrayISyntheticFrontEnd::Update() { +bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::Update() { m_ptr_size = 0; m_items = 0; m_data_ptr = 0; @@ -552,12 +712,12 @@ bool lldb_private::formatters::NSArrayISyntheticFrontEnd::Update() { return false; } -bool lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren() { +bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::MightHaveChildren() { return true; } lldb::ValueObjectSP -lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex( +lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetChildAtIndex( size_t idx) { if (idx >= CalculateNumChildren()) return lldb::ValueObjectSP(); @@ -575,6 +735,99 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex( m_exe_ctx_ref, m_id_type); } +lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::NSArrayISyntheticFrontEnd_1400( + lldb::ValueObjectSP valobj_sp) + : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), + m_data_32(nullptr), m_data_64(nullptr) { + if (valobj_sp) { + CompilerType type = valobj_sp->GetCompilerType(); + if (type) { + ClangASTContext *ast = valobj_sp->GetExecutionContextRef() + .GetTargetSP() + ->GetScratchClangASTContext(); + if (ast) + m_id_type = CompilerType(ast->getASTContext(), + ast->getASTContext()->ObjCBuiltinIdTy); + } + } +} + +lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::~NSArrayISyntheticFrontEnd_1400() { + delete m_data_32; + m_data_32 = nullptr; + delete m_data_64; + m_data_64 = nullptr; +} + +size_t +lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::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; +} + +size_t +lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::CalculateNumChildren() { + return m_data_32 ? m_data_32->used : m_data_64->used; +} + +bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::Update() { + ValueObjectSP valobj_sp = m_backend.GetSP(); + m_ptr_size = 0; + delete m_data_32; + m_data_32 = nullptr; + delete m_data_64; + m_data_64 = nullptr; + if (!valobj_sp) + return false; + m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); + Status error; + error.Clear(); + lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); + if (!process_sp) + return false; + m_ptr_size = process_sp->GetAddressByteSize(); + uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; + if (m_ptr_size == 4) { + m_data_32 = new DataDescriptor_32(); + process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), + error); + } else { + m_data_64 = new DataDescriptor_64(); + process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), + error); + } + if (error.Fail()) + return false; + return false; +} + +bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::MightHaveChildren() { + return true; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetChildAtIndex( + size_t idx) { + if (idx >= CalculateNumChildren()) + return lldb::ValueObjectSP(); + lldb::addr_t object_at_idx = m_data_32 ? m_data_32->list : m_data_64->list; + object_at_idx += (idx * m_ptr_size); + ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); + if (!process_sp) + return lldb::ValueObjectSP(); + Status error; + if (error.Fail()) + return lldb::ValueObjectSP(); + StreamString idx_name; + idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); + return CreateValueObjectFromAddress(idx_name.GetString(), object_at_idx, + m_exe_ctx_ref, m_id_type); +} + lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd( lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp) {} @@ -683,17 +936,24 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator( static const ConstString g_NSArrayM("__NSArrayM"); static const ConstString g_NSArray0("__NSArray0"); static const ConstString g_NSArray1("__NSSingleObjectArrayI"); + static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy"); + static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable"); if (class_name.IsEmpty()) return nullptr; if (class_name == g_NSArrayI) { - return (new NSArrayISyntheticFrontEnd(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1400) + return (new NSArrayISyntheticFrontEnd_1400(valobj_sp)); + else + return (new NSArrayISyntheticFrontEnd_1300(valobj_sp)); } else if (class_name == g_NSArray0) { return (new NSArray0SyntheticFrontEnd(valobj_sp)); } else if (class_name == g_NSArray1) { return (new NSArray1SyntheticFrontEnd(valobj_sp)); } else if (class_name == g_NSArrayM) { + if (runtime->GetFoundationVersion() >= 1400) + return (new NSArrayMSyntheticFrontEnd_1400(valobj_sp)); if (runtime->GetFoundationVersion() >= 1100) return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp)); else diff --git a/source/Plugins/Language/ObjC/NSDictionary.cpp b/source/Plugins/Language/ObjC/NSDictionary.cpp index 6df83d52acca..50febbe39758 100644 --- a/source/Plugins/Language/ObjC/NSDictionary.cpp +++ b/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -17,6 +17,8 @@ // Project includes #include "NSDictionary.h" +#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" + #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/DataFormatters/FormattersHelpers.h" @@ -181,6 +183,52 @@ public: private: struct DataDescriptor_32 { + uint32_t used : 26; + uint32_t kvo : 1; + uint32_t size; + uint32_t buffer; + }; + + struct DataDescriptor_64 { + uint64_t used : 58; + uint32_t kvo : 1; + uint64_t size; + uint64_t buffer; + }; + + struct DictionaryItemDescriptor { + lldb::addr_t key_ptr; + lldb::addr_t val_ptr; + lldb::ValueObjectSP valobj_sp; + }; + + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + lldb::ByteOrder m_order; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + CompilerType m_pair_type; + std::vector<DictionaryItemDescriptor> m_children; +}; + +class NSDictionaryMLegacySyntheticFrontEnd : public SyntheticChildrenFrontEnd { +public: + NSDictionaryMLegacySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + + ~NSDictionaryMLegacySyntheticFrontEnd() override; + + size_t CalculateNumChildren() override; + + lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; + + bool Update() override; + + bool MightHaveChildren() override; + + size_t GetIndexOfChildWithName(const ConstString &name) override; + +private: + struct DataDescriptor_32 { uint32_t _used : 26; uint32_t _kvo : 1; uint32_t _size; @@ -250,19 +298,21 @@ bool lldb_private::formatters::NSDictionarySummaryProvider( static const ConstString g_DictionaryI("__NSDictionaryI"); static const ConstString g_DictionaryM("__NSDictionaryM"); + static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy"); + static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable"); static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI"); if (class_name.IsEmpty()) return false; - if (class_name == g_DictionaryI) { + if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) { Status error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); if (error.Fail()) return false; value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); - } else if (class_name == g_DictionaryM) { + } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy) { Status error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); @@ -311,9 +361,8 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); if (!process_sp) return nullptr; - ObjCLanguageRuntime *runtime = - (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime( - lldb::eLanguageTypeObjC); + AppleObjCRuntime *runtime = + llvm::dyn_cast_or_null<AppleObjCRuntime>(process_sp->GetObjCLanguageRuntime()); if (!runtime) return nullptr; @@ -338,6 +387,8 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( static const ConstString g_DictionaryI("__NSDictionaryI"); static const ConstString g_DictionaryM("__NSDictionaryM"); static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI"); + static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable"); + static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy"); if (class_name.IsEmpty()) return nullptr; @@ -345,7 +396,13 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( if (class_name == g_DictionaryI) { return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); } else if (class_name == g_DictionaryM) { - return (new NSDictionaryMSyntheticFrontEnd(valobj_sp)); + if (runtime->GetFoundationVersion() > 1400) { + return (new NSDictionaryMSyntheticFrontEnd(valobj_sp)); + } else { + return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp)); + } + } else if (class_name == g_DictionaryMLegacy) { + return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp)); } else if (class_name == g_Dictionary1) { return (new NSDictionary1SyntheticFrontEnd(valobj_sp)); } else { @@ -611,7 +668,7 @@ size_t lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: CalculateNumChildren() { if (!m_data_32 && !m_data_64) return 0; - return (m_data_32 ? m_data_32->_used : m_data_64->_used); + return (m_data_32 ? m_data_32->used : m_data_64->used); } bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() { @@ -655,6 +712,165 @@ bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: lldb::ValueObjectSP lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex( size_t idx) { + lldb::addr_t m_keys_ptr; + lldb::addr_t m_values_ptr; + if (m_data_32) { + uint32_t size = m_data_32->size; + m_keys_ptr = m_data_32->buffer; + m_values_ptr = m_data_32->buffer + (m_ptr_size * size); + } else { + uint32_t size = m_data_64->size; + m_keys_ptr = m_data_64->buffer; + m_values_ptr = m_data_64->buffer + (m_ptr_size * size); + } + + uint32_t num_children = CalculateNumChildren(); + + if (idx >= num_children) + return lldb::ValueObjectSP(); + + if (m_children.empty()) { + // do the scan phase + lldb::addr_t key_at_idx = 0, val_at_idx = 0; + + uint32_t tries = 0; + uint32_t test_idx = 0; + + while (tries < num_children) { + key_at_idx = m_keys_ptr + (test_idx * m_ptr_size); + val_at_idx = m_values_ptr + (test_idx * m_ptr_size); + ; + ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); + if (!process_sp) + return lldb::ValueObjectSP(); + Status error; + key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); + if (error.Fail()) + return lldb::ValueObjectSP(); + val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); + if (error.Fail()) + return lldb::ValueObjectSP(); + + test_idx++; + + if (!key_at_idx || !val_at_idx) + continue; + tries++; + + DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx, + lldb::ValueObjectSP()}; + + m_children.push_back(descriptor); + } + } + + if (idx >= m_children.size()) // should never happen + return lldb::ValueObjectSP(); + + DictionaryItemDescriptor &dict_item = m_children[idx]; + if (!dict_item.valobj_sp) { + if (!m_pair_type.IsValid()) { + TargetSP target_sp(m_backend.GetTargetSP()); + if (!target_sp) + return ValueObjectSP(); + m_pair_type = GetLLDBNSPairType(target_sp); + } + if (!m_pair_type.IsValid()) + return ValueObjectSP(); + + DataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0)); + + if (m_ptr_size == 8) { + uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); + *data_ptr = dict_item.key_ptr; + *(data_ptr + 1) = dict_item.val_ptr; + } else { + uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); + *data_ptr = dict_item.key_ptr; + *(data_ptr + 1) = dict_item.val_ptr; + } + + StreamString idx_name; + idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); + DataExtractor data(buffer_sp, m_order, m_ptr_size); + dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data, + m_exe_ctx_ref, m_pair_type); + } + return dict_item.valobj_sp; +} + + +lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: + NSDictionaryMLegacySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) + : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), + m_order(lldb::eByteOrderInvalid), m_data_32(nullptr), m_data_64(nullptr), + m_pair_type() {} + +lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: + ~NSDictionaryMLegacySyntheticFrontEnd() { + delete m_data_32; + m_data_32 = nullptr; + delete m_data_64; + m_data_64 = nullptr; +} + +size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: + 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; +} + +size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: + CalculateNumChildren() { + if (!m_data_32 && !m_data_64) + return 0; + return (m_data_32 ? m_data_32->_used : m_data_64->_used); +} + +bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::Update() { + m_children.clear(); + ValueObjectSP valobj_sp = m_backend.GetSP(); + m_ptr_size = 0; + delete m_data_32; + m_data_32 = nullptr; + delete m_data_64; + m_data_64 = nullptr; + if (!valobj_sp) + return false; + m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); + Status error; + error.Clear(); + lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); + if (!process_sp) + return false; + m_ptr_size = process_sp->GetAddressByteSize(); + m_order = process_sp->GetByteOrder(); + uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; + if (m_ptr_size == 4) { + m_data_32 = new DataDescriptor_32(); + process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), + error); + } else { + m_data_64 = new DataDescriptor_64(); + process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), + error); + } + if (error.Fail()) + return false; + return false; +} + +bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: + MightHaveChildren() { + return true; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::GetChildAtIndex( + size_t idx) { lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr); lldb::addr_t m_values_ptr = diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/source/Plugins/Language/ObjC/ObjCLanguage.cpp index 4d9227598cef..ea2eec7b33b7 100644 --- a/source/Plugins/Language/ObjC/ObjCLanguage.cpp +++ b/source/Plugins/Language/ObjC/ObjCLanguage.cpp @@ -1026,6 +1026,7 @@ bool ObjCLanguage::GetFormatterPrefixSuffix(ValueObject &valobj, static ConstString g_NSNumberShort("NSNumber:short"); static ConstString g_NSNumberInt("NSNumber:int"); static ConstString g_NSNumberLong("NSNumber:long"); + static ConstString g_NSNumberInt128("NSNumber:int128_t"); static ConstString g_NSNumberFloat("NSNumber:float"); static ConstString g_NSNumberDouble("NSNumber:double"); @@ -1061,6 +1062,10 @@ bool ObjCLanguage::GetFormatterPrefixSuffix(ValueObject &valobj, prefix = "(long)"; return true; } + if (type_hint == g_NSNumberInt128) { + prefix = "(int128_t)"; + return true; + } if (type_hint == g_NSNumberFloat) { prefix = "(float)"; return true; |