Author: Zequan Wu Date: 2022-06-08T16:41:23-07:00 New Revision: d6710023e396aa55f92e3906755d68b06489d95f
URL: https://github.com/llvm/llvm-project/commit/d6710023e396aa55f92e3906755d68b06489d95f DIFF: https://github.com/llvm/llvm-project/commit/d6710023e396aa55f92e3906755d68b06489d95f.diff LOG: [LLDB][NativePDB] Fix several crashes when parsing debug info. 1. If array element type is a tag decl, complete it. 2. Fix few places where `asTag` should be used instead of `asClass()`. 3. Handle the case that `PdbAstBuilder::CreateFunctionDecl` return nullptr mainly due to an existing workaround (`m_cxx_record_map`). 4. `FindMembersSize` should never return error as this would cause early exiting in `CVTypeVisitor::visitFieldListMemberStream` and then cause assertion failure. 5. In some pdbs from C++ runtime libraries have S_LPROC32 followed directly by S_LOCAL and the local variable location is a S_DEFRANGE_FRAMEPOINTER_REL. There is no information about base frame register in this case, ignoring it by returning RegisterId::NONE. 6. Add a TODO when S_DEFRANGE_SUBFIELD_REGISTER describes the variable location of a pointer type. For now, just ignoring it if the variable is pointer. Added: Modified: lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp Removed: ################################################################################ diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 80d51ab656f4a..0217186cf87a3 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -711,6 +711,10 @@ bool PdbAstBuilder::CompleteType(clang::QualType qt) { if (qt.isNull()) return false; clang::TagDecl *tag = qt->getAsTagDecl(); + if (qt->isArrayType()) { + const clang::Type *element_type = qt->getArrayElementTypeNoTypeQual(); + tag = element_type->getAsTagDecl(); + } if (!tag) return false; @@ -1089,6 +1093,7 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id, ->getCanonicalTypeInternal(); lldb::opaque_compiler_type_t parent_opaque_ty = ToCompilerType(parent_qt).GetOpaqueQualType(); + // FIXME: Remove this workaround. auto iter = m_cxx_record_map.find(parent_opaque_ty); if (iter != m_cxx_record_map.end()) { if (iter->getSecond().contains({func_name, func_ct})) { @@ -1103,18 +1108,17 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id, TypeIndex class_index = func_record.getClassType(); CVType parent_cvt = m_index.tpi().getType(class_index); - ClassRecord class_record = CVTagRecord::create(parent_cvt).asClass(); + TagRecord tag_record = CVTagRecord::create(parent_cvt).asTag(); // If it's a forward reference, try to get the real TypeIndex. - if (class_record.isForwardRef()) { + if (tag_record.isForwardRef()) { llvm::Expected<TypeIndex> eti = m_index.tpi().findFullDeclForForwardRef(class_index); if (eti) { - class_record = - CVTagRecord::create(m_index.tpi().getType(*eti)).asClass(); + tag_record = CVTagRecord::create(m_index.tpi().getType(*eti)).asTag(); } } - if (!class_record.FieldList.isSimple()) { - CVType field_list = m_index.tpi().getType(class_record.FieldList); + if (!tag_record.FieldList.isSimple()) { + CVType field_list = m_index.tpi().getType(tag_record.FieldList); CreateMethodDecl process(m_index, m_clang, func_ti, function_decl, parent_opaque_ty, func_name, func_ct); if (llvm::Error err = visitMemberRecordStream(field_list.data(), process)) @@ -1156,6 +1160,8 @@ PdbAstBuilder::GetOrCreateInlinedFunctionDecl(PdbCompilandSymId inlinesite_id) { return llvm::dyn_cast<clang::FunctionDecl>(decl); clang::FunctionDecl *function_decl = CreateFunctionDeclFromId(func_id, inlinesite_id); + if (function_decl == nullptr) + return nullptr; // Use inline site id in m_decl_to_status because it's expected to be a // PdbCompilandSymId so that we can parse local variables info after it. @@ -1261,6 +1267,8 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) { clang::FunctionDecl *function_decl = CreateFunctionDecl(func_id, proc_name, proc.FunctionType, func_ct, func_type->getNumParams(), storage, false, parent); + if (function_decl == nullptr) + return nullptr; lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0); m_uid_to_decl[toOpaqueUid(func_id)] = function_decl; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp index 8ef4f21a69694..10e8cbd11482d 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp @@ -59,11 +59,9 @@ struct FindMembersSize : public TypeVisitorCallbacks { TpiStream &tpi; llvm::Error visitKnownMember(CVMemberRecord &cvr, DataMemberRecord &member) override { - auto it = members_info.insert( + members_info.insert( {member.getFieldOffset(), {llvm::codeview::RegisterId::NONE, GetSizeOfType(member.Type, tpi)}}); - if (!it.second) - return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record); return llvm::Error::success(); } }; @@ -586,7 +584,8 @@ static RegisterId GetBaseFrameRegister(PdbIndex &index, PdbCompilandSymId frame_proc_id, bool is_parameter) { CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id); - lldbassert(frame_proc_cvs.kind() == S_FRAMEPROC); + if (frame_proc_cvs.kind() != S_FRAMEPROC) + return RegisterId::NONE; FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym); cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs, @@ -658,7 +657,8 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo( RegisterId base_reg = GetBaseFrameRegister(index, frame_proc_id, result.is_param); - + if (base_reg == RegisterId::NONE) + break; if (base_reg == RegisterId::VFRAME) { llvm::StringRef program; if (GetFrameDataProgram(index, ranges, program)) { @@ -719,12 +719,29 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo( bool is_simple_type = result.type.isSimple(); if (!is_simple_type) { CVType class_cvt = index.tpi().getType(result.type); - ClassRecord class_record = CVTagRecord::create(class_cvt).asClass(); - CVType field_list = index.tpi().getType(class_record.FieldList); - FindMembersSize find_members_size(members_info, index.tpi()); - if (llvm::Error err = - visitMemberRecordStream(field_list.data(), find_members_size)) { - llvm::consumeError(std::move(err)); + TypeIndex class_id = result.type; + if (class_cvt.kind() == LF_MODIFIER) + class_id = LookThroughModifierRecord(class_cvt); + if (IsForwardRefUdt(class_id, index.tpi())) { + auto expected_full_ti = + index.tpi().findFullDeclForForwardRef(class_id); + if (!expected_full_ti) { + llvm::consumeError(expected_full_ti.takeError()); + break; + } + class_cvt = index.tpi().getType(*expected_full_ti); + } + if (IsTagRecord(class_cvt)) { + TagRecord tag_record = CVTagRecord::create(class_cvt).asTag(); + CVType field_list = index.tpi().getType(tag_record.FieldList); + FindMembersSize find_members_size(members_info, index.tpi()); + if (llvm::Error err = visitMemberRecordStream(field_list.data(), + find_members_size)) { + llvm::consumeError(std::move(err)); + break; + } + } else { + // TODO: Handle poiner type. break; } } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits