forked from OSchip/llvm-project
[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
This commit is contained in:
parent
835e09c4c3
commit
5c9f3ec4ad
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue