[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:
Kuba Mracek 2018-11-12 21:26:03 +00:00
parent 87e403aa4f
commit 377912845e
3 changed files with 45 additions and 3 deletions

View File

@ -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))

View File

@ -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();

View File

@ -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",