[lldb] Add synthetic frontend for _NSCallStackArray
An Obj-C array type _NSCallStackArray is used in NSException backtraces. This patch adds a synthetic frontend for _NSCallStackArray, which now correctly returns frame PCs. Differential Revision: https://reviews.llvm.org/D44081 llvm-svn: 346708
This commit is contained in:
parent
87e403aa4f
commit
377912845e
|
@ -28,7 +28,8 @@ class ObjCExceptionsTestCase(TestBase):
|
|||
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 @@ class ObjCExceptionsTestCase(TestBase):
|
|||
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))
|
||||
|
|
|
@ -214,6 +214,25 @@ namespace Foundation1437 {
|
|||
|
||||
}
|
||||
|
||||
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<DataDescriptor_32, DataDescriptor_64>;
|
||||
} // namespace CallStackArray
|
||||
|
||||
template <typename D32, typename D64, bool Inline>
|
||||
class GenericNSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd {
|
||||
public:
|
||||
|
@ -364,6 +383,7 @@ bool lldb_private::formatters::NSArraySummaryProvider(
|
|||
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 @@ bool lldb_private::formatters::NSArraySummaryProvider(
|
|||
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 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator(
|
|||
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 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator(
|
|||
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();
|
||||
|
|
|
@ -407,6 +407,9 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
|
|||
AddCXXSummary(
|
||||
objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
|
||||
"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);
|
||||
|
@ -526,6 +529,10 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
|
|||
lldb_private::formatters::NSArraySyntheticFrontEndCreator,
|
||||
"NSArray synthetic children", ConstString("__NSCFArray"),
|
||||
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",
|
||||
|
|
Loading…
Reference in New Issue