[Lldb-commits] [lldb] 5c9f3ec - [LLDB][NativePDB] Check for missing type info to avoid crash.

Zequan Wu via lldb-commits lldb-commits at lists.llvm.org
Wed May 25 13:21:55 PDT 2022


Author: Zequan Wu
Date: 2022-05-25T13:19:27-07:00
New Revision: 5c9f3ec4ad5d930f38c5682345a589ce57a5d602

URL: https://github.com/llvm/llvm-project/commit/5c9f3ec4ad5d930f38c5682345a589ce57a5d602
DIFF: https://github.com/llvm/llvm-project/commit/5c9f3ec4ad5d930f38c5682345a589ce57a5d602.diff

LOG: [LLDB][NativePDB] Check for missing type info to avoid crash.

NativePDB often assumes that all debug info are available.
This is one step to make it more pervasive.

Differential Revision: https://reviews.llvm.org/D125844

Added: 
    lldb/test/Shell/SymbolFile/NativePDB/missing-type.s

Modified: 
    lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
    lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
    lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index eaff882c5f13..80d51ab656f4 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -323,6 +323,8 @@ PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {
   // LLDB TypeSP for the parent.  This will cause the AST to automatically get
   // the right DeclContext created for any parent.
   clang::QualType parent_qt = GetOrCreateType(parent_iter->second);
+  if (parent_qt.isNull())
+    return {nullptr, ""};
 
   context = clang::TagDecl::castToDeclContext(parent_qt->getAsTagDecl());
   return {context, uname};
@@ -532,6 +534,8 @@ llvm::Optional<CompilerDecl> PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid)
     break;
   case PdbSymUidKind::Type: {
     clang::QualType qt = GetOrCreateType(uid.asTypeSym());
+    if (qt.isNull())
+      return llvm::None;
     if (auto *tag = qt->getAsTagDecl()) {
       result = tag;
       break;
@@ -581,6 +585,8 @@ PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) {
   std::vector<TypeIndex> types = m_index.tpi().findRecordsByName(scope_name);
   while (!types.empty()) {
     clang::QualType qt = GetOrCreateType(types.back());
+    if (qt.isNull())
+      continue;
     clang::TagDecl *tag = qt->getAsTagDecl();
     if (tag)
       return {clang::TagDecl::castToDeclContext(tag), std::string(uname)};
@@ -622,6 +628,8 @@ PdbAstBuilder::GetParentDeclContextForSymbol(const CVSymbol &sym) {
     std::vector<TypeIndex> matches = m_index.tpi().findRecordsByName(qname);
     while (!matches.empty()) {
       clang::QualType qt = GetOrCreateType(matches.back());
+      if (qt.isNull())
+        continue;
       clang::TagDecl *tag = qt->getAsTagDecl();
       if (tag)
         return clang::TagDecl::castToDeclContext(tag);
@@ -700,6 +708,8 @@ clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) {
 }
 
 bool PdbAstBuilder::CompleteType(clang::QualType qt) {
+  if (qt.isNull())
+    return false;
   clang::TagDecl *tag = qt->getAsTagDecl();
   if (!tag)
     return false;
@@ -767,6 +777,8 @@ clang::QualType PdbAstBuilder::CreateSimpleType(TypeIndex ti) {
 
   if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
     clang::QualType direct_type = GetOrCreateType(ti.makeDirect());
+    if (direct_type.isNull())
+      return {};
     return m_clang.getASTContext().getPointerType(direct_type);
   }
 
@@ -791,7 +803,8 @@ clang::QualType PdbAstBuilder::CreatePointerType(const PointerRecord &pointer) {
   if (pointer.isPointerToMember()) {
     MemberPointerInfo mpi = pointer.getMemberInfo();
     clang::QualType class_type = GetOrCreateType(mpi.ContainingType);
-
+    if (class_type.isNull())
+      return {};
     return m_clang.getASTContext().getMemberPointerType(
         pointee_type, class_type.getTypePtr());
   }
@@ -835,6 +848,9 @@ clang::QualType PdbAstBuilder::CreateRecordType(PdbTypeSymId id,
   clang::DeclContext *context = nullptr;
   std::string uname;
   std::tie(context, uname) = CreateDeclInfoForType(record, id.index);
+  if (!context)
+    return {};
+
   clang::TagTypeKind ttk = TranslateUdtKind(record);
   lldb::AccessType access =
       (ttk == clang::TTK_Class) ? lldb::eAccessPrivate : lldb::eAccessPublic;
@@ -899,6 +915,8 @@ clang::VarDecl *PdbAstBuilder::CreateVariableDecl(PdbSymUid uid, CVSymbol sym,
                                                   clang::DeclContext &scope) {
   VariableInfo var_info = GetVariableNameInfo(sym);
   clang::QualType qt = GetOrCreateType(var_info.type);
+  if (qt.isNull())
+    return nullptr;
 
   clang::VarDecl *var_decl = m_clang.CreateVariableDeclaration(
       &scope, OptionalClangModuleID(), var_info.name.str().c_str(), qt);
@@ -947,6 +965,8 @@ PdbAstBuilder::GetOrCreateTypedefDecl(PdbGlobalSymId id) {
 
   PdbTypeSymId real_type_id{udt.Type, false};
   clang::QualType qt = GetOrCreateType(real_type_id);
+  if (qt.isNull())
+    return nullptr;
 
   std::string uname = std::string(DropNameScope(udt.Name));
 
@@ -1017,6 +1037,9 @@ clang::QualType PdbAstBuilder::CreateType(PdbTypeSymId type) {
 }
 
 clang::QualType PdbAstBuilder::GetOrCreateType(PdbTypeSymId type) {
+  if (type.index.isNoneType())
+    return {};
+
   lldb::user_id_t uid = toOpaqueUid(type);
   auto iter = m_uid_to_type.find(uid);
   if (iter != m_uid_to_type.end())
@@ -1029,6 +1052,8 @@ clang::QualType PdbAstBuilder::GetOrCreateType(PdbTypeSymId type) {
     // This is a forward decl.  Call GetOrCreate on the full decl, then map the
     // forward decl id to the full decl QualType.
     clang::QualType qt = GetOrCreateType(best_type);
+    if (qt.isNull())
+      return {};
     m_uid_to_type[toOpaqueUid(type)] = qt;
     return qt;
   }
@@ -1036,6 +1061,9 @@ clang::QualType PdbAstBuilder::GetOrCreateType(PdbTypeSymId type) {
   // This is either a full decl, or a forward decl with no matching full decl
   // in the debug info.
   qt = CreateType(type);
+  if (qt.isNull())
+    return {};
+
   m_uid_to_type[toOpaqueUid(type)] = qt;
   if (IsTagRecord(type, m_index.tpi())) {
     clang::TagDecl *tag = qt->getAsTagDecl();
@@ -1298,6 +1326,8 @@ void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id,
 
     PdbCompilandSymId param_uid(func_id.modi, record_offset);
     clang::QualType qt = GetOrCreateType(param_type);
+    if (qt.isNull())
+      return;
 
     CompilerType param_type_ct = m_clang.GetType(qt);
     clang::ParmVarDecl *param = m_clang.CreateParameterDeclaration(
@@ -1319,7 +1349,12 @@ clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id,
   clang::DeclContext *decl_context = nullptr;
   std::string uname;
   std::tie(decl_context, uname) = CreateDeclInfoForType(er, id.index);
+  if (!decl_context)
+    return {};
+
   clang::QualType underlying_type = GetOrCreateType(er.UnderlyingType);
+  if (underlying_type.isNull())
+    return {};
 
   Declaration declaration;
   CompilerType enum_ct = m_clang.CreateEnumerationType(
@@ -1336,7 +1371,7 @@ clang::QualType PdbAstBuilder::CreateArrayType(const ArrayRecord &ar) {
   clang::QualType element_type = GetOrCreateType(ar.ElementType);
 
   uint64_t element_size = GetSizeOfType({ar.ElementType}, m_index.tpi());
-  if (element_size == 0)
+  if (element_type.isNull() || element_size == 0)
     return {};
   uint64_t element_count = ar.Size / element_size;
 
@@ -1364,10 +1399,14 @@ clang::QualType PdbAstBuilder::CreateFunctionType(
 
   for (TypeIndex arg_index : arg_indices) {
     clang::QualType arg_type = GetOrCreateType(arg_index);
+    if (arg_type.isNull())
+      continue;
     arg_types.push_back(ToCompilerType(arg_type));
   }
 
   clang::QualType return_type = GetOrCreateType(return_type_idx);
+  if (return_type.isNull())
+    return {};
 
   llvm::Optional<clang::CallingConv> cc =
       TranslateCallingConvention(calling_convention);
@@ -1418,7 +1457,7 @@ void PdbAstBuilder::ParseAllNamespacesPlusChildrenOf(
     clang::DeclContext *context = nullptr;
     std::string uname;
     std::tie(context, uname) = CreateDeclInfoForType(tag.asTag(), tid.index);
-    if (!context->isNamespace())
+    if (!context || !context->isNamespace())
       continue;
 
     clang::NamespaceDecl *ns = llvm::cast<clang::NamespaceDecl>(context);

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 22d8977e117b..18fd7efb93e8 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -726,6 +726,8 @@ TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) {
   PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id;
 
   clang::QualType qt = m_ast->GetOrCreateType(best_decl_id);
+  if (qt.isNull())
+    return nullptr;
 
   TypeSP result = CreateType(best_decl_id, m_ast->ToCompilerType(qt));
   if (!result)

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
index 856ba1cb296d..dba304420c55 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -67,7 +67,8 @@ clang::QualType UdtRecordCompleter::AddBaseClassForTypeIndex(
       m_ast_builder.clang().CreateBaseClassSpecifier(
           qt.getAsOpaquePtr(), TranslateMemberAccess(access),
           vtable_idx.hasValue(), udt_cvt.kind() == LF_CLASS);
-  lldbassert(base_spec);
+  if (!base_spec)
+    return {};
 
   m_bases.push_back(
       std::make_pair(vtable_idx.getValueOr(0), std::move(base_spec)));
@@ -80,6 +81,8 @@ void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx,
                                    MemberAttributes attrs) {
   clang::QualType method_qt =
       m_ast_builder.GetOrCreateType(PdbTypeSymId(type_idx));
+  if (method_qt.isNull())
+    return;
   m_ast_builder.CompleteType(method_qt);
   CompilerType method_ct = m_ast_builder.ToCompilerType(method_qt);
   lldb::opaque_compiler_type_t derived_opaque_ty = m_derived_ct.GetOpaqueQualType();
@@ -106,6 +109,8 @@ Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
   clang::QualType base_qt =
       AddBaseClassForTypeIndex(base.Type, base.getAccess());
 
+  if (base_qt.isNull())
+    return llvm::Error::success();
   auto decl =
       m_ast_builder.clang().GetAsCXXRecordDecl(base_qt.getAsOpaquePtr());
   lldbassert(decl);
@@ -137,6 +142,8 @@ Error UdtRecordCompleter::visitKnownMember(
     CVMemberRecord &cvr, StaticDataMemberRecord &static_data_member) {
   clang::QualType member_type =
       m_ast_builder.GetOrCreateType(PdbTypeSymId(static_data_member.Type));
+  if (member_type.isNull())
+    return llvm::Error::success();
 
   CompilerType member_ct = m_ast_builder.ToCompilerType(member_type);
 
@@ -235,6 +242,8 @@ Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
   }
 
   clang::QualType member_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(ti));
+  if (member_qt.isNull())
+    return Error::success();
   m_ast_builder.CompleteType(member_qt);
 
   lldb::AccessType access = TranslateMemberAccess(data_member.getAccess());

diff  --git a/lldb/test/Shell/SymbolFile/NativePDB/missing-type.s b/lldb/test/Shell/SymbolFile/NativePDB/missing-type.s
new file mode 100644
index 000000000000..32be7a1b96ee
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/NativePDB/missing-type.s
@@ -0,0 +1,108 @@
+# clang-format off
+# REQUIRES: lld, x86
+
+# Test when type index is missing in FieldList.
+# RUN: llvm-mc -triple=x86_64-windows-msvc --filetype=obj %s > %t.obj
+# RUN: lld-link /debug:full /nodefaultlib /entry:main %t.obj /out:%t.exe /base:0x140000000
+# RUN: lldb-test symbols --find=type --name=S %t.exe | FileCheck %s
+
+# CHECK:      name = "S", size = 4, compiler_type = {{.*}} struct S {
+# CHECK-NEXT: }
+
+
+
+	.text
+	.def	@feat.00;
+	.scl	3;
+	.type	0;
+	.endef
+	.globl	@feat.00
+.set @feat.00, 0
+	.intel_syntax noprefix
+	.file	"a.cpp"
+	.def	main;
+	.scl	2;
+	.type	32;
+	.endef
+	.globl	main                            # -- Begin function main
+	.p2align	4, 0x90
+main:                                   # @main
+.seh_proc main
+# %bb.0:                                # %entry
+	sub	rsp, 24
+	.seh_stackalloc 24
+	.seh_endprologue
+	mov	dword ptr [rsp + 20], 0
+	mov	qword ptr [rsp + 8], rdx
+	mov	dword ptr [rsp + 4], ecx
+.Ltmp0:
+	mov	eax, dword ptr [rsp]
+	add	rsp, 24
+	ret
+.Ltmp1:
+.Lfunc_end0:
+	.seh_endproc
+                                        # -- End function
+	.section	.drectve,"yn"
+.Ltmp25:
+	.section	.debug$T,"dr"
+	.p2align	2
+	.long	4                               # Debug section magic
+	# Pointer (0x1000)
+	.short	0xa                             # Record length
+	.short	0x1002                          # Record kind: LF_POINTER
+	.long	0x670                           # PointeeType: char*
+	.long	0x1000c                         # Attrs: [ Type: Near64, Mode: Pointer, SizeOf: 8 ]
+	# ArgList (0x1001)
+	.short	0xe                             # Record length
+	.short	0x1201                          # Record kind: LF_ARGLIST
+	.long	0x2                             # NumArgs
+	.long	0x74                            # Argument: int
+	.long	0x1000                          # Argument: char**
+	# Procedure (0x1002)
+	.short	0xe                             # Record length
+	.short	0x1008                          # Record kind: LF_PROCEDURE
+	.long	0x74                            # ReturnType: int
+	.byte	0x0                             # CallingConvention: NearC
+	.byte	0x0                             # FunctionOptions
+	.short	0x2                             # NumParameters
+	.long	0x1001                          # ArgListType: (int, char**)
+	# FuncId (0x1003)
+	.short	0x12                            # Record length
+	.short	0x1601                          # Record kind: LF_FUNC_ID
+	.long	0x0                             # ParentScope
+	.long	0x1002                          # FunctionType: int (int, char**)
+	.asciz	"main"                          # Name
+	.byte	243
+	.byte	242
+	.byte	241
+	# Struct (0x1004)
+	.short	0x1e                            # Record length
+	.short	0x1505                          # Record kind: LF_STRUCTURE
+	.short	0x0                             # MemberCount
+	.short	0x280                           # Properties ( ForwardReference (0x80) | HasUniqueName (0x200) )
+	.long	0x0                             # FieldList
+	.long	0x0                             # DerivedFrom
+	.long	0x0                             # VShape
+	.short	0x0                             # SizeOf
+	.asciz	"S"                             # Name
+	.asciz	".?AUS@@"                       # LinkageName
+	# FieldList (0x1005)
+	.short	0xe                             # Record length
+	.short	0x1203                          # Record kind: LF_FIELDLIST
+	.short	0x150d                          # Member kind: DataMember ( LF_MEMBER )
+	.short	0x3                             # Attrs: Public
+	.long	0                               # Type. It's intentionally written as 0 for testing.
+	.short	0x0                             # FieldOffset
+	.asciz	"x"                             # Name
+	# Struct (0x1006)
+	.short	0x1e                            # Record length
+	.short	0x1505                          # Record kind: LF_STRUCTURE
+	.short	0x1                             # MemberCount
+	.short	0x200                           # Properties ( HasUniqueName (0x200) )
+	.long	0x1005                          # FieldList: <field list>
+	.long	0x0                             # DerivedFrom
+	.long	0x0                             # VShape
+	.short	0x4                             # SizeOf
+	.asciz	"S"                             # Name
+	.asciz	".?AUS@@"                       # LinkageName


        


More information about the lldb-commits mailing list