Index: source/Plugins/Language/ObjC/NSException.cpp =================================================================== --- source/Plugins/Language/ObjC/NSException.cpp +++ source/Plugins/Language/ObjC/NSException.cpp @@ -29,52 +29,70 @@ using namespace lldb_private; using namespace lldb_private::formatters; -bool lldb_private::formatters::NSException_SummaryProvider( - ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { +static bool ExtractFields(ValueObject &valobj, ValueObjectSP *name_sp, + ValueObjectSP *reason_sp, + ValueObjectSP *userinfo_sp) { ProcessSP process_sp(valobj.GetProcessSP()); if (!process_sp) return false; - lldb::addr_t ptr_value = LLDB_INVALID_ADDRESS; + lldb::addr_t ptr = LLDB_INVALID_ADDRESS; CompilerType valobj_type(valobj.GetCompilerType()); Flags type_flags(valobj_type.GetTypeInfo()); if (type_flags.AllClear(eTypeHasValue)) { if (valobj.IsBaseClass() && valobj.GetParent()) - ptr_value = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - } else - ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + ptr = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + } else { + ptr = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + } - if (ptr_value == LLDB_INVALID_ADDRESS) + if (ptr == LLDB_INVALID_ADDRESS) return false; size_t ptr_size = process_sp->GetAddressByteSize(); - lldb::addr_t name_location = ptr_value + 1 * ptr_size; - lldb::addr_t reason_location = ptr_value + 2 * ptr_size; Status error; - lldb::addr_t name = process_sp->ReadPointerFromMemory(name_location, error); + auto name = process_sp->ReadPointerFromMemory(ptr + 1 * ptr_size, error); if (error.Fail() || name == LLDB_INVALID_ADDRESS) return false; - - lldb::addr_t reason = - process_sp->ReadPointerFromMemory(reason_location, error); + auto reason = process_sp->ReadPointerFromMemory(ptr + 2 * ptr_size, error); if (error.Fail() || reason == LLDB_INVALID_ADDRESS) return false; + auto userinfo = process_sp->ReadPointerFromMemory(ptr + 3 * ptr_size, error); + if (error.Fail() || userinfo == LLDB_INVALID_ADDRESS) + return false; InferiorSizedWord name_isw(name, *process_sp); InferiorSizedWord reason_isw(reason, *process_sp); + InferiorSizedWord userinfo_isw(userinfo, *process_sp); CompilerType voidstar = process_sp->GetTarget() .GetScratchClangASTContext() ->GetBasicType(lldb::eBasicTypeVoid) .GetPointerType(); - ValueObjectSP name_sp = ValueObject::CreateValueObjectFromData( - "name_str", name_isw.GetAsData(process_sp->GetByteOrder()), - valobj.GetExecutionContextRef(), voidstar); - ValueObjectSP reason_sp = ValueObject::CreateValueObjectFromData( - "reason_str", reason_isw.GetAsData(process_sp->GetByteOrder()), - valobj.GetExecutionContextRef(), voidstar); + if (name_sp) + *name_sp = ValueObject::CreateValueObjectFromData( + "name", name_isw.GetAsData(process_sp->GetByteOrder()), + valobj.GetExecutionContextRef(), voidstar); + if (reason_sp) + *reason_sp = ValueObject::CreateValueObjectFromData( + "reason", reason_isw.GetAsData(process_sp->GetByteOrder()), + valobj.GetExecutionContextRef(), voidstar); + if (userinfo_sp) + *userinfo_sp = ValueObject::CreateValueObjectFromData( + "userInfo", userinfo_isw.GetAsData(process_sp->GetByteOrder()), + valobj.GetExecutionContextRef(), voidstar); + + return true; +} + +bool lldb_private::formatters::NSException_SummaryProvider( + ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { + lldb::ValueObjectSP name_sp; + lldb::ValueObjectSP reason_sp; + if (!ExtractFields(valobj, &name_sp, &reason_sp, nullptr)) + return false; if (!name_sp || !reason_sp) return false; @@ -97,63 +115,24 @@ : SyntheticChildrenFrontEnd(*valobj_sp) {} ~NSExceptionSyntheticFrontEnd() override = default; - // no need to delete m_child_ptr - it's kept alive by the cluster manager on - // our behalf size_t CalculateNumChildren() override { - if (m_child_ptr) - return 1; - if (m_child_sp) - return 1; - return 0; + return 1; } lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { - if (idx != 0) - return lldb::ValueObjectSP(); - - if (m_child_ptr) - return m_child_ptr->GetSP(); - return m_child_sp; + switch (idx) { + case 0: return m_userinfo_sp; + } + return lldb::ValueObjectSP(); } bool Update() override { - m_child_ptr = nullptr; - m_child_sp.reset(); - - ProcessSP process_sp(m_backend.GetProcessSP()); - if (!process_sp) - return false; - - lldb::addr_t userinfo_location = LLDB_INVALID_ADDRESS; - - CompilerType valobj_type(m_backend.GetCompilerType()); - Flags type_flags(valobj_type.GetTypeInfo()); - if (type_flags.AllClear(eTypeHasValue)) { - if (m_backend.IsBaseClass() && m_backend.GetParent()) - userinfo_location = - m_backend.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - } else - userinfo_location = m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - - if (userinfo_location == LLDB_INVALID_ADDRESS) + m_userinfo_sp.reset(); + if (!ExtractFields(m_backend, nullptr, nullptr, &m_userinfo_sp)) { return false; - - size_t ptr_size = process_sp->GetAddressByteSize(); - - userinfo_location += 3 * ptr_size; - Status error; - lldb::addr_t userinfo = - process_sp->ReadPointerFromMemory(userinfo_location, error); - if (userinfo == LLDB_INVALID_ADDRESS || error.Fail()) - return false; - InferiorSizedWord isw(userinfo, *process_sp); - m_child_sp = CreateValueObjectFromData( - "userInfo", isw.GetAsData(process_sp->GetByteOrder()), - m_backend.GetExecutionContextRef(), - process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType( - lldb::eBasicTypeObjCID)); - return false; + } + return true; } bool MightHaveChildren() override { return true; } @@ -166,14 +145,7 @@ } private: - // the child here can be "real" (i.e. an actual child of the root) or - // synthetized from raw memory if the former, I need to store a plain pointer - // to it - or else a loop of references will cause this entire hierarchy of - // values to leak if the latter, then I need to store a SharedPointer to it - - // so that it only goes away when everyone else in the cluster goes away oh - // joy! - ValueObject *m_child_ptr; - ValueObjectSP m_child_sp; + ValueObjectSP m_userinfo_sp; }; SyntheticChildrenFrontEnd *