Index: packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py =================================================================== --- packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py +++ packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py @@ -28,7 +28,8 @@ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, substrs=['stopped', 'stop reason = breakpoint']) - thread = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread() + target = self.dbg.GetSelectedTarget() + thread = target.GetProcess().GetSelectedThread() frame = thread.GetSelectedFrame() self.expect( @@ -87,4 +88,13 @@ self.assertEqual(userInfo.summary, "1 key/value pair") self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key") self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value") - self.assertGreater(e2.GetChildMemberWithName("reserved").dynamic.num_children, 0) + reserved = e2.GetChildMemberWithName("reserved").dynamic + self.assertGreater(reserved.num_children, 0) + callStackReturnAddresses = [reserved.GetChildAtIndex(i).GetChildAtIndex(1) for i in range(0, reserved.GetNumChildren()) + if reserved.GetChildAtIndex(i).GetChildAtIndex(0).description == "callStackReturnAddresses"][0].dynamic + children = [callStackReturnAddresses.GetChildAtIndex(i) for i in range(0, callStackReturnAddresses.num_children)] + + pcs = [i.unsigned for i in children] + names = [target.ResolveSymbolContextForAddress(lldb.SBAddress(pc, target), lldb.eSymbolContextSymbol).GetSymbol().name for pc in pcs] + for n in ["objc_exception_throw", "foo", "main"]: + self.assertTrue(n in names, "%s is in the exception backtrace (%s)" % (n, names)) Index: source/Plugins/Language/ObjC/NSArray.cpp =================================================================== --- source/Plugins/Language/ObjC/NSArray.cpp +++ source/Plugins/Language/ObjC/NSArray.cpp @@ -214,6 +214,25 @@ } +namespace CallStackArray { +struct DataDescriptor_32 { + uint32_t _data; + uint32_t _used; + uint32_t _offset; + const uint32_t _size = 0; +}; + +struct DataDescriptor_64 { + uint64_t _data; + uint64_t _used; + uint64_t _offset; + const uint64_t _size = 0; +}; + +using NSCallStackArraySyntheticFrontEnd = + GenericNSArrayMSyntheticFrontEnd; +} // namespace CallStackArray + template class GenericNSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: @@ -364,6 +383,7 @@ static const ConstString g_NSArrayCF("__NSCFArray"); static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy"); static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable"); + static const ConstString g_NSCallStackArray("_NSCallStackArray"); if (class_name.IsEmpty()) return false; @@ -413,7 +433,9 @@ value = 0; } else if (class_name == g_NSArray1) { value = 1; - } else if (class_name == g_NSArrayCF) { + } else if (class_name == g_NSArrayCF || class_name == g_NSCallStackArray) { + // __NSCFArray and _NSCallStackArray store the number of elements as a + // pointer-sized value at offset `2 * ptr_size`. Status error; value = process_sp->ReadUnsignedIntegerFromMemory( valobj_addr + 2 * ptr_size, ptr_size, 0, error); @@ -813,6 +835,7 @@ static const ConstString g_NSArray1("__NSSingleObjectArrayI"); static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy"); static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable"); + static const ConstString g_NSCallStackArray("_NSCallStackArray"); if (class_name.IsEmpty()) return nullptr; @@ -842,6 +865,8 @@ return (new Foundation1010::NSArrayMSyntheticFrontEnd(valobj_sp)); else return (new Foundation109::NSArrayMSyntheticFrontEnd(valobj_sp)); + } else if (class_name == g_NSCallStackArray) { + return (new CallStackArray::NSCallStackArraySyntheticFrontEnd(valobj_sp)); } else { auto &map(NSArray_Additionals::GetAdditionalSynthetics()); auto iter = map.find(class_name), end = map.end(); Index: source/Plugins/Language/ObjC/ObjCLanguage.cpp =================================================================== --- source/Plugins/Language/ObjC/ObjCLanguage.cpp +++ source/Plugins/Language/ObjC/ObjCLanguage.cpp @@ -409,6 +409,9 @@ "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags); AddCXXSummary( objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, + "NSArray summary provider", ConstString("_NSCallStackArray"), appkit_flags); + AddCXXSummary( + objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags); AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, @@ -528,6 +531,10 @@ ScriptedSyntheticChildren::Flags()); AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, + "NSArray synthetic children", ConstString("_NSCallStackArray"), + ScriptedSyntheticChildren::Flags()); + AddCXXSynthetic(objc_category_sp, + lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFMutableArrayRef"), ScriptedSyntheticChildren::Flags());