[Lldb-commits] [lldb] d671002 - [LLDB][NativePDB] Fix several crashes when parsing debug info.
Zequan Wu via lldb-commits
lldb-commits at lists.llvm.org
Wed Jun 8 16:41:30 PDT 2022
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;
}
}
More information about the lldb-commits
mailing list