diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 |
| commit | 94994d372d014ce4c8758b9605d63fae651bd8aa (patch) | |
| tree | 51c0b708bd59f205d6b35cb2a8c24d62f0c33d77 /source/Plugins/SymbolFile/PDB | |
| parent | 39be7ce23363d12ae3e49aeb1fdb2bfeb892e836 (diff) | |
Notes
Diffstat (limited to 'source/Plugins/SymbolFile/PDB')
| -rw-r--r-- | source/Plugins/SymbolFile/PDB/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | source/Plugins/SymbolFile/PDB/PDBASTParser.cpp | 1003 | ||||
| -rw-r--r-- | source/Plugins/SymbolFile/PDB/PDBASTParser.h | 67 | ||||
| -rw-r--r-- | source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp | 640 | ||||
| -rw-r--r-- | source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp | 587 | ||||
| -rw-r--r-- | source/Plugins/SymbolFile/PDB/SymbolFilePDB.h | 69 |
6 files changed, 1771 insertions, 596 deletions
diff --git a/source/Plugins/SymbolFile/PDB/CMakeLists.txt b/source/Plugins/SymbolFile/PDB/CMakeLists.txt index 1c176c32224d..19698a7187f7 100644 --- a/source/Plugins/SymbolFile/PDB/CMakeLists.txt +++ b/source/Plugins/SymbolFile/PDB/CMakeLists.txt @@ -9,6 +9,7 @@ add_lldb_library(lldbPluginSymbolFilePDB PLUGIN lldbCore lldbSymbol lldbUtility + lldbPluginSymbolFileNativePDB LINK_COMPONENTS DebugInfoPDB Support diff --git a/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp index 8bea994aae5d..65e718bedaf1 100644 --- a/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -9,14 +9,19 @@ #include "PDBASTParser.h" +#include "SymbolFilePDB.h" + #include "clang/AST/CharUnits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "lldb/Core/Module.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/ClangUtil.h" #include "lldb/Symbol/Declaration.h" #include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/TypeSystem.h" #include "llvm/DebugInfo/PDB/IPDBLineNumber.h" @@ -33,12 +38,13 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" + using namespace lldb; using namespace lldb_private; using namespace llvm::pdb; -namespace { -int TranslateUdtKind(PDB_UdtType pdb_kind) { +static int TranslateUdtKind(PDB_UdtType pdb_kind) { switch (pdb_kind) { case PDB_UdtType::Class: return clang::TTK_Class; @@ -49,10 +55,10 @@ int TranslateUdtKind(PDB_UdtType pdb_kind) { case PDB_UdtType::Interface: return clang::TTK_Interface; } - return -1; + llvm_unreachable("unsuported PDB UDT type"); } -lldb::Encoding TranslateBuiltinEncoding(PDB_BuiltinType type) { +static lldb::Encoding TranslateBuiltinEncoding(PDB_BuiltinType type) { switch (type) { case PDB_BuiltinType::Float: return lldb::eEncodingIEEE754; @@ -73,7 +79,7 @@ lldb::Encoding TranslateBuiltinEncoding(PDB_BuiltinType type) { } } -lldb::Encoding TranslateEnumEncoding(PDB_VariantType type) { +static lldb::Encoding TranslateEnumEncoding(PDB_VariantType type) { switch (type) { case PDB_VariantType::Int8: case PDB_VariantType::Int16: @@ -94,7 +100,7 @@ lldb::Encoding TranslateEnumEncoding(PDB_VariantType type) { return lldb::eEncodingSint; } -CompilerType +static CompilerType GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast, const PDBSymbolTypeBuiltin &pdb_type, Encoding encoding, uint32_t width) { @@ -109,6 +115,8 @@ GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast, return CompilerType(); case PDB_BuiltinType::Void: return clang_ast.GetBasicType(eBasicTypeVoid); + case PDB_BuiltinType::Char: + return clang_ast.GetBasicType(eBasicTypeChar); case PDB_BuiltinType::Bool: return clang_ast.GetBasicType(eBasicTypeBool); case PDB_BuiltinType::Long: @@ -143,8 +151,8 @@ GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast, return clang_ast.GetBuiltinTypeForEncodingAndBitSize(encoding, width); } -ConstString GetPDBBuiltinTypeName(const PDBSymbolTypeBuiltin &pdb_type, - CompilerType &compiler_type) { +static ConstString GetPDBBuiltinTypeName(const PDBSymbolTypeBuiltin &pdb_type, + CompilerType &compiler_type) { PDB_BuiltinType kind = pdb_type.getBuiltinType(); switch (kind) { default: @@ -175,7 +183,8 @@ ConstString GetPDBBuiltinTypeName(const PDBSymbolTypeBuiltin &pdb_type, return compiler_type.GetTypeName(); } -bool GetDeclarationForSymbol(const PDBSymbol &symbol, Declaration &decl) { +static bool GetDeclarationForSymbol(const PDBSymbol &symbol, + Declaration &decl) { auto &raw_sym = symbol.getRawSymbol(); auto first_line_up = raw_sym.getSrcLineOnTypeDefn(); @@ -193,13 +202,159 @@ bool GetDeclarationForSymbol(const PDBSymbol &symbol, Declaration &decl) { if (!src_file_up) return false; - FileSpec spec(src_file_up->getFileName(), /*resolve_path*/ false); + FileSpec spec(src_file_up->getFileName()); decl.SetFile(spec); decl.SetColumn(first_line_up->getColumnNumber()); decl.SetLine(first_line_up->getLineNumber()); return true; } -} // namespace + +static AccessType TranslateMemberAccess(PDB_MemberAccess access) { + switch (access) { + case PDB_MemberAccess::Private: + return eAccessPrivate; + case PDB_MemberAccess::Protected: + return eAccessProtected; + case PDB_MemberAccess::Public: + return eAccessPublic; + } + return eAccessNone; +} + +static AccessType GetDefaultAccessibilityForUdtKind(PDB_UdtType udt_kind) { + switch (udt_kind) { + case PDB_UdtType::Struct: + case PDB_UdtType::Union: + return eAccessPublic; + case PDB_UdtType::Class: + case PDB_UdtType::Interface: + return eAccessPrivate; + } + llvm_unreachable("unsupported PDB UDT type"); +} + +static AccessType GetAccessibilityForUdt(const PDBSymbolTypeUDT &udt) { + AccessType access = TranslateMemberAccess(udt.getAccess()); + if (access != lldb::eAccessNone || !udt.isNested()) + return access; + + auto parent = udt.getClassParent(); + if (!parent) + return lldb::eAccessNone; + + auto parent_udt = llvm::dyn_cast<PDBSymbolTypeUDT>(parent.get()); + if (!parent_udt) + return lldb::eAccessNone; + + return GetDefaultAccessibilityForUdtKind(parent_udt->getUdtKind()); +} + +static clang::MSInheritanceAttr::Spelling +GetMSInheritance(const PDBSymbolTypeUDT &udt) { + int base_count = 0; + bool has_virtual = false; + + auto bases_enum = udt.findAllChildren<PDBSymbolTypeBaseClass>(); + if (bases_enum) { + while (auto base = bases_enum->getNext()) { + base_count++; + has_virtual |= base->isVirtualBaseClass(); + } + } + + if (has_virtual) + return clang::MSInheritanceAttr::Keyword_virtual_inheritance; + if (base_count > 1) + return clang::MSInheritanceAttr::Keyword_multiple_inheritance; + return clang::MSInheritanceAttr::Keyword_single_inheritance; +} + +static std::unique_ptr<llvm::pdb::PDBSymbol> +GetClassOrFunctionParent(const llvm::pdb::PDBSymbol &symbol) { + const IPDBSession &session = symbol.getSession(); + const IPDBRawSymbol &raw = symbol.getRawSymbol(); + auto tag = symbol.getSymTag(); + + // For items that are nested inside of a class, return the class that it is + // nested inside of. + // Note that only certain items can be nested inside of classes. + switch (tag) { + case PDB_SymType::Function: + case PDB_SymType::Data: + case PDB_SymType::UDT: + case PDB_SymType::Enum: + case PDB_SymType::FunctionSig: + case PDB_SymType::Typedef: + case PDB_SymType::BaseClass: + case PDB_SymType::VTable: { + auto class_parent_id = raw.getClassParentId(); + if (auto class_parent = session.getSymbolById(class_parent_id)) + return class_parent; + break; + } + default: + break; + } + + // Otherwise, if it is nested inside of a function, return the function. + // Note that only certain items can be nested inside of functions. + switch (tag) { + case PDB_SymType::Block: + case PDB_SymType::Data: { + auto lexical_parent_id = raw.getLexicalParentId(); + auto lexical_parent = session.getSymbolById(lexical_parent_id); + if (!lexical_parent) + return nullptr; + + auto lexical_parent_tag = lexical_parent->getSymTag(); + if (lexical_parent_tag == PDB_SymType::Function) + return lexical_parent; + if (lexical_parent_tag == PDB_SymType::Exe) + return nullptr; + + return GetClassOrFunctionParent(*lexical_parent); + } + default: + return nullptr; + } +} + +static clang::NamedDecl * +GetDeclFromContextByName(const clang::ASTContext &ast, + const clang::DeclContext &decl_context, + llvm::StringRef name) { + clang::IdentifierInfo &ident = ast.Idents.get(name); + clang::DeclarationName decl_name = ast.DeclarationNames.getIdentifier(&ident); + clang::DeclContext::lookup_result result = decl_context.lookup(decl_name); + if (result.empty()) + return nullptr; + + return result[0]; +} + +static bool IsAnonymousNamespaceName(llvm::StringRef name) { + return name == "`anonymous namespace'" || name == "`anonymous-namespace'"; +} + +static clang::CallingConv TranslateCallingConvention(PDB_CallingConv pdb_cc) { + switch (pdb_cc) { + case llvm::codeview::CallingConvention::NearC: + return clang::CC_C; + case llvm::codeview::CallingConvention::NearStdCall: + return clang::CC_X86StdCall; + case llvm::codeview::CallingConvention::NearFast: + return clang::CC_X86FastCall; + case llvm::codeview::CallingConvention::ThisCall: + return clang::CC_X86ThisCall; + case llvm::codeview::CallingConvention::NearVector: + return clang::CC_X86VectorCall; + case llvm::codeview::CallingConvention::NearPascal: + return clang::CC_X86Pascal; + default: + assert(false && "Unknown calling convention"); + return clang::CC_C; + } +} PDBASTParser::PDBASTParser(lldb_private::ClangASTContext &ast) : m_ast(ast) {} @@ -208,76 +363,167 @@ PDBASTParser::~PDBASTParser() {} // DebugInfoASTParser interface lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { - // PDB doesn't maintain enough information to robustly rebuild the entire - // tree, and this is most problematic when it comes to figure out the right - // DeclContext to put a type in. So for now, everything goes in the - // translation unit decl as a fully qualified type. - clang::DeclContext *tu_decl_ctx = m_ast.GetTranslationUnitDecl(); Declaration decl; - switch (type.getSymTag()) { + case PDB_SymType::BaseClass: { + auto symbol_file = m_ast.GetSymbolFile(); + if (!symbol_file) + return nullptr; + + auto ty = symbol_file->ResolveTypeUID(type.getRawSymbol().getTypeId()); + return ty ? ty->shared_from_this() : nullptr; + } break; case PDB_SymType::UDT: { auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&type); assert(udt); - AccessType access = lldb::eAccessPublic; - PDB_UdtType udt_kind = udt->getUdtKind(); - auto tag_type_kind = TranslateUdtKind(udt_kind); - if (tag_type_kind == -1) + + // Note that, unnamed UDT being typedef-ed is generated as a UDT symbol + // other than a Typedef symbol in PDB. For example, + // typedef union { short Row; short Col; } Union; + // is generated as a named UDT in PDB: + // union Union { short Row; short Col; } + // Such symbols will be handled here. + + // Some UDT with trival ctor has zero length. Just ignore. + if (udt->getLength() == 0) + return nullptr; + + // Ignore unnamed-tag UDTs. + std::string name = MSVCUndecoratedNameParser::DropScope(udt->getName()); + if (name.empty()) return nullptr; - if (udt_kind == PDB_UdtType::Class) - access = lldb::eAccessPrivate; + auto decl_context = GetDeclContextContainingSymbol(type); - CompilerType clang_type = m_ast.CreateRecordType( - tu_decl_ctx, access, udt->getName().c_str(), tag_type_kind, - lldb::eLanguageTypeC_plus_plus, nullptr); + // Check if such an UDT already exists in the current context. + // This may occur with const or volatile types. There are separate type + // symbols in PDB for types with const or volatile modifiers, but we need + // to create only one declaration for them all. + Type::ResolveStateTag type_resolve_state_tag; + CompilerType clang_type = m_ast.GetTypeForIdentifier<clang::CXXRecordDecl>( + ConstString(name), decl_context); + if (!clang_type.IsValid()) { + auto access = GetAccessibilityForUdt(*udt); - m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); + auto tag_type_kind = TranslateUdtKind(udt->getUdtKind()); + ClangASTMetadata metadata; + metadata.SetUserID(type.getSymIndexId()); + metadata.SetIsDynamicCXXType(false); + + clang_type = m_ast.CreateRecordType( + decl_context, access, name.c_str(), tag_type_kind, + lldb::eLanguageTypeC_plus_plus, &metadata); + assert(clang_type.IsValid()); + + auto record_decl = + m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + assert(record_decl); + m_uid_to_decl[type.getSymIndexId()] = record_decl; + + auto inheritance_attr = clang::MSInheritanceAttr::CreateImplicit( + *m_ast.getASTContext(), GetMSInheritance(*udt)); + record_decl->addAttr(inheritance_attr); + + ClangASTContext::StartTagDeclarationDefinition(clang_type); + + auto children = udt->findAllChildren(); + if (!children || children->getChildCount() == 0) { + // PDB does not have symbol of forwarder. We assume we get an udt w/o + // any fields. Just complete it at this point. + ClangASTContext::CompleteTagDeclarationDefinition(clang_type); + + ClangASTContext::SetHasExternalStorage(clang_type.GetOpaqueQualType(), + false); + + type_resolve_state_tag = Type::eResolveStateFull; + } else { + // Add the type to the forward declarations. It will help us to avoid + // an endless recursion in CompleteTypeFromUdt function. + m_forward_decl_to_uid[record_decl] = type.getSymIndexId(); + + ClangASTContext::SetHasExternalStorage(clang_type.GetOpaqueQualType(), + true); + + type_resolve_state_tag = Type::eResolveStateForward; + } + } else + type_resolve_state_tag = Type::eResolveStateForward; + + if (udt->isConstType()) + clang_type = clang_type.AddConstModifier(); + + if (udt->isVolatileType()) + clang_type = clang_type.AddVolatileModifier(); + + GetDeclarationForSymbol(type, decl); return std::make_shared<lldb_private::Type>( - type.getSymIndexId(), m_ast.GetSymbolFile(), - ConstString(udt->getName()), udt->getLength(), nullptr, - LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, clang_type, - lldb_private::Type::eResolveStateForward); + type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), + udt->getLength(), nullptr, LLDB_INVALID_UID, + lldb_private::Type::eEncodingIsUID, decl, clang_type, + type_resolve_state_tag); } break; case PDB_SymType::Enum: { auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type); assert(enum_type); - auto underlying_type_up = enum_type->getUnderlyingType(); - if (!underlying_type_up) - return nullptr; - lldb::Encoding encoding = - TranslateBuiltinEncoding(underlying_type_up->getBuiltinType()); - // FIXME: Type of underlying builtin is always `Int`. We correct it with - // the very first enumerator's encoding if any. - auto first_child = enum_type->findOneChild<PDBSymbolData>(); - if (first_child) { - encoding = TranslateEnumEncoding(first_child->getValue().Type); - } - std::string name = enum_type->getName(); + + std::string name = + MSVCUndecoratedNameParser::DropScope(enum_type->getName()); + auto decl_context = GetDeclContextContainingSymbol(type); uint64_t bytes = enum_type->getLength(); - CompilerType builtin_type; - if (bytes > 0) - builtin_type = GetBuiltinTypeForPDBEncodingAndBitSize( - m_ast, *underlying_type_up, encoding, bytes * 8); - else - builtin_type = m_ast.GetBasicType(eBasicTypeInt); - // FIXME: PDB does not have information about scoped enumeration (Enum - // Class). Set it false for now. - bool isScoped = false; - CompilerType ast_enum = m_ast.CreateEnumerationType( - name.c_str(), tu_decl_ctx, decl, builtin_type, isScoped); - auto enum_values = enum_type->findAllChildren<PDBSymbolData>(); - if (enum_values) { - while (auto enum_value = enum_values->getNext()) { - if (enum_value->getDataKind() != PDB_DataKind::Constant) - continue; - AddEnumValue(ast_enum, *enum_value); + // Check if such an enum already exists in the current context + CompilerType ast_enum = m_ast.GetTypeForIdentifier<clang::EnumDecl>( + ConstString(name), decl_context); + if (!ast_enum.IsValid()) { + auto underlying_type_up = enum_type->getUnderlyingType(); + if (!underlying_type_up) + return nullptr; + + lldb::Encoding encoding = + TranslateBuiltinEncoding(underlying_type_up->getBuiltinType()); + // FIXME: Type of underlying builtin is always `Int`. We correct it with + // the very first enumerator's encoding if any. + auto first_child = enum_type->findOneChild<PDBSymbolData>(); + if (first_child) + encoding = TranslateEnumEncoding(first_child->getValue().Type); + + CompilerType builtin_type; + if (bytes > 0) + builtin_type = GetBuiltinTypeForPDBEncodingAndBitSize( + m_ast, *underlying_type_up, encoding, bytes * 8); + else + builtin_type = m_ast.GetBasicType(eBasicTypeInt); + + // FIXME: PDB does not have information about scoped enumeration (Enum + // Class). Set it false for now. + bool isScoped = false; + + ast_enum = m_ast.CreateEnumerationType(name.c_str(), decl_context, decl, + builtin_type, isScoped); + + auto enum_decl = ClangASTContext::GetAsEnumDecl(ast_enum); + assert(enum_decl); + m_uid_to_decl[type.getSymIndexId()] = enum_decl; + + auto enum_values = enum_type->findAllChildren<PDBSymbolData>(); + if (enum_values) { + while (auto enum_value = enum_values->getNext()) { + if (enum_value->getDataKind() != PDB_DataKind::Constant) + continue; + AddEnumValue(ast_enum, *enum_value); + } } + + if (ClangASTContext::StartTagDeclarationDefinition(ast_enum)) + ClangASTContext::CompleteTagDeclarationDefinition(ast_enum); } - if (ClangASTContext::StartTagDeclarationDefinition(ast_enum)) - ClangASTContext::CompleteTagDeclarationDefinition(ast_enum); + + if (enum_type->isConstType()) + ast_enum = ast_enum.AddConstModifier(); + + if (enum_type->isVolatileType()) + ast_enum = ast_enum.AddVolatileModifier(); GetDeclarationForSymbol(type, decl); return std::make_shared<lldb_private::Type>( @@ -288,23 +534,43 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { case PDB_SymType::Typedef: { auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type); assert(type_def); + lldb_private::Type *target_type = m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId()); if (!target_type) return nullptr; - std::string name = type_def->getName(); - uint64_t bytes = type_def->getLength(); - CompilerType target_ast_type = target_type->GetFullCompilerType(); - CompilerDeclContext target_decl_ctx = - m_ast.GetSymbolFile()->GetDeclContextForUID(target_type->GetID()); + + std::string name = + MSVCUndecoratedNameParser::DropScope(type_def->getName()); + auto decl_ctx = GetDeclContextContainingSymbol(type); + + // Check if such a typedef already exists in the current context CompilerType ast_typedef = - m_ast.CreateTypedefType(target_ast_type, name.c_str(), target_decl_ctx); - if (!ast_typedef) - return nullptr; + m_ast.GetTypeForIdentifier<clang::TypedefNameDecl>(ConstString(name), + decl_ctx); + if (!ast_typedef.IsValid()) { + CompilerType target_ast_type = target_type->GetFullCompilerType(); + + ast_typedef = m_ast.CreateTypedefType( + target_ast_type, name.c_str(), CompilerDeclContext(&m_ast, decl_ctx)); + if (!ast_typedef) + return nullptr; + + auto typedef_decl = ClangASTContext::GetAsTypedefDecl(ast_typedef); + assert(typedef_decl); + m_uid_to_decl[type.getSymIndexId()] = typedef_decl; + } + + if (type_def->isConstType()) + ast_typedef = ast_typedef.AddConstModifier(); + if (type_def->isVolatileType()) + ast_typedef = ast_typedef.AddVolatileModifier(); + + GetDeclarationForSymbol(type, decl); return std::make_shared<lldb_private::Type>( type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), - bytes, nullptr, target_type->GetID(), + type_def->getLength(), nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID, decl, ast_typedef, lldb_private::Type::eResolveStateFull); } break; @@ -321,7 +587,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { return nullptr; func_sig = sig.release(); // Function type is named. - name = pdb_func->getName(); + name = MSVCUndecoratedNameParser::DropScope(pdb_func->getName()); } else if (auto pdb_func_sig = llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type)) { func_sig = const_cast<PDBSymbolTypeFunctionSig *>(pdb_func_sig); @@ -364,9 +630,10 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { type_quals |= clang::Qualifiers::Const; if (func_sig->isVolatileType()) type_quals |= clang::Qualifiers::Volatile; + auto cc = TranslateCallingConvention(func_sig->getCallingConvention()); CompilerType func_sig_ast_type = m_ast.CreateFunctionType(return_ast_type, arg_list.data(), - arg_list.size(), is_variadic, type_quals); + arg_list.size(), is_variadic, type_quals, cc); GetDeclarationForSymbol(type, decl); return std::make_shared<lldb_private::Type>( @@ -391,7 +658,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { CompilerType element_ast_type = element_type->GetForwardCompilerType(); // If element type is UDT, it needs to be complete. if (ClangASTContext::IsCXXClassType(element_ast_type) && - element_ast_type.GetCompleteType() == false) { + !element_ast_type.GetCompleteType()) { if (ClangASTContext::StartTagDeclarationDefinition(element_ast_type)) { ClangASTContext::CompleteTagDeclarationDefinition(element_ast_type); } else { @@ -441,6 +708,26 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { if (!pointee_type) return nullptr; + if (pointer_type->isPointerToDataMember() || + pointer_type->isPointerToMemberFunction()) { + auto class_parent_uid = pointer_type->getRawSymbol().getClassParentId(); + auto class_parent_type = + m_ast.GetSymbolFile()->ResolveTypeUID(class_parent_uid); + assert(class_parent_type); + + CompilerType pointer_ast_type; + pointer_ast_type = ClangASTContext::CreateMemberPointerType( + class_parent_type->GetLayoutCompilerType(), + pointee_type->GetForwardCompilerType()); + assert(pointer_ast_type); + + return std::make_shared<lldb_private::Type>( + pointer_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), + pointer_type->getLength(), nullptr, LLDB_INVALID_UID, + lldb_private::Type::eEncodingIsUID, decl, pointer_ast_type, + lldb_private::Type::eResolveStateForward); + } + CompilerType pointer_ast_type; pointer_ast_type = pointee_type->GetFullCompilerType(); if (pointer_type->isReference()) @@ -471,11 +758,363 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { return nullptr; } +bool PDBASTParser::CompleteTypeFromPDB( + lldb_private::CompilerType &compiler_type) { + if (GetClangASTImporter().CanImport(compiler_type)) + return GetClangASTImporter().CompleteType(compiler_type); + + // Remove the type from the forward declarations to avoid + // an endless recursion for types like a linked list. + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(compiler_type.GetOpaqueQualType()); + auto uid_it = m_forward_decl_to_uid.find(record_decl); + if (uid_it == m_forward_decl_to_uid.end()) + return true; + + auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile()); + if (!symbol_file) + return false; + + std::unique_ptr<PDBSymbol> symbol = + symbol_file->GetPDBSession().getSymbolById(uid_it->getSecond()); + if (!symbol) + return false; + + m_forward_decl_to_uid.erase(uid_it); + + ClangASTContext::SetHasExternalStorage(compiler_type.GetOpaqueQualType(), + false); + + switch (symbol->getSymTag()) { + case PDB_SymType::UDT: { + auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(symbol.get()); + if (!udt) + return false; + + return CompleteTypeFromUDT(*symbol_file, compiler_type, *udt); + } + default: + llvm_unreachable("not a forward clang type decl!"); + } +} + +clang::Decl * +PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { + uint32_t sym_id = symbol.getSymIndexId(); + auto it = m_uid_to_decl.find(sym_id); + if (it != m_uid_to_decl.end()) + return it->second; + + auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile()); + if (!symbol_file) + return nullptr; + + // First of all, check if the symbol is a member of a class. Resolve the full + // class type and return the declaration from the cache if so. + auto tag = symbol.getSymTag(); + if (tag == PDB_SymType::Data || tag == PDB_SymType::Function) { + const IPDBSession &session = symbol.getSession(); + const IPDBRawSymbol &raw = symbol.getRawSymbol(); + + auto class_parent_id = raw.getClassParentId(); + if (std::unique_ptr<PDBSymbol> class_parent = + session.getSymbolById(class_parent_id)) { + auto class_parent_type = symbol_file->ResolveTypeUID(class_parent_id); + if (!class_parent_type) + return nullptr; + + CompilerType class_parent_ct = class_parent_type->GetFullCompilerType(); + + // Look a declaration up in the cache after completing the class + clang::Decl *decl = m_uid_to_decl.lookup(sym_id); + if (decl) + return decl; + + // A declaration was not found in the cache. It means that the symbol + // has the class parent, but the class doesn't have the symbol in its + // children list. + if (auto func = llvm::dyn_cast_or_null<PDBSymbolFunc>(&symbol)) { + // Try to find a class child method with the same RVA and use its + // declaration if found. + if (uint32_t rva = func->getRelativeVirtualAddress()) { + if (std::unique_ptr<ConcreteSymbolEnumerator<PDBSymbolFunc>> + methods_enum = + class_parent->findAllChildren<PDBSymbolFunc>()) { + while (std::unique_ptr<PDBSymbolFunc> method = + methods_enum->getNext()) { + if (method->getRelativeVirtualAddress() == rva) { + decl = m_uid_to_decl.lookup(method->getSymIndexId()); + if (decl) + break; + } + } + } + } + + // If no class methods with the same RVA were found, then create a new + // method. It is possible for template methods. + if (!decl) + decl = AddRecordMethod(*symbol_file, class_parent_ct, *func); + } + + if (decl) + m_uid_to_decl[sym_id] = decl; + + return decl; + } + } + + // If we are here, then the symbol is not belonging to a class and is not + // contained in the cache. So create a declaration for it. + switch (symbol.getSymTag()) { + case PDB_SymType::Data: { + auto data = llvm::dyn_cast<PDBSymbolData>(&symbol); + assert(data); + + auto decl_context = GetDeclContextContainingSymbol(symbol); + assert(decl_context); + + // May be the current context is a class really, but we haven't found + // any class parent. This happens e.g. in the case of class static + // variables - they has two symbols, one is a child of the class when + // another is a child of the exe. So always complete the parent and use + // an existing declaration if possible. + if (auto parent_decl = llvm::dyn_cast_or_null<clang::TagDecl>(decl_context)) + m_ast.GetCompleteDecl(parent_decl); + + std::string name = MSVCUndecoratedNameParser::DropScope(data->getName()); + + // Check if the current context already contains the symbol with the name. + clang::Decl *decl = + GetDeclFromContextByName(*m_ast.getASTContext(), *decl_context, name); + if (!decl) { + auto type = symbol_file->ResolveTypeUID(data->getTypeId()); + if (!type) + return nullptr; + + decl = m_ast.CreateVariableDeclaration( + decl_context, name.c_str(), + ClangUtil::GetQualType(type->GetLayoutCompilerType())); + } + + m_uid_to_decl[sym_id] = decl; + + return decl; + } + case PDB_SymType::Function: { + auto func = llvm::dyn_cast<PDBSymbolFunc>(&symbol); + assert(func); + + auto decl_context = GetDeclContextContainingSymbol(symbol); + assert(decl_context); + + std::string name = MSVCUndecoratedNameParser::DropScope(func->getName()); + + Type *type = symbol_file->ResolveTypeUID(sym_id); + if (!type) + return nullptr; + + auto storage = func->isStatic() ? clang::StorageClass::SC_Static + : clang::StorageClass::SC_None; + + auto decl = m_ast.CreateFunctionDeclaration( + decl_context, name.c_str(), type->GetForwardCompilerType(), storage, + func->hasInlineAttribute()); + + std::vector<clang::ParmVarDecl *> params; + if (std::unique_ptr<PDBSymbolTypeFunctionSig> sig = func->getSignature()) { + if (std::unique_ptr<ConcreteSymbolEnumerator<PDBSymbolTypeFunctionArg>> + arg_enum = sig->findAllChildren<PDBSymbolTypeFunctionArg>()) { + while (std::unique_ptr<PDBSymbolTypeFunctionArg> arg = + arg_enum->getNext()) { + Type *arg_type = symbol_file->ResolveTypeUID(arg->getTypeId()); + if (!arg_type) + continue; + + clang::ParmVarDecl *param = m_ast.CreateParameterDeclaration( + decl, nullptr, arg_type->GetForwardCompilerType(), + clang::SC_None); + if (param) + params.push_back(param); + } + } + } + if (params.size()) + m_ast.SetFunctionParameters(decl, params.data(), params.size()); + + m_uid_to_decl[sym_id] = decl; + + return decl; + } + default: { + // It's not a variable and not a function, check if it's a type + Type *type = symbol_file->ResolveTypeUID(sym_id); + if (!type) + return nullptr; + + return m_uid_to_decl.lookup(sym_id); + } + } +} + +clang::DeclContext * +PDBASTParser::GetDeclContextForSymbol(const llvm::pdb::PDBSymbol &symbol) { + if (symbol.getSymTag() == PDB_SymType::Function) { + clang::DeclContext *result = + llvm::dyn_cast_or_null<clang::FunctionDecl>(GetDeclForSymbol(symbol)); + + if (result) + m_decl_context_to_uid[result] = symbol.getSymIndexId(); + + return result; + } + + auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile()); + if (!symbol_file) + return nullptr; + + auto type = symbol_file->ResolveTypeUID(symbol.getSymIndexId()); + if (!type) + return nullptr; + + clang::DeclContext *result = + m_ast.GetDeclContextForType(type->GetForwardCompilerType()); + + if (result) + m_decl_context_to_uid[result] = symbol.getSymIndexId(); + + return result; +} + +clang::DeclContext *PDBASTParser::GetDeclContextContainingSymbol( + const llvm::pdb::PDBSymbol &symbol) { + auto parent = GetClassOrFunctionParent(symbol); + while (parent) { + if (auto parent_context = GetDeclContextForSymbol(*parent)) + return parent_context; + + parent = GetClassOrFunctionParent(*parent); + } + + // We can't find any class or function parent of the symbol. So analyze + // the full symbol name. The symbol may be belonging to a namespace + // or function (or even to a class if it's e.g. a static variable symbol). + + // TODO: Make clang to emit full names for variables in namespaces + // (as MSVC does) + + std::string name(symbol.getRawSymbol().getName()); + MSVCUndecoratedNameParser parser(name); + llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers(); + if (specs.empty()) + return m_ast.GetTranslationUnitDecl(); + + auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile()); + if (!symbol_file) + return m_ast.GetTranslationUnitDecl(); + + auto global = symbol_file->GetPDBSession().getGlobalScope(); + if (!global) + return m_ast.GetTranslationUnitDecl(); + + bool has_type_or_function_parent = false; + clang::DeclContext *curr_context = m_ast.GetTranslationUnitDecl(); + for (std::size_t i = 0; i < specs.size() - 1; i++) { + // Check if there is a function or a type with the current context's name. + if (std::unique_ptr<IPDBEnumSymbols> children_enum = global->findChildren( + PDB_SymType::None, specs[i].GetFullName(), NS_CaseSensitive)) { + while (IPDBEnumChildren<PDBSymbol>::ChildTypePtr child = + children_enum->getNext()) { + if (clang::DeclContext *child_context = + GetDeclContextForSymbol(*child)) { + // Note that `GetDeclContextForSymbol' retrieves + // a declaration context for functions and types only, + // so if we are here then `child_context' is guaranteed + // a function or a type declaration context. + has_type_or_function_parent = true; + curr_context = child_context; + } + } + } + + // If there were no functions or types above then retrieve a namespace with + // the current context's name. There can be no namespaces inside a function + // or a type. We check it to avoid fake namespaces such as `__l2': + // `N0::N1::CClass::PrivateFunc::__l2::InnerFuncStruct' + if (!has_type_or_function_parent) { + std::string namespace_name = specs[i].GetBaseName(); + const char *namespace_name_c_str = + IsAnonymousNamespaceName(namespace_name) ? nullptr + : namespace_name.data(); + clang::NamespaceDecl *namespace_decl = + m_ast.GetUniqueNamespaceDeclaration(namespace_name_c_str, + curr_context); + + m_parent_to_namespaces[curr_context].insert(namespace_decl); + m_namespaces.insert(namespace_decl); + + curr_context = namespace_decl; + } + } + + return curr_context; +} + +void PDBASTParser::ParseDeclsForDeclContext( + const clang::DeclContext *decl_context) { + auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile()); + if (!symbol_file) + return; + + IPDBSession &session = symbol_file->GetPDBSession(); + auto symbol_up = + session.getSymbolById(m_decl_context_to_uid.lookup(decl_context)); + auto global_up = session.getGlobalScope(); + + PDBSymbol *symbol; + if (symbol_up) + symbol = symbol_up.get(); + else if (global_up) + symbol = global_up.get(); + else + return; + + if (auto children = symbol->findAllChildren()) + while (auto child = children->getNext()) + GetDeclForSymbol(*child); +} + +clang::NamespaceDecl * +PDBASTParser::FindNamespaceDecl(const clang::DeclContext *parent, + llvm::StringRef name) { + NamespacesSet *set; + if (parent) { + auto pit = m_parent_to_namespaces.find(parent); + if (pit == m_parent_to_namespaces.end()) + return nullptr; + + set = &pit->second; + } else { + set = &m_namespaces; + } + assert(set); + + for (clang::NamespaceDecl *namespace_decl : *set) + if (namespace_decl->getName().equals(name)) + return namespace_decl; + + for (clang::NamespaceDecl *namespace_decl : *set) + if (namespace_decl->isAnonymousNamespace()) + return FindNamespaceDecl(namespace_decl, name); + + return nullptr; +} + bool PDBASTParser::AddEnumValue(CompilerType enum_type, - const PDBSymbolData &enum_value) const { + const PDBSymbolData &enum_value) { Declaration decl; Variant v = enum_value.getValue(); - std::string name = enum_value.getName(); + std::string name = MSVCUndecoratedNameParser::DropScope(enum_value.getName()); int64_t raw_value; switch (v.Type) { case PDB_VariantType::Int8: @@ -509,7 +1148,213 @@ bool PDBASTParser::AddEnumValue(CompilerType enum_type, m_ast.GetEnumerationIntegerType(enum_type.GetOpaqueQualType()); uint32_t byte_size = m_ast.getASTContext()->getTypeSize( ClangUtil::GetQualType(underlying_type)); - return m_ast.AddEnumerationValueToEnumerationType( - enum_type.GetOpaqueQualType(), underlying_type, decl, name.c_str(), - raw_value, byte_size * 8); + auto enum_constant_decl = m_ast.AddEnumerationValueToEnumerationType( + enum_type, decl, name.c_str(), raw_value, byte_size * 8); + if (!enum_constant_decl) + return false; + + m_uid_to_decl[enum_value.getSymIndexId()] = enum_constant_decl; + + return true; +} + +bool PDBASTParser::CompleteTypeFromUDT( + lldb_private::SymbolFile &symbol_file, + lldb_private::CompilerType &compiler_type, + llvm::pdb::PDBSymbolTypeUDT &udt) { + ClangASTImporter::LayoutInfo layout_info; + layout_info.bit_size = udt.getLength() * 8; + + auto nested_enums = udt.findAllChildren<PDBSymbolTypeUDT>(); + if (nested_enums) + while (auto nested = nested_enums->getNext()) + symbol_file.ResolveTypeUID(nested->getSymIndexId()); + + auto bases_enum = udt.findAllChildren<PDBSymbolTypeBaseClass>(); + if (bases_enum) + AddRecordBases(symbol_file, compiler_type, + TranslateUdtKind(udt.getUdtKind()), *bases_enum, + layout_info); + + auto members_enum = udt.findAllChildren<PDBSymbolData>(); + if (members_enum) + AddRecordMembers(symbol_file, compiler_type, *members_enum, layout_info); + + auto methods_enum = udt.findAllChildren<PDBSymbolFunc>(); + if (methods_enum) + AddRecordMethods(symbol_file, compiler_type, *methods_enum); + + m_ast.AddMethodOverridesForCXXRecordType(compiler_type.GetOpaqueQualType()); + ClangASTContext::BuildIndirectFields(compiler_type); + ClangASTContext::CompleteTagDeclarationDefinition(compiler_type); + + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(compiler_type.GetOpaqueQualType()); + if (!record_decl) + return static_cast<bool>(compiler_type); + + GetClangASTImporter().InsertRecordDecl(record_decl, layout_info); + + return static_cast<bool>(compiler_type); +} + +void PDBASTParser::AddRecordMembers( + lldb_private::SymbolFile &symbol_file, + lldb_private::CompilerType &record_type, + PDBDataSymbolEnumerator &members_enum, + lldb_private::ClangASTImporter::LayoutInfo &layout_info) { + while (auto member = members_enum.getNext()) { + if (member->isCompilerGenerated()) + continue; + + auto member_name = member->getName(); + + auto member_type = symbol_file.ResolveTypeUID(member->getTypeId()); + if (!member_type) + continue; + + auto member_comp_type = member_type->GetLayoutCompilerType(); + if (!member_comp_type.GetCompleteType()) { + symbol_file.GetObjectFile()->GetModule()->ReportError( + ":: Class '%s' has a member '%s' of type '%s' " + "which does not have a complete definition.", + record_type.GetTypeName().GetCString(), member_name.c_str(), + member_comp_type.GetTypeName().GetCString()); + if (ClangASTContext::StartTagDeclarationDefinition(member_comp_type)) + ClangASTContext::CompleteTagDeclarationDefinition(member_comp_type); + } + + auto access = TranslateMemberAccess(member->getAccess()); + + switch (member->getDataKind()) { + case PDB_DataKind::Member: { + auto location_type = member->getLocationType(); + + auto bit_size = member->getLength(); + if (location_type == PDB_LocType::ThisRel) + bit_size *= 8; + + auto decl = ClangASTContext::AddFieldToRecordType( + record_type, member_name.c_str(), member_comp_type, access, bit_size); + if (!decl) + continue; + + m_uid_to_decl[member->getSymIndexId()] = decl; + + auto offset = member->getOffset() * 8; + if (location_type == PDB_LocType::BitField) + offset += member->getBitPosition(); + + layout_info.field_offsets.insert(std::make_pair(decl, offset)); + + break; + } + case PDB_DataKind::StaticMember: { + auto decl = ClangASTContext::AddVariableToRecordType( + record_type, member_name.c_str(), member_comp_type, access); + if (!decl) + continue; + + m_uid_to_decl[member->getSymIndexId()] = decl; + + break; + } + default: + llvm_unreachable("unsupported PDB data kind"); + } + } +} + +void PDBASTParser::AddRecordBases( + lldb_private::SymbolFile &symbol_file, + lldb_private::CompilerType &record_type, int record_kind, + PDBBaseClassSymbolEnumerator &bases_enum, + lldb_private::ClangASTImporter::LayoutInfo &layout_info) const { + std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> base_classes; + + while (auto base = bases_enum.getNext()) { + auto base_type = symbol_file.ResolveTypeUID(base->getTypeId()); + if (!base_type) + continue; + + auto base_comp_type = base_type->GetFullCompilerType(); + if (!base_comp_type.GetCompleteType()) { + symbol_file.GetObjectFile()->GetModule()->ReportError( + ":: Class '%s' has a base class '%s' " + "which does not have a complete definition.", + record_type.GetTypeName().GetCString(), + base_comp_type.GetTypeName().GetCString()); + if (ClangASTContext::StartTagDeclarationDefinition(base_comp_type)) + ClangASTContext::CompleteTagDeclarationDefinition(base_comp_type); + } + + auto access = TranslateMemberAccess(base->getAccess()); + + auto is_virtual = base->isVirtualBaseClass(); + + std::unique_ptr<clang::CXXBaseSpecifier> base_spec = + m_ast.CreateBaseClassSpecifier(base_comp_type.GetOpaqueQualType(), + access, is_virtual, + record_kind == clang::TTK_Class); + lldbassert(base_spec); + + base_classes.push_back(std::move(base_spec)); + + if (is_virtual) + continue; + + auto decl = m_ast.GetAsCXXRecordDecl(base_comp_type.GetOpaqueQualType()); + if (!decl) + continue; + + auto offset = clang::CharUnits::fromQuantity(base->getOffset()); + layout_info.base_offsets.insert(std::make_pair(decl, offset)); + } + + m_ast.TransferBaseClasses(record_type.GetOpaqueQualType(), + std::move(base_classes)); +} + +void PDBASTParser::AddRecordMethods(lldb_private::SymbolFile &symbol_file, + lldb_private::CompilerType &record_type, + PDBFuncSymbolEnumerator &methods_enum) { + while (std::unique_ptr<PDBSymbolFunc> method = methods_enum.getNext()) + if (clang::CXXMethodDecl *decl = + AddRecordMethod(symbol_file, record_type, *method)) + m_uid_to_decl[method->getSymIndexId()] = decl; +} + +clang::CXXMethodDecl * +PDBASTParser::AddRecordMethod(lldb_private::SymbolFile &symbol_file, + lldb_private::CompilerType &record_type, + const llvm::pdb::PDBSymbolFunc &method) const { + std::string name = MSVCUndecoratedNameParser::DropScope(method.getName()); + + Type *method_type = symbol_file.ResolveTypeUID(method.getSymIndexId()); + // MSVC specific __vecDelDtor. + if (!method_type) + return nullptr; + + CompilerType method_comp_type = method_type->GetFullCompilerType(); + if (!method_comp_type.GetCompleteType()) { + symbol_file.GetObjectFile()->GetModule()->ReportError( + ":: Class '%s' has a method '%s' whose type cannot be completed.", + record_type.GetTypeName().GetCString(), + method_comp_type.GetTypeName().GetCString()); + if (ClangASTContext::StartTagDeclarationDefinition(method_comp_type)) + ClangASTContext::CompleteTagDeclarationDefinition(method_comp_type); + } + + AccessType access = TranslateMemberAccess(method.getAccess()); + if (access == eAccessNone) + access = eAccessPublic; + + // TODO: get mangled name for the method. + return m_ast.AddMethodToCXXRecordType( + record_type.GetOpaqueQualType(), name.c_str(), + /*mangled_name*/ nullptr, method_comp_type, access, method.isVirtual(), + method.isStatic(), method.hasInlineAttribute(), + /*is_explicit*/ false, // FIXME: Need this field in CodeView. + /*is_attr_used*/ false, + /*is_artificial*/ method.isCompilerGenerated()); } diff --git a/source/Plugins/SymbolFile/PDB/PDBASTParser.h b/source/Plugins/SymbolFile/PDB/PDBASTParser.h index d1ac138b8115..02353870ab60 100644 --- a/source/Plugins/SymbolFile/PDB/PDBASTParser.h +++ b/source/Plugins/SymbolFile/PDB/PDBASTParser.h @@ -14,6 +14,8 @@ #include "lldb/Symbol/ClangASTImporter.h" +class SymbolFilePDB; + namespace clang { class CharUnits; class CXXRecordDecl; @@ -28,9 +30,14 @@ class CompilerType; namespace llvm { namespace pdb { +template <typename ChildType> class ConcreteSymbolEnumerator; + class PDBSymbol; class PDBSymbolData; +class PDBSymbolFunc; +class PDBSymbolTypeBaseClass; class PDBSymbolTypeBuiltin; +class PDBSymbolTypeUDT; } // namespace pdb } // namespace llvm @@ -40,13 +47,71 @@ public: ~PDBASTParser(); lldb::TypeSP CreateLLDBTypeFromPDBType(const llvm::pdb::PDBSymbol &type); + bool CompleteTypeFromPDB(lldb_private::CompilerType &compiler_type); + + clang::Decl *GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol); + + clang::DeclContext * + GetDeclContextForSymbol(const llvm::pdb::PDBSymbol &symbol); + clang::DeclContext * + GetDeclContextContainingSymbol(const llvm::pdb::PDBSymbol &symbol); + + void ParseDeclsForDeclContext(const clang::DeclContext *decl_context); + + clang::NamespaceDecl *FindNamespaceDecl(const clang::DeclContext *parent, + llvm::StringRef name); + + lldb_private::ClangASTImporter &GetClangASTImporter() { + return m_ast_importer; + } private: + typedef llvm::DenseMap<clang::CXXRecordDecl *, lldb::user_id_t> + CXXRecordDeclToUidMap; + typedef llvm::DenseMap<lldb::user_id_t, clang::Decl *> UidToDeclMap; + typedef std::set<clang::NamespaceDecl *> NamespacesSet; + typedef llvm::DenseMap<clang::DeclContext *, NamespacesSet> + ParentToNamespacesMap; + typedef llvm::DenseMap<clang::DeclContext *, lldb::user_id_t> + DeclContextToUidMap; + typedef llvm::pdb::ConcreteSymbolEnumerator<llvm::pdb::PDBSymbolData> + PDBDataSymbolEnumerator; + typedef llvm::pdb::ConcreteSymbolEnumerator<llvm::pdb::PDBSymbolTypeBaseClass> + PDBBaseClassSymbolEnumerator; + typedef llvm::pdb::ConcreteSymbolEnumerator<llvm::pdb::PDBSymbolFunc> + PDBFuncSymbolEnumerator; + bool AddEnumValue(lldb_private::CompilerType enum_type, - const llvm::pdb::PDBSymbolData &data) const; + const llvm::pdb::PDBSymbolData &data); + bool CompleteTypeFromUDT(lldb_private::SymbolFile &symbol_file, + lldb_private::CompilerType &compiler_type, + llvm::pdb::PDBSymbolTypeUDT &udt); + void + AddRecordMembers(lldb_private::SymbolFile &symbol_file, + lldb_private::CompilerType &record_type, + PDBDataSymbolEnumerator &members_enum, + lldb_private::ClangASTImporter::LayoutInfo &layout_info); + void + AddRecordBases(lldb_private::SymbolFile &symbol_file, + lldb_private::CompilerType &record_type, int record_kind, + PDBBaseClassSymbolEnumerator &bases_enum, + lldb_private::ClangASTImporter::LayoutInfo &layout_info) const; + void AddRecordMethods(lldb_private::SymbolFile &symbol_file, + lldb_private::CompilerType &record_type, + PDBFuncSymbolEnumerator &methods_enum); + clang::CXXMethodDecl * + AddRecordMethod(lldb_private::SymbolFile &symbol_file, + lldb_private::CompilerType &record_type, + const llvm::pdb::PDBSymbolFunc &method) const; lldb_private::ClangASTContext &m_ast; lldb_private::ClangASTImporter m_ast_importer; + + CXXRecordDeclToUidMap m_forward_decl_to_uid; + UidToDeclMap m_uid_to_decl; + ParentToNamespacesMap m_parent_to_namespaces; + NamespacesSet m_namespaces; + DeclContextToUidMap m_decl_context_to_uid; }; #endif // LLDB_PLUGINS_SYMBOLFILE_PDB_PDBASTPARSER_H diff --git a/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp b/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp index 69ef70cc508c..9f398ef9b047 100644 --- a/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp +++ b/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp @@ -26,51 +26,51 @@ using namespace llvm::pdb; namespace { const uint32_t g_code_view_to_lldb_registers_x86[] = { - LLDB_INVALID_REGNUM, // CVRegNONE - lldb_al_i386, // CVRegAL - lldb_cl_i386, // CVRegCL - lldb_dl_i386, // CVRegDL - lldb_bl_i386, // CVRegBL - lldb_ah_i386, // CVRegAH - lldb_ch_i386, // CVRegCH - lldb_dh_i386, // CVRegDH - lldb_bh_i386, // CVRegBH - lldb_ax_i386, // CVRegAX - lldb_cx_i386, // CVRegCX - lldb_dx_i386, // CVRegDX - lldb_bx_i386, // CVRegBX - lldb_sp_i386, // CVRegSP - lldb_bp_i386, // CVRegBP - lldb_si_i386, // CVRegSI - lldb_di_i386, // CVRegDI - lldb_eax_i386, // CVRegEAX - lldb_ecx_i386, // CVRegECX - lldb_edx_i386, // CVRegEDX - lldb_ebx_i386, // CVRegEBX - lldb_esp_i386, // CVRegESP - lldb_ebp_i386, // CVRegEBP - lldb_esi_i386, // CVRegESI - lldb_edi_i386, // CVRegEDI - lldb_es_i386, // CVRegES - lldb_cs_i386, // CVRegCS - lldb_ss_i386, // CVRegSS - lldb_ds_i386, // CVRegDS - lldb_fs_i386, // CVRegFS - lldb_gs_i386, // CVRegGS - LLDB_INVALID_REGNUM, // CVRegIP - LLDB_INVALID_REGNUM, // CVRegFLAGS - lldb_eip_i386, // CVRegEIP - lldb_eflags_i386, // CVRegEFLAGS + LLDB_INVALID_REGNUM, // NONE + lldb_al_i386, // AL + lldb_cl_i386, // CL + lldb_dl_i386, // DL + lldb_bl_i386, // BL + lldb_ah_i386, // AH + lldb_ch_i386, // CH + lldb_dh_i386, // DH + lldb_bh_i386, // BH + lldb_ax_i386, // AX + lldb_cx_i386, // CX + lldb_dx_i386, // DX + lldb_bx_i386, // BX + lldb_sp_i386, // SP + lldb_bp_i386, // BP + lldb_si_i386, // SI + lldb_di_i386, // DI + lldb_eax_i386, // EAX + lldb_ecx_i386, // ECX + lldb_edx_i386, // EDX + lldb_ebx_i386, // EBX + lldb_esp_i386, // ESP + lldb_ebp_i386, // EBP + lldb_esi_i386, // ESI + lldb_edi_i386, // EDI + lldb_es_i386, // ES + lldb_cs_i386, // CS + lldb_ss_i386, // SS + lldb_ds_i386, // DS + lldb_fs_i386, // FS + lldb_gs_i386, // GS + LLDB_INVALID_REGNUM, // IP + LLDB_INVALID_REGNUM, // FLAGS + lldb_eip_i386, // EIP + lldb_eflags_i386, // EFLAGS LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CVRegTEMP - LLDB_INVALID_REGNUM, // CVRegTEMPH - LLDB_INVALID_REGNUM, // CVRegQUOTE - LLDB_INVALID_REGNUM, // CVRegPCDR3 - LLDB_INVALID_REGNUM, // CVRegPCDR4 - LLDB_INVALID_REGNUM, // CVRegPCDR5 - LLDB_INVALID_REGNUM, // CVRegPCDR6 - LLDB_INVALID_REGNUM, // CVRegPCDR7 + LLDB_INVALID_REGNUM, // TEMP + LLDB_INVALID_REGNUM, // TEMPH + LLDB_INVALID_REGNUM, // QUOTE + LLDB_INVALID_REGNUM, // PCDR3 + LLDB_INVALID_REGNUM, // PCDR4 + LLDB_INVALID_REGNUM, // PCDR5 + LLDB_INVALID_REGNUM, // PCDR6 + LLDB_INVALID_REGNUM, // PCDR7 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, @@ -82,123 +82,123 @@ const uint32_t g_code_view_to_lldb_registers_x86[] = { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CVRegCR0 - LLDB_INVALID_REGNUM, // CVRegCR1 - LLDB_INVALID_REGNUM, // CVRegCR2 - LLDB_INVALID_REGNUM, // CVRegCR3 - LLDB_INVALID_REGNUM, // CVRegCR4 + LLDB_INVALID_REGNUM, // CR0 + LLDB_INVALID_REGNUM, // CR1 + LLDB_INVALID_REGNUM, // CR2 + LLDB_INVALID_REGNUM, // CR3 + LLDB_INVALID_REGNUM, // CR4 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_dr0_i386, // CVRegDR0 - lldb_dr1_i386, // CVRegDR1 - lldb_dr2_i386, // CVRegDR2 - lldb_dr3_i386, // CVRegDR3 - lldb_dr4_i386, // CVRegDR4 - lldb_dr5_i386, // CVRegDR5 - lldb_dr6_i386, // CVRegDR6 - lldb_dr7_i386, // CVRegDR7 + lldb_dr0_i386, // DR0 + lldb_dr1_i386, // DR1 + lldb_dr2_i386, // DR2 + lldb_dr3_i386, // DR3 + lldb_dr4_i386, // DR4 + lldb_dr5_i386, // DR5 + lldb_dr6_i386, // DR6 + lldb_dr7_i386, // DR7 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CVRegGDTR - LLDB_INVALID_REGNUM, // CVRegGDTL - LLDB_INVALID_REGNUM, // CVRegIDTR - LLDB_INVALID_REGNUM, // CVRegIDTL - LLDB_INVALID_REGNUM, // CVRegLDTR - LLDB_INVALID_REGNUM, // CVRegTR - LLDB_INVALID_REGNUM, // CVRegPSEUDO1 - LLDB_INVALID_REGNUM, // CVRegPSEUDO2 - LLDB_INVALID_REGNUM, // CVRegPSEUDO3 - LLDB_INVALID_REGNUM, // CVRegPSEUDO4 - LLDB_INVALID_REGNUM, // CVRegPSEUDO5 - LLDB_INVALID_REGNUM, // CVRegPSEUDO6 - LLDB_INVALID_REGNUM, // CVRegPSEUDO7 - LLDB_INVALID_REGNUM, // CVRegPSEUDO8 - LLDB_INVALID_REGNUM, // CVRegPSEUDO9 + LLDB_INVALID_REGNUM, // GDTR + LLDB_INVALID_REGNUM, // GDTL + LLDB_INVALID_REGNUM, // IDTR + LLDB_INVALID_REGNUM, // IDTL + LLDB_INVALID_REGNUM, // LDTR + LLDB_INVALID_REGNUM, // TR + LLDB_INVALID_REGNUM, // PSEUDO1 + LLDB_INVALID_REGNUM, // PSEUDO2 + LLDB_INVALID_REGNUM, // PSEUDO3 + LLDB_INVALID_REGNUM, // PSEUDO4 + LLDB_INVALID_REGNUM, // PSEUDO5 + LLDB_INVALID_REGNUM, // PSEUDO6 + LLDB_INVALID_REGNUM, // PSEUDO7 + LLDB_INVALID_REGNUM, // PSEUDO8 + LLDB_INVALID_REGNUM, // PSEUDO9 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_st0_i386, // CVRegST0 - lldb_st1_i386, // CVRegST1 - lldb_st2_i386, // CVRegST2 - lldb_st3_i386, // CVRegST3 - lldb_st4_i386, // CVRegST4 - lldb_st5_i386, // CVRegST5 - lldb_st6_i386, // CVRegST6 - lldb_st7_i386, // CVRegST7 - LLDB_INVALID_REGNUM, // CVRegCTRL - LLDB_INVALID_REGNUM, // CVRegSTAT - LLDB_INVALID_REGNUM, // CVRegTAG - LLDB_INVALID_REGNUM, // CVRegFPIP - LLDB_INVALID_REGNUM, // CVRegFPCS - LLDB_INVALID_REGNUM, // CVRegFPDO - LLDB_INVALID_REGNUM, // CVRegFPDS - LLDB_INVALID_REGNUM, // CVRegISEM - LLDB_INVALID_REGNUM, // CVRegFPEIP - LLDB_INVALID_REGNUM, // CVRegFPEDO - lldb_mm0_i386, // CVRegMM0 - lldb_mm1_i386, // CVRegMM1 - lldb_mm2_i386, // CVRegMM2 - lldb_mm3_i386, // CVRegMM3 - lldb_mm4_i386, // CVRegMM4 - lldb_mm5_i386, // CVRegMM5 - lldb_mm6_i386, // CVRegMM6 - lldb_mm7_i386, // CVRegMM7 - lldb_xmm0_i386, // CVRegXMM0 - lldb_xmm1_i386, // CVRegXMM1 - lldb_xmm2_i386, // CVRegXMM2 - lldb_xmm3_i386, // CVRegXMM3 - lldb_xmm4_i386, // CVRegXMM4 - lldb_xmm5_i386, // CVRegXMM5 - lldb_xmm6_i386, // CVRegXMM6 - lldb_xmm7_i386 // CVRegXMM7 + lldb_st0_i386, // ST0 + lldb_st1_i386, // ST1 + lldb_st2_i386, // ST2 + lldb_st3_i386, // ST3 + lldb_st4_i386, // ST4 + lldb_st5_i386, // ST5 + lldb_st6_i386, // ST6 + lldb_st7_i386, // ST7 + LLDB_INVALID_REGNUM, // CTRL + LLDB_INVALID_REGNUM, // STAT + LLDB_INVALID_REGNUM, // TAG + LLDB_INVALID_REGNUM, // FPIP + LLDB_INVALID_REGNUM, // FPCS + LLDB_INVALID_REGNUM, // FPDO + LLDB_INVALID_REGNUM, // FPDS + LLDB_INVALID_REGNUM, // ISEM + LLDB_INVALID_REGNUM, // FPEIP + LLDB_INVALID_REGNUM, // FPEDO + lldb_mm0_i386, // MM0 + lldb_mm1_i386, // MM1 + lldb_mm2_i386, // MM2 + lldb_mm3_i386, // MM3 + lldb_mm4_i386, // MM4 + lldb_mm5_i386, // MM5 + lldb_mm6_i386, // MM6 + lldb_mm7_i386, // MM7 + lldb_xmm0_i386, // XMM0 + lldb_xmm1_i386, // XMM1 + lldb_xmm2_i386, // XMM2 + lldb_xmm3_i386, // XMM3 + lldb_xmm4_i386, // XMM4 + lldb_xmm5_i386, // XMM5 + lldb_xmm6_i386, // XMM6 + lldb_xmm7_i386 // XMM7 }; const uint32_t g_code_view_to_lldb_registers_x86_64[] = { - LLDB_INVALID_REGNUM, // CVRegNONE - lldb_al_x86_64, // CVRegAL - lldb_cl_x86_64, // CVRegCL - lldb_dl_x86_64, // CVRegDL - lldb_bl_x86_64, // CVRegBL - lldb_ah_x86_64, // CVRegAH - lldb_ch_x86_64, // CVRegCH - lldb_dh_x86_64, // CVRegDH - lldb_bh_x86_64, // CVRegBH - lldb_ax_x86_64, // CVRegAX - lldb_cx_x86_64, // CVRegCX - lldb_dx_x86_64, // CVRegDX - lldb_bx_x86_64, // CVRegBX - lldb_sp_x86_64, // CVRegSP - lldb_bp_x86_64, // CVRegBP - lldb_si_x86_64, // CVRegSI - lldb_di_x86_64, // CVRegDI - lldb_eax_x86_64, // CVRegEAX - lldb_ecx_x86_64, // CVRegECX - lldb_edx_x86_64, // CVRegEDX - lldb_ebx_x86_64, // CVRegEBX - lldb_esp_x86_64, // CVRegESP - lldb_ebp_x86_64, // CVRegEBP - lldb_esi_x86_64, // CVRegESI - lldb_edi_x86_64, // CVRegEDI - lldb_es_x86_64, // CVRegES - lldb_cs_x86_64, // CVRegCS - lldb_ss_x86_64, // CVRegSS - lldb_ds_x86_64, // CVRegDS - lldb_fs_x86_64, // CVRegFS - lldb_gs_x86_64, // CVRegGS - LLDB_INVALID_REGNUM, // CVRegIP - LLDB_INVALID_REGNUM, // CVRegFLAGS - LLDB_INVALID_REGNUM, // CVRegEIP - LLDB_INVALID_REGNUM, // CVRegEFLAGS + LLDB_INVALID_REGNUM, // NONE + lldb_al_x86_64, // AL + lldb_cl_x86_64, // CL + lldb_dl_x86_64, // DL + lldb_bl_x86_64, // BL + lldb_ah_x86_64, // AH + lldb_ch_x86_64, // CH + lldb_dh_x86_64, // DH + lldb_bh_x86_64, // BH + lldb_ax_x86_64, // AX + lldb_cx_x86_64, // CX + lldb_dx_x86_64, // DX + lldb_bx_x86_64, // BX + lldb_sp_x86_64, // SP + lldb_bp_x86_64, // BP + lldb_si_x86_64, // SI + lldb_di_x86_64, // DI + lldb_eax_x86_64, // EAX + lldb_ecx_x86_64, // ECX + lldb_edx_x86_64, // EDX + lldb_ebx_x86_64, // EBX + lldb_esp_x86_64, // ESP + lldb_ebp_x86_64, // EBP + lldb_esi_x86_64, // ESI + lldb_edi_x86_64, // EDI + lldb_es_x86_64, // ES + lldb_cs_x86_64, // CS + lldb_ss_x86_64, // SS + lldb_ds_x86_64, // DS + lldb_fs_x86_64, // FS + lldb_gs_x86_64, // GS + LLDB_INVALID_REGNUM, // IP + LLDB_INVALID_REGNUM, // FLAGS + LLDB_INVALID_REGNUM, // EIP + LLDB_INVALID_REGNUM, // EFLAGS LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CVRegTEMP - LLDB_INVALID_REGNUM, // CVRegTEMPH - LLDB_INVALID_REGNUM, // CVRegQUOTE - LLDB_INVALID_REGNUM, // CVRegPCDR3 - LLDB_INVALID_REGNUM, // CVRegPCDR4 - LLDB_INVALID_REGNUM, // CVRegPCDR5 - LLDB_INVALID_REGNUM, // CVRegPCDR6 - LLDB_INVALID_REGNUM, // CVRegPCDR7 + LLDB_INVALID_REGNUM, // TEMP + LLDB_INVALID_REGNUM, // TEMPH + LLDB_INVALID_REGNUM, // QUOTE + LLDB_INVALID_REGNUM, // PCDR3 + LLDB_INVALID_REGNUM, // PCDR4 + LLDB_INVALID_REGNUM, // PCDR5 + LLDB_INVALID_REGNUM, // PCDR6 + LLDB_INVALID_REGNUM, // PCDR7 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, @@ -210,75 +210,75 @@ const uint32_t g_code_view_to_lldb_registers_x86_64[] = { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CVRegCR0 - LLDB_INVALID_REGNUM, // CVRegCR1 - LLDB_INVALID_REGNUM, // CVRegCR2 - LLDB_INVALID_REGNUM, // CVRegCR3 - LLDB_INVALID_REGNUM, // CVRegCR4 + LLDB_INVALID_REGNUM, // CR0 + LLDB_INVALID_REGNUM, // CR1 + LLDB_INVALID_REGNUM, // CR2 + LLDB_INVALID_REGNUM, // CR3 + LLDB_INVALID_REGNUM, // CR4 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_dr0_x86_64, // CVRegDR0 - lldb_dr1_x86_64, // CVRegDR1 - lldb_dr2_x86_64, // CVRegDR2 - lldb_dr3_x86_64, // CVRegDR3 - lldb_dr4_x86_64, // CVRegDR4 - lldb_dr5_x86_64, // CVRegDR5 - lldb_dr6_x86_64, // CVRegDR6 - lldb_dr7_x86_64, // CVRegDR7 + lldb_dr0_x86_64, // DR0 + lldb_dr1_x86_64, // DR1 + lldb_dr2_x86_64, // DR2 + lldb_dr3_x86_64, // DR3 + lldb_dr4_x86_64, // DR4 + lldb_dr5_x86_64, // DR5 + lldb_dr6_x86_64, // DR6 + lldb_dr7_x86_64, // DR7 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CVRegGDTR - LLDB_INVALID_REGNUM, // CVRegGDTL - LLDB_INVALID_REGNUM, // CVRegIDTR - LLDB_INVALID_REGNUM, // CVRegIDTL - LLDB_INVALID_REGNUM, // CVRegLDTR - LLDB_INVALID_REGNUM, // CVRegTR - LLDB_INVALID_REGNUM, // CVRegPSEUDO1 - LLDB_INVALID_REGNUM, // CVRegPSEUDO2 - LLDB_INVALID_REGNUM, // CVRegPSEUDO3 - LLDB_INVALID_REGNUM, // CVRegPSEUDO4 - LLDB_INVALID_REGNUM, // CVRegPSEUDO5 - LLDB_INVALID_REGNUM, // CVRegPSEUDO6 - LLDB_INVALID_REGNUM, // CVRegPSEUDO7 - LLDB_INVALID_REGNUM, // CVRegPSEUDO8 - LLDB_INVALID_REGNUM, // CVRegPSEUDO9 + LLDB_INVALID_REGNUM, // GDTR + LLDB_INVALID_REGNUM, // GDTL + LLDB_INVALID_REGNUM, // IDTR + LLDB_INVALID_REGNUM, // IDTL + LLDB_INVALID_REGNUM, // LDTR + LLDB_INVALID_REGNUM, // TR + LLDB_INVALID_REGNUM, // PSEUDO1 + LLDB_INVALID_REGNUM, // PSEUDO2 + LLDB_INVALID_REGNUM, // PSEUDO3 + LLDB_INVALID_REGNUM, // PSEUDO4 + LLDB_INVALID_REGNUM, // PSEUDO5 + LLDB_INVALID_REGNUM, // PSEUDO6 + LLDB_INVALID_REGNUM, // PSEUDO7 + LLDB_INVALID_REGNUM, // PSEUDO8 + LLDB_INVALID_REGNUM, // PSEUDO9 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_st0_x86_64, // CVRegST0 - lldb_st1_x86_64, // CVRegST1 - lldb_st2_x86_64, // CVRegST2 - lldb_st3_x86_64, // CVRegST3 - lldb_st4_x86_64, // CVRegST4 - lldb_st5_x86_64, // CVRegST5 - lldb_st6_x86_64, // CVRegST6 - lldb_st7_x86_64, // CVRegST7 - LLDB_INVALID_REGNUM, // CVRegCTRL - LLDB_INVALID_REGNUM, // CVRegSTAT - LLDB_INVALID_REGNUM, // CVRegTAG - LLDB_INVALID_REGNUM, // CVRegFPIP - LLDB_INVALID_REGNUM, // CVRegFPCS - LLDB_INVALID_REGNUM, // CVRegFPDO - LLDB_INVALID_REGNUM, // CVRegFPDS - LLDB_INVALID_REGNUM, // CVRegISEM - LLDB_INVALID_REGNUM, // CVRegFPEIP - LLDB_INVALID_REGNUM, // CVRegFPEDO - lldb_mm0_x86_64, // CVRegMM0 - lldb_mm1_x86_64, // CVRegMM1 - lldb_mm2_x86_64, // CVRegMM2 - lldb_mm3_x86_64, // CVRegMM3 - lldb_mm4_x86_64, // CVRegMM4 - lldb_mm5_x86_64, // CVRegMM5 - lldb_mm6_x86_64, // CVRegMM6 - lldb_mm7_x86_64, // CVRegMM7 - lldb_xmm0_x86_64, // CVRegXMM0 - lldb_xmm1_x86_64, // CVRegXMM1 - lldb_xmm2_x86_64, // CVRegXMM2 - lldb_xmm3_x86_64, // CVRegXMM3 - lldb_xmm4_x86_64, // CVRegXMM4 - lldb_xmm5_x86_64, // CVRegXMM5 - lldb_xmm6_x86_64, // CVRegXMM6 - lldb_xmm7_x86_64, // CVRegXMM7 + lldb_st0_x86_64, // ST0 + lldb_st1_x86_64, // ST1 + lldb_st2_x86_64, // ST2 + lldb_st3_x86_64, // ST3 + lldb_st4_x86_64, // ST4 + lldb_st5_x86_64, // ST5 + lldb_st6_x86_64, // ST6 + lldb_st7_x86_64, // ST7 + LLDB_INVALID_REGNUM, // CTRL + LLDB_INVALID_REGNUM, // STAT + LLDB_INVALID_REGNUM, // TAG + LLDB_INVALID_REGNUM, // FPIP + LLDB_INVALID_REGNUM, // FPCS + LLDB_INVALID_REGNUM, // FPDO + LLDB_INVALID_REGNUM, // FPDS + LLDB_INVALID_REGNUM, // ISEM + LLDB_INVALID_REGNUM, // FPEIP + LLDB_INVALID_REGNUM, // FPEDO + lldb_mm0_x86_64, // MM0 + lldb_mm1_x86_64, // MM1 + lldb_mm2_x86_64, // MM2 + lldb_mm3_x86_64, // MM3 + lldb_mm4_x86_64, // MM4 + lldb_mm5_x86_64, // MM5 + lldb_mm6_x86_64, // MM6 + lldb_mm7_x86_64, // MM7 + lldb_xmm0_x86_64, // XMM0 + lldb_xmm1_x86_64, // XMM1 + lldb_xmm2_x86_64, // XMM2 + lldb_xmm3_x86_64, // XMM3 + lldb_xmm4_x86_64, // XMM4 + lldb_xmm5_x86_64, // XMM5 + lldb_xmm6_x86_64, // XMM6 + lldb_xmm7_x86_64, // XMM7 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, @@ -296,51 +296,51 @@ const uint32_t g_code_view_to_lldb_registers_x86_64[] = { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_mxcsr_x86_64, // CVRegMXCSR - LLDB_INVALID_REGNUM, // CVRegEDXEAX + lldb_mxcsr_x86_64, // MXCSR + LLDB_INVALID_REGNUM, // EDXEAX LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, // CVRegEMM0L - LLDB_INVALID_REGNUM, // CVRegEMM1L - LLDB_INVALID_REGNUM, // CVRegEMM2L - LLDB_INVALID_REGNUM, // CVRegEMM3L - LLDB_INVALID_REGNUM, // CVRegEMM4L - LLDB_INVALID_REGNUM, // CVRegEMM5L - LLDB_INVALID_REGNUM, // CVRegEMM6L - LLDB_INVALID_REGNUM, // CVRegEMM7L - LLDB_INVALID_REGNUM, // CVRegEMM0H - LLDB_INVALID_REGNUM, // CVRegEMM1H - LLDB_INVALID_REGNUM, // CVRegEMM2H - LLDB_INVALID_REGNUM, // CVRegEMM3H - LLDB_INVALID_REGNUM, // CVRegEMM4H - LLDB_INVALID_REGNUM, // CVRegEMM5H - LLDB_INVALID_REGNUM, // CVRegEMM6H - LLDB_INVALID_REGNUM, // CVRegEMM7H - LLDB_INVALID_REGNUM, // CVRegMM00 - LLDB_INVALID_REGNUM, // CVRegMM01 - LLDB_INVALID_REGNUM, // CVRegMM10 - LLDB_INVALID_REGNUM, // CVRegMM11 - LLDB_INVALID_REGNUM, // CVRegMM20 - LLDB_INVALID_REGNUM, // CVRegMM21 - LLDB_INVALID_REGNUM, // CVRegMM30 - LLDB_INVALID_REGNUM, // CVRegMM31 - LLDB_INVALID_REGNUM, // CVRegMM40 - LLDB_INVALID_REGNUM, // CVRegMM41 - LLDB_INVALID_REGNUM, // CVRegMM50 - LLDB_INVALID_REGNUM, // CVRegMM51 - LLDB_INVALID_REGNUM, // CVRegMM60 - LLDB_INVALID_REGNUM, // CVRegMM61 - LLDB_INVALID_REGNUM, // CVRegMM70 - LLDB_INVALID_REGNUM, // CVRegMM71 - lldb_xmm8_x86_64, // CVRegXMM8 - lldb_xmm9_x86_64, // CVRegXMM9 - lldb_xmm10_x86_64, // CVRegXMM10 - lldb_xmm11_x86_64, // CVRegXMM11 - lldb_xmm12_x86_64, // CVRegXMM12 - lldb_xmm13_x86_64, // CVRegXMM13 - lldb_xmm14_x86_64, // CVRegXMM14 - lldb_xmm15_x86_64, // CVRegXMM15 + LLDB_INVALID_REGNUM, // EMM0L + LLDB_INVALID_REGNUM, // EMM1L + LLDB_INVALID_REGNUM, // EMM2L + LLDB_INVALID_REGNUM, // EMM3L + LLDB_INVALID_REGNUM, // EMM4L + LLDB_INVALID_REGNUM, // EMM5L + LLDB_INVALID_REGNUM, // EMM6L + LLDB_INVALID_REGNUM, // EMM7L + LLDB_INVALID_REGNUM, // EMM0H + LLDB_INVALID_REGNUM, // EMM1H + LLDB_INVALID_REGNUM, // EMM2H + LLDB_INVALID_REGNUM, // EMM3H + LLDB_INVALID_REGNUM, // EMM4H + LLDB_INVALID_REGNUM, // EMM5H + LLDB_INVALID_REGNUM, // EMM6H + LLDB_INVALID_REGNUM, // EMM7H + LLDB_INVALID_REGNUM, // MM00 + LLDB_INVALID_REGNUM, // MM01 + LLDB_INVALID_REGNUM, // MM10 + LLDB_INVALID_REGNUM, // MM11 + LLDB_INVALID_REGNUM, // MM20 + LLDB_INVALID_REGNUM, // MM21 + LLDB_INVALID_REGNUM, // MM30 + LLDB_INVALID_REGNUM, // MM31 + LLDB_INVALID_REGNUM, // MM40 + LLDB_INVALID_REGNUM, // MM41 + LLDB_INVALID_REGNUM, // MM50 + LLDB_INVALID_REGNUM, // MM51 + LLDB_INVALID_REGNUM, // MM60 + LLDB_INVALID_REGNUM, // MM61 + LLDB_INVALID_REGNUM, // MM70 + LLDB_INVALID_REGNUM, // MM71 + lldb_xmm8_x86_64, // XMM8 + lldb_xmm9_x86_64, // XMM9 + lldb_xmm10_x86_64, // XMM10 + lldb_xmm11_x86_64, // XMM11 + lldb_xmm12_x86_64, // XMM12 + lldb_xmm13_x86_64, // XMM13 + lldb_xmm14_x86_64, // XMM14 + lldb_xmm15_x86_64, // XMM15 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, @@ -363,73 +363,73 @@ const uint32_t g_code_view_to_lldb_registers_x86_64[] = { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_sil_x86_64, // CVRegSIL - lldb_dil_x86_64, // CVRegDIL - lldb_bpl_x86_64, // CVRegBPL - lldb_spl_x86_64, // CVRegSPL - lldb_rax_x86_64, // CVRegRAX - lldb_rbx_x86_64, // CVRegRBX - lldb_rcx_x86_64, // CVRegRCX - lldb_rdx_x86_64, // CVRegRDX - lldb_rsi_x86_64, // CVRegRSI - lldb_rdi_x86_64, // CVRegRDI - lldb_rbp_x86_64, // CVRegRBP - lldb_rsp_x86_64, // CVRegRSP - lldb_r8_x86_64, // CVRegR8 - lldb_r9_x86_64, // CVRegR9 - lldb_r10_x86_64, // CVRegR10 - lldb_r11_x86_64, // CVRegR11 - lldb_r12_x86_64, // CVRegR12 - lldb_r13_x86_64, // CVRegR13 - lldb_r14_x86_64, // CVRegR14 - lldb_r15_x86_64, // CVRegR15 - lldb_r8l_x86_64, // CVRegR8B - lldb_r9l_x86_64, // CVRegR9B - lldb_r10l_x86_64, // CVRegR10B - lldb_r11l_x86_64, // CVRegR11B - lldb_r12l_x86_64, // CVRegR12B - lldb_r13l_x86_64, // CVRegR13B - lldb_r14l_x86_64, // CVRegR14B - lldb_r15l_x86_64, // CVRegR15B - lldb_r8w_x86_64, // CVRegR8W - lldb_r9w_x86_64, // CVRegR9W - lldb_r10w_x86_64, // CVRegR10W - lldb_r11w_x86_64, // CVRegR11W - lldb_r12w_x86_64, // CVRegR12W - lldb_r13w_x86_64, // CVRegR13W - lldb_r14w_x86_64, // CVRegR14W - lldb_r15w_x86_64, // CVRegR15W - lldb_r8d_x86_64, // CVRegR8D - lldb_r9d_x86_64, // CVRegR9D - lldb_r10d_x86_64, // CVRegR10D - lldb_r11d_x86_64, // CVRegR11D - lldb_r12d_x86_64, // CVRegR12D - lldb_r13d_x86_64, // CVRegR13D - lldb_r14d_x86_64, // CVRegR14D - lldb_r15d_x86_64, // CVRegR15D - lldb_ymm0_x86_64, // CVRegAMD64_YMM0 - lldb_ymm1_x86_64, // CVRegAMD64_YMM1 - lldb_ymm2_x86_64, // CVRegAMD64_YMM2 - lldb_ymm3_x86_64, // CVRegAMD64_YMM3 - lldb_ymm4_x86_64, // CVRegAMD64_YMM4 - lldb_ymm5_x86_64, // CVRegAMD64_YMM5 - lldb_ymm6_x86_64, // CVRegAMD64_YMM6 - lldb_ymm7_x86_64, // CVRegAMD64_YMM7 - lldb_ymm8_x86_64, // CVRegAMD64_YMM8 - lldb_ymm9_x86_64, // CVRegAMD64_YMM9 - lldb_ymm10_x86_64, // CVRegAMD64_YMM10 - lldb_ymm11_x86_64, // CVRegAMD64_YMM11 - lldb_ymm12_x86_64, // CVRegAMD64_YMM12 - lldb_ymm13_x86_64, // CVRegAMD64_YMM13 - lldb_ymm14_x86_64, // CVRegAMD64_YMM14 - lldb_ymm15_x86_64, // CVRegAMD64_YMM15 + lldb_sil_x86_64, // SIL + lldb_dil_x86_64, // DIL + lldb_bpl_x86_64, // BPL + lldb_spl_x86_64, // SPL + lldb_rax_x86_64, // RAX + lldb_rbx_x86_64, // RBX + lldb_rcx_x86_64, // RCX + lldb_rdx_x86_64, // RDX + lldb_rsi_x86_64, // RSI + lldb_rdi_x86_64, // RDI + lldb_rbp_x86_64, // RBP + lldb_rsp_x86_64, // RSP + lldb_r8_x86_64, // R8 + lldb_r9_x86_64, // R9 + lldb_r10_x86_64, // R10 + lldb_r11_x86_64, // R11 + lldb_r12_x86_64, // R12 + lldb_r13_x86_64, // R13 + lldb_r14_x86_64, // R14 + lldb_r15_x86_64, // R15 + lldb_r8l_x86_64, // R8B + lldb_r9l_x86_64, // R9B + lldb_r10l_x86_64, // R10B + lldb_r11l_x86_64, // R11B + lldb_r12l_x86_64, // R12B + lldb_r13l_x86_64, // R13B + lldb_r14l_x86_64, // R14B + lldb_r15l_x86_64, // R15B + lldb_r8w_x86_64, // R8W + lldb_r9w_x86_64, // R9W + lldb_r10w_x86_64, // R10W + lldb_r11w_x86_64, // R11W + lldb_r12w_x86_64, // R12W + lldb_r13w_x86_64, // R13W + lldb_r14w_x86_64, // R14W + lldb_r15w_x86_64, // R15W + lldb_r8d_x86_64, // R8D + lldb_r9d_x86_64, // R9D + lldb_r10d_x86_64, // R10D + lldb_r11d_x86_64, // R11D + lldb_r12d_x86_64, // R12D + lldb_r13d_x86_64, // R13D + lldb_r14d_x86_64, // R14D + lldb_r15d_x86_64, // R15D + lldb_ymm0_x86_64, // AMD64_YMM0 + lldb_ymm1_x86_64, // AMD64_YMM1 + lldb_ymm2_x86_64, // AMD64_YMM2 + lldb_ymm3_x86_64, // AMD64_YMM3 + lldb_ymm4_x86_64, // AMD64_YMM4 + lldb_ymm5_x86_64, // AMD64_YMM5 + lldb_ymm6_x86_64, // AMD64_YMM6 + lldb_ymm7_x86_64, // AMD64_YMM7 + lldb_ymm8_x86_64, // AMD64_YMM8 + lldb_ymm9_x86_64, // AMD64_YMM9 + lldb_ymm10_x86_64, // AMD64_YMM10 + lldb_ymm11_x86_64, // AMD64_YMM11 + lldb_ymm12_x86_64, // AMD64_YMM12 + lldb_ymm13_x86_64, // AMD64_YMM13 + lldb_ymm14_x86_64, // AMD64_YMM14 + lldb_ymm15_x86_64, // AMD64_YMM15 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, - lldb_bnd0_x86_64, // CVRegBND0 - lldb_bnd1_x86_64, // CVRegBND1 - lldb_bnd2_x86_64 // CVRegBND2 + lldb_bnd0_x86_64, // BND0 + lldb_bnd1_x86_64, // BND1 + lldb_bnd2_x86_64 // BND2 }; uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type, @@ -443,13 +443,13 @@ uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type, register_id)]; switch (register_id) { - case llvm::codeview::RegisterId::CVRegMXCSR: + case llvm::codeview::RegisterId::MXCSR: return lldb_mxcsr_i386; - case llvm::codeview::RegisterId::CVRegBND0: + case llvm::codeview::RegisterId::BND0: return lldb_bnd0_i386; - case llvm::codeview::RegisterId::CVRegBND1: + case llvm::codeview::RegisterId::BND1: return lldb_bnd1_i386; - case llvm::codeview::RegisterId::CVRegBND2: + case llvm::codeview::RegisterId::BND2: return lldb_bnd2_i386; default: return LLDB_INVALID_REGNUM; @@ -468,7 +468,7 @@ uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type, } uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) { - if (register_id == llvm::codeview::RegisterId::CVRegVFRAME) + if (register_id == llvm::codeview::RegisterId::VFRAME) return LLDB_REGNUM_GENERIC_FP; return LLDB_INVALID_REGNUM; diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index 05f3017819fa..ad25842f4d05 100644 --- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -9,6 +9,9 @@ #include "SymbolFilePDB.h" +#include "PDBASTParser.h" +#include "PDBLocationToDWARFExpression.h" + #include "clang/Lex/Lexer.h" #include "lldb/Core/Module.h" @@ -46,8 +49,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" -#include "Plugins/SymbolFile/PDB/PDBASTParser.h" -#include "Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h" +#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" +#include "Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h" #include <regex> @@ -74,14 +77,32 @@ bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line, } } // namespace +static bool ShouldUseNativeReader() { +#if defined(_WIN32) + llvm::StringRef use_native = ::getenv("LLDB_USE_NATIVE_PDB_READER"); + return use_native.equals_lower("on") || use_native.equals_lower("yes") || + use_native.equals_lower("1") || use_native.equals_lower("true"); +#else + return true; +#endif +} + void SymbolFilePDB::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance, - DebuggerInitialize); + if (ShouldUseNativeReader()) { + npdb::SymbolFileNativePDB::Initialize(); + } else { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance, + DebuggerInitialize); + } } void SymbolFilePDB::Terminate() { - PluginManager::UnregisterPlugin(CreateInstance); + if (ShouldUseNativeReader()) { + npdb::SymbolFileNativePDB::Terminate(); + } else { + PluginManager::UnregisterPlugin(CreateInstance); + } } void SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger) {} @@ -246,14 +267,8 @@ lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) { return ParseCompileUnitForUID(compiland_up->getSymIndexId(), index); } -lldb::LanguageType -SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) { - // What fields should I expect to be filled out on the SymbolContext? Is it - // safe to assume that `sc.comp_unit` is valid? - if (!sc.comp_unit) - return lldb::eLanguageTypeUnknown; - - auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID()); +lldb::LanguageType SymbolFilePDB::ParseLanguage(CompileUnit &comp_unit) { + auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); if (!compiland_up) return lldb::eLanguageTypeUnknown; auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>(); @@ -262,9 +277,11 @@ SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) { return TranslateLanguage(details->getLanguage()); } -lldb_private::Function *SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc( - const PDBSymbolFunc &pdb_func, const lldb_private::SymbolContext &sc) { - lldbassert(sc.comp_unit && sc.module_sp.get()); +lldb_private::Function * +SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc &pdb_func, + CompileUnit &comp_unit) { + if (FunctionSP result = comp_unit.FindFunctionByUID(pdb_func.getSymIndexId())) + return result.get(); auto file_vm_addr = pdb_func.getVirtualAddress(); if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0) @@ -272,7 +289,8 @@ lldb_private::Function *SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc( auto func_length = pdb_func.getLength(); AddressRange func_range = - AddressRange(file_vm_addr, func_length, sc.module_sp->GetSectionList()); + AddressRange(file_vm_addr, func_length, + GetObjectFile()->GetModule()->GetSectionList()); if (!func_range.GetBaseAddress().IsValid()) return nullptr; @@ -285,59 +303,61 @@ lldb_private::Function *SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc( Mangled mangled = GetMangledForPDBFunc(pdb_func); FunctionSP func_sp = - std::make_shared<Function>(sc.comp_unit, pdb_func.getSymIndexId(), + std::make_shared<Function>(&comp_unit, pdb_func.getSymIndexId(), func_type_uid, mangled, func_type, func_range); - sc.comp_unit->AddFunction(func_sp); + comp_unit.AddFunction(func_sp); + + TypeSystem *type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + if (!type_system) + return nullptr; + ClangASTContext *clang_type_system = + llvm::dyn_cast_or_null<ClangASTContext>(type_system); + if (!clang_type_system) + return nullptr; + clang_type_system->GetPDBParser()->GetDeclForSymbol(pdb_func); + return func_sp.get(); } -size_t SymbolFilePDB::ParseCompileUnitFunctions( - const lldb_private::SymbolContext &sc) { - lldbassert(sc.comp_unit); +size_t SymbolFilePDB::ParseFunctions(CompileUnit &comp_unit) { size_t func_added = 0; - auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID()); + auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); if (!compiland_up) return 0; auto results_up = compiland_up->findAllChildren<PDBSymbolFunc>(); if (!results_up) return 0; while (auto pdb_func_up = results_up->getNext()) { - auto func_sp = - sc.comp_unit->FindFunctionByUID(pdb_func_up->getSymIndexId()); + auto func_sp = comp_unit.FindFunctionByUID(pdb_func_up->getSymIndexId()); if (!func_sp) { - if (ParseCompileUnitFunctionForPDBFunc(*pdb_func_up, sc)) + if (ParseCompileUnitFunctionForPDBFunc(*pdb_func_up, comp_unit)) ++func_added; } } return func_added; } -bool SymbolFilePDB::ParseCompileUnitLineTable( - const lldb_private::SymbolContext &sc) { - lldbassert(sc.comp_unit); - if (sc.comp_unit->GetLineTable()) +bool SymbolFilePDB::ParseLineTable(CompileUnit &comp_unit) { + if (comp_unit.GetLineTable()) return true; - return ParseCompileUnitLineTable(sc, 0); + return ParseCompileUnitLineTable(comp_unit, 0); } -bool SymbolFilePDB::ParseCompileUnitDebugMacros( - const lldb_private::SymbolContext &sc) { +bool SymbolFilePDB::ParseDebugMacros(CompileUnit &comp_unit) { // PDB doesn't contain information about macros return false; } -bool SymbolFilePDB::ParseCompileUnitSupportFiles( - const lldb_private::SymbolContext &sc, - lldb_private::FileSpecList &support_files) { - lldbassert(sc.comp_unit); +bool SymbolFilePDB::ParseSupportFiles( + CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) { // In theory this is unnecessary work for us, because all of this information // is easily (and quickly) accessible from DebugInfoPDB, so caching it a // second time seems like a waste. Unfortunately, there's no good way around // this short of a moderate refactor since SymbolVendor depends on being able // to cache this list. - auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID()); + auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); if (!compiland_up) return false; auto files = m_session_up->getSourceFilesForCompiland(*compiland_up); @@ -345,13 +365,13 @@ bool SymbolFilePDB::ParseCompileUnitSupportFiles( return false; while (auto file = files->getNext()) { - FileSpec spec(file->getFileName(), false, FileSpec::Style::windows); + FileSpec spec(file->getFileName(), FileSpec::Style::windows); support_files.AppendIfUnique(spec); } // LLDB uses the DWARF-like file numeration (one based), // the zeroth file is the compile unit itself - support_files.Insert(0, *sc.comp_unit); + support_files.Insert(0, comp_unit); return true; } @@ -364,9 +384,8 @@ bool SymbolFilePDB::ParseImportedModules( } static size_t ParseFunctionBlocksForPDBSymbol( - const lldb_private::SymbolContext &sc, uint64_t func_file_vm_addr, - const llvm::pdb::PDBSymbol *pdb_symbol, lldb_private::Block *parent_block, - bool is_top_parent) { + uint64_t func_file_vm_addr, const llvm::pdb::PDBSymbol *pdb_symbol, + lldb_private::Block *parent_block, bool is_top_parent) { assert(pdb_symbol && parent_block); size_t num_added = 0; @@ -405,7 +424,7 @@ static size_t ParseFunctionBlocksForPDBSymbol( break; while (auto symbol_up = results_up->getNext()) { num_added += ParseFunctionBlocksForPDBSymbol( - sc, func_file_vm_addr, symbol_up.get(), block, false); + func_file_vm_addr, symbol_up.get(), block, false); } } break; default: @@ -414,28 +433,22 @@ static size_t ParseFunctionBlocksForPDBSymbol( return num_added; } -size_t -SymbolFilePDB::ParseFunctionBlocks(const lldb_private::SymbolContext &sc) { - lldbassert(sc.comp_unit && sc.function); +size_t SymbolFilePDB::ParseBlocksRecursive(Function &func) { size_t num_added = 0; - auto uid = sc.function->GetID(); + auto uid = func.GetID(); auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid); if (!pdb_func_up) return 0; - Block &parent_block = sc.function->GetBlock(false); - num_added = - ParseFunctionBlocksForPDBSymbol(sc, pdb_func_up->getVirtualAddress(), - pdb_func_up.get(), &parent_block, true); + Block &parent_block = func.GetBlock(false); + num_added = ParseFunctionBlocksForPDBSymbol( + pdb_func_up->getVirtualAddress(), pdb_func_up.get(), &parent_block, true); return num_added; } -size_t SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc) { - lldbassert(sc.module_sp.get()); - if (!sc.comp_unit) - return 0; +size_t SymbolFilePDB::ParseTypes(CompileUnit &comp_unit) { size_t num_added = 0; - auto compiland = GetPDBCompilandByUID(sc.comp_unit->GetID()); + auto compiland = GetPDBCompilandByUID(comp_unit.GetID()); if (!compiland) return 0; @@ -459,31 +472,26 @@ size_t SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc) { // This should cause the type to get cached and stored in the `m_types` // lookup. - if (!ResolveTypeUID(symbol->getSymIndexId())) - continue; - - ++num_added; + if (auto type = ResolveTypeUID(symbol->getSymIndexId())) { + // Resolve the type completely to avoid a completion + // (and so a list change, which causes an iterators invalidation) + // during a TypeList dumping + type->GetFullCompilerType(); + ++num_added; + } } } }; - if (sc.function) { - auto pdb_func = m_session_up->getConcreteSymbolById<PDBSymbolFunc>( - sc.function->GetID()); - if (!pdb_func) - return 0; - ParseTypesByTagFn(*pdb_func); - } else { - ParseTypesByTagFn(*compiland); + ParseTypesByTagFn(*compiland); - // Also parse global types particularly coming from this compiland. - // Unfortunately, PDB has no compiland information for each global type. We - // have to parse them all. But ensure we only do this once. - static bool parse_all_global_types = false; - if (!parse_all_global_types) { - ParseTypesByTagFn(*m_global_scope_up); - parse_all_global_types = true; - } + // Also parse global types particularly coming from this compiland. + // Unfortunately, PDB has no compiland information for each global type. We + // have to parse them all. But ensure we only do this once. + static bool parse_all_global_types = false; + if (!parse_all_global_types) { + ParseTypesByTagFn(*m_global_scope_up); + parse_all_global_types = true; } return num_added; } @@ -513,7 +521,7 @@ SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) { auto results = m_global_scope_up->findAllChildren<PDBSymbolData>(); if (results && results->getChildCount()) { while (auto result = results->getNext()) { - auto cu_id = result->getCompilandId(); + auto cu_id = GetCompilandId(*result); // FIXME: We are not able to determine variable's compile unit. if (cu_id == 0) continue; @@ -548,8 +556,7 @@ lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) { llvm::dyn_cast_or_null<ClangASTContext>(type_system); if (!clang_type_system) return nullptr; - PDBASTParser *pdb = - llvm::dyn_cast<PDBASTParser>(clang_type_system->GetPDBParser()); + PDBASTParser *pdb = clang_type_system->GetPDBParser(); if (!pdb) return nullptr; @@ -567,34 +574,109 @@ lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) { return result.get(); } +llvm::Optional<SymbolFile::ArrayInfo> SymbolFilePDB::GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { + return llvm::None; +} + bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) { - // TODO: Implement this - return false; + std::lock_guard<std::recursive_mutex> guard( + GetObjectFile()->GetModule()->GetMutex()); + + ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + if (!clang_ast_ctx) + return false; + + PDBASTParser *pdb = clang_ast_ctx->GetPDBParser(); + if (!pdb) + return false; + + return pdb->CompleteTypeFromPDB(compiler_type); } lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) { - return lldb_private::CompilerDecl(); + ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + if (!clang_ast_ctx) + return CompilerDecl(); + + PDBASTParser *pdb = clang_ast_ctx->GetPDBParser(); + if (!pdb) + return CompilerDecl(); + + auto symbol = m_session_up->getSymbolById(uid); + if (!symbol) + return CompilerDecl(); + + auto decl = pdb->GetDeclForSymbol(*symbol); + if (!decl) + return CompilerDecl(); + + return CompilerDecl(clang_ast_ctx, decl); } lldb_private::CompilerDeclContext SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) { - // PDB always uses the translation unit decl context for everything. We can - // improve this later but it's not easy because PDB doesn't provide a high - // enough level of type fidelity in this area. - return *m_tu_decl_ctx_up; + ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + if (!clang_ast_ctx) + return CompilerDeclContext(); + + PDBASTParser *pdb = clang_ast_ctx->GetPDBParser(); + if (!pdb) + return CompilerDeclContext(); + + auto symbol = m_session_up->getSymbolById(uid); + if (!symbol) + return CompilerDeclContext(); + + auto decl_context = pdb->GetDeclContextForSymbol(*symbol); + if (!decl_context) + return GetDeclContextContainingUID(uid); + + return CompilerDeclContext(clang_ast_ctx, decl_context); } lldb_private::CompilerDeclContext SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { - return *m_tu_decl_ctx_up; + ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + if (!clang_ast_ctx) + return CompilerDeclContext(); + + PDBASTParser *pdb = clang_ast_ctx->GetPDBParser(); + if (!pdb) + return CompilerDeclContext(); + + auto symbol = m_session_up->getSymbolById(uid); + if (!symbol) + return CompilerDeclContext(); + + auto decl_context = pdb->GetDeclContextContainingSymbol(*symbol); + assert(decl_context); + + return CompilerDeclContext(clang_ast_ctx, decl_context); } void SymbolFilePDB::ParseDeclsForContext( - lldb_private::CompilerDeclContext decl_ctx) {} + lldb_private::CompilerDeclContext decl_ctx) { + ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( + GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus)); + if (!clang_ast_ctx) + return; + + PDBASTParser *pdb = clang_ast_ctx->GetPDBParser(); + if (!pdb) + return; + + pdb->ParseDeclsForDeclContext( + static_cast<clang::DeclContext *>(decl_ctx.GetOpaqueDeclContext())); +} uint32_t SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, - uint32_t resolve_scope, + SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) { uint32_t resolved_flags = 0; if (resolve_scope & eSymbolContextCompUnit || @@ -614,7 +696,8 @@ SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, lldbassert(sc.module_sp == cu_sp->GetModule()); } - if (resolve_scope & eSymbolContextFunction) { + if (resolve_scope & eSymbolContextFunction || + resolve_scope & eSymbolContextBlock) { addr_t file_vm_addr = so_addr.GetFileAddress(); auto symbol_up = m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::Function); @@ -624,12 +707,16 @@ SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, auto func_uid = pdb_func->getSymIndexId(); sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get(); if (sc.function == nullptr) - sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc); + sc.function = + ParseCompileUnitFunctionForPDBFunc(*pdb_func, *sc.comp_unit); if (sc.function) { resolved_flags |= eSymbolContextFunction; if (resolve_scope & eSymbolContextBlock) { - Block &block = sc.function->GetBlock(true); - sc.block = block.FindBlockByID(sc.function->GetID()); + auto block_symbol = m_session_up->findSymbolByAddress( + file_vm_addr, PDB_SymType::Block); + auto block_id = block_symbol ? block_symbol->getSymIndexId() + : sc.function->GetID(); + sc.block = sc.function->GetBlock(true).FindBlockByID(block_id); if (sc.block) resolved_flags |= eSymbolContextBlock; } @@ -650,7 +737,7 @@ SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, uint32_t SymbolFilePDB::ResolveSymbolContext( const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines, - uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list) { + SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) { const size_t old_size = sc_list.GetSize(); if (resolve_scope & lldb::eSymbolContextCompUnit) { // Locate all compilation units with line numbers referencing the specified @@ -674,7 +761,7 @@ uint32_t SymbolFilePDB::ResolveSymbolContext( std::string source_file = compiland->getSourceFileFullPath(); if (source_file.empty()) continue; - FileSpec this_spec(source_file, false, FileSpec::Style::windows); + FileSpec this_spec(source_file, FileSpec::Style::windows); bool need_full_match = !file_spec.GetDirectory().IsEmpty(); if (FileSpec::Compare(file_spec, this_spec, need_full_match) != 0) continue; @@ -691,7 +778,7 @@ uint32_t SymbolFilePDB::ResolveSymbolContext( // table that match the requested line (or all lines if `line` == 0). if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock | eSymbolContextLineEntry)) { - bool has_line_table = ParseCompileUnitLineTable(sc, line); + bool has_line_table = ParseCompileUnitLineTable(*sc.comp_unit, line); if ((resolve_scope & eSymbolContextLineEntry) && !has_line_table) { // The query asks for line entries, but we can't get them for the @@ -734,7 +821,8 @@ uint32_t SymbolFilePDB::ResolveSymbolContext( if (sc.function == nullptr) { auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get()); assert(pdb_func); - sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc); + sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, + *sc.comp_unit); } if (sc.function && (resolve_scope & eSymbolContextBlock)) { Block &block = sc.function->GetBlock(true); @@ -759,24 +847,16 @@ uint32_t SymbolFilePDB::ResolveSymbolContext( } std::string SymbolFilePDB::GetMangledForPDBData(const PDBSymbolData &pdb_data) { - std::string decorated_name; - auto vm_addr = pdb_data.getVirtualAddress(); - if (vm_addr != LLDB_INVALID_ADDRESS && vm_addr) { - auto result_up = - m_global_scope_up->findAllChildren(PDB_SymType::PublicSymbol); - if (result_up) { - while (auto symbol_up = result_up->getNext()) { - if (symbol_up->getRawSymbol().getVirtualAddress() == vm_addr) { - decorated_name = symbol_up->getRawSymbol().getName(); - break; - } - } - } - } - if (!decorated_name.empty()) - return decorated_name; + // Cache public names at first + if (m_public_names.empty()) + if (auto result_up = + m_global_scope_up->findAllChildren(PDB_SymType::PublicSymbol)) + while (auto symbol_up = result_up->getNext()) + if (auto addr = symbol_up->getRawSymbol().getVirtualAddress()) + m_public_names[addr] = symbol_up->getRawSymbol().getName(); - return std::string(); + // Look up the name in the cache + return m_public_names.lookup(pdb_data.getVirtualAddress()); } VariableSP SymbolFilePDB::ParseVariableForPDBData( @@ -843,7 +923,7 @@ VariableSP SymbolFilePDB::ParseVariableForPDBData( uint32_t src_file_id = first_line->getSourceFileId(); auto src_file = m_session_up->getSourceFileById(src_file_id); if (src_file) { - FileSpec spec(src_file->getFileName(), /*resolve_path*/ false); + FileSpec spec(src_file->getFileName()); decl.SetFile(spec); decl.SetColumn(first_line->getColumnNumber()); decl.SetLine(first_line->getLineNumber()); @@ -857,7 +937,7 @@ VariableSP SymbolFilePDB::ParseVariableForPDBData( if (scope == eValueTypeVariableLocal) { if (sc.function) { context_scope = sc.function->GetBlock(true).FindBlockByID( - pdb_data.getClassParentId()); + pdb_data.getLexicalParentId()); if (context_scope == nullptr) context_scope = sc.function; } @@ -937,6 +1017,9 @@ SymbolFilePDB::ParseVariables(const lldb_private::SymbolContext &sc, if (variable_list) variable_list->AddVariableIfUnique(var_sp); ++num_added; + PDBASTParser *ast = GetPDBAstParser(); + if (ast) + ast->GetDeclForSymbol(*pdb_data); } } } @@ -959,9 +1042,7 @@ uint32_t SymbolFilePDB::FindGlobalVariables( if (name.IsEmpty()) return 0; - auto results = - m_global_scope_up->findChildren(PDB_SymType::Data, name.GetStringRef(), - PDB_NameSearchFlags::NS_CaseSensitive); + auto results = m_global_scope_up->findAllChildren<PDBSymbolData>(); if (!results) return 0; @@ -976,11 +1057,19 @@ uint32_t SymbolFilePDB::FindGlobalVariables( sc.module_sp = m_obj_file->GetModule(); lldbassert(sc.module_sp.get()); - sc.comp_unit = ParseCompileUnitForUID(pdb_data->getCompilandId()).get(); + if (!name.GetStringRef().equals( + MSVCUndecoratedNameParser::DropScope(pdb_data->getName()))) + continue; + + sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get(); // FIXME: We are not able to determine the compile unit. if (sc.comp_unit == nullptr) continue; + if (parent_decl_ctx && GetDeclContextContainingUID( + result->getSymIndexId()) != *parent_decl_ctx) + continue; + ParseVariables(sc, *pdb_data, &variables); matches = variables.GetSize() - old_size; } @@ -1013,7 +1102,7 @@ SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression ®ex, sc.module_sp = m_obj_file->GetModule(); lldbassert(sc.module_sp.get()); - sc.comp_unit = ParseCompileUnitForUID(pdb_data->getCompilandId()).get(); + sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get(); // FIXME: We are not able to determine the compile unit. if (sc.comp_unit == nullptr) continue; @@ -1033,7 +1122,7 @@ bool SymbolFilePDB::ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func, if (!sc.comp_unit) return false; sc.module_sp = sc.comp_unit->GetModule(); - sc.function = ParseCompileUnitFunctionForPDBFunc(pdb_func, sc); + sc.function = ParseCompileUnitFunctionForPDBFunc(pdb_func, *sc.comp_unit); if (!sc.function) return false; @@ -1075,22 +1164,11 @@ void SymbolFilePDB::CacheFunctionNames() { // Class. We won't bother to check if the parent is UDT or Enum here. m_func_method_names.Append(ConstString(name), uid); - ConstString cstr_name(name); - // To search a method name, like NS::Class:MemberFunc, LLDB searches // its base name, i.e. MemberFunc by default. Since PDBSymbolFunc does // not have inforamtion of this, we extract base names and cache them // by our own effort. - llvm::StringRef basename; - CPlusPlusLanguage::MethodName cpp_method(cstr_name); - if (cpp_method.IsValid()) { - llvm::StringRef context; - basename = cpp_method.GetBasename(); - if (basename.empty()) - CPlusPlusLanguage::ExtractContextAndIdentifier(name.c_str(), - context, basename); - } - + llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(name); if (!basename.empty()) m_func_base_names.Append(ConstString(basename), uid); else { @@ -1103,11 +1181,12 @@ void SymbolFilePDB::CacheFunctionNames() { } else { // Handle not-method symbols. - // The function name might contain namespace, or its lexical scope. It - // is not safe to get its base name by applying same scheme as we deal - // with the method names. - // FIXME: Remove namespace if function is static in a scope. - m_func_base_names.Append(ConstString(name), uid); + // The function name might contain namespace, or its lexical scope. + llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(name); + if (!basename.empty()) + m_func_base_names.Append(ConstString(basename), uid); + else + m_func_base_names.Append(ConstString(name), uid); if (name == "main") { m_func_full_names.Append(ConstString(name), uid); @@ -1157,7 +1236,7 @@ void SymbolFilePDB::CacheFunctionNames() { uint32_t SymbolFilePDB::FindFunctions( const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, - uint32_t name_type_mask, bool include_inlines, bool append, + FunctionNameType name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList &sc_list) { if (!append) sc_list.Clear(); @@ -1177,20 +1256,28 @@ uint32_t SymbolFilePDB::FindFunctions( CacheFunctionNames(); std::set<uint32_t> resolved_ids; - auto ResolveFn = [include_inlines, &name, &sc_list, &resolved_ids, - this](UniqueCStringMap<uint32_t> &Names) { + auto ResolveFn = [this, &name, parent_decl_ctx, include_inlines, &sc_list, + &resolved_ids](UniqueCStringMap<uint32_t> &Names) { std::vector<uint32_t> ids; - if (Names.GetValues(name, ids)) { - for (auto id : ids) { - if (resolved_ids.find(id) == resolved_ids.end()) { - if (ResolveFunction(id, include_inlines, sc_list)) - resolved_ids.insert(id); - } - } + if (!Names.GetValues(name, ids)) + return; + + for (uint32_t id : ids) { + if (resolved_ids.find(id) != resolved_ids.end()) + continue; + + if (parent_decl_ctx && + GetDeclContextContainingUID(id) != *parent_decl_ctx) + continue; + + if (ResolveFunction(id, include_inlines, sc_list)) + resolved_ids.insert(id); } }; if (name_type_mask & eFunctionNameTypeFull) { ResolveFn(m_func_full_names); + ResolveFn(m_func_base_names); + ResolveFn(m_func_method_names); } if (name_type_mask & eFunctionNameTypeBase) { ResolveFn(m_func_base_names); @@ -1236,8 +1323,59 @@ void SymbolFilePDB::GetMangledNamesForFunction( const std::string &scope_qualified_name, std::vector<lldb_private::ConstString> &mangled_names) {} +void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { + std::set<lldb::addr_t> sym_addresses; + for (size_t i = 0; i < symtab.GetNumSymbols(); i++) + sym_addresses.insert(symtab.SymbolAtIndex(i)->GetFileAddress()); + + auto results = m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>(); + if (!results) + return; + + auto section_list = m_obj_file->GetSectionList(); + if (!section_list) + return; + + while (auto pub_symbol = results->getNext()) { + auto section_idx = pub_symbol->getAddressSection() - 1; + if (section_idx >= section_list->GetSize()) + continue; + + auto section = section_list->GetSectionAtIndex(section_idx); + if (!section) + continue; + + auto offset = pub_symbol->getAddressOffset(); + + auto file_addr = section->GetFileAddress() + offset; + if (sym_addresses.find(file_addr) != sym_addresses.end()) + continue; + sym_addresses.insert(file_addr); + + auto size = pub_symbol->getLength(); + symtab.AddSymbol( + Symbol(pub_symbol->getSymIndexId(), // symID + pub_symbol->getName().c_str(), // name + true, // name_is_mangled + pub_symbol->isCode() ? eSymbolTypeCode : eSymbolTypeData, // type + true, // external + false, // is_debug + false, // is_trampoline + false, // is_artificial + section, // section_sp + offset, // value + size, // size + size != 0, // size_is_valid + false, // contains_linker_annotations + 0 // flags + )); + } + + symtab.CalculateSymbolSizes(); + symtab.Finalize(); +} + uint32_t SymbolFilePDB::FindTypes( - const lldb_private::SymbolContext &sc, const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, @@ -1253,14 +1391,20 @@ uint32_t SymbolFilePDB::FindTypes( searched_symbol_files.clear(); searched_symbol_files.insert(this); - std::string name_str = name.AsCString(); - // There is an assumption 'name' is not a regex - FindTypesByName(name_str, max_matches, types); + FindTypesByName(name.GetStringRef(), parent_decl_ctx, max_matches, types); return types.GetSize(); } +void SymbolFilePDB::DumpClangAST(Stream &s) { + auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + auto clang = llvm::dyn_cast_or_null<ClangASTContext>(type_system); + if (!clang) + return; + clang->Dump(s); +} + void SymbolFilePDB::FindTypesByRegex( const lldb_private::RegularExpression ®ex, uint32_t max_matches, lldb_private::TypeMap &types) { @@ -1316,14 +1460,14 @@ void SymbolFilePDB::FindTypesByRegex( } } -void SymbolFilePDB::FindTypesByName(const std::string &name, - uint32_t max_matches, - lldb_private::TypeMap &types) { +void SymbolFilePDB::FindTypesByName( + llvm::StringRef name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, + uint32_t max_matches, lldb_private::TypeMap &types) { std::unique_ptr<IPDBEnumSymbols> results; if (name.empty()) return; - results = m_global_scope_up->findChildren(PDB_SymType::None, name, - PDB_NameSearchFlags::NS_Default); + results = m_global_scope_up->findAllChildren(PDB_SymType::None); if (!results) return; @@ -1332,6 +1476,11 @@ void SymbolFilePDB::FindTypesByName(const std::string &name, while (auto result = results->getNext()) { if (max_matches > 0 && matches >= max_matches) break; + + if (MSVCUndecoratedNameParser::DropScope( + result->getRawSymbol().getName()) != name) + continue; + switch (result->getSymTag()) { case PDB_SymType::Enum: case PDB_SymType::UDT: @@ -1348,6 +1497,10 @@ void SymbolFilePDB::FindTypesByName(const std::string &name, if (!ResolveTypeUID(result->getSymIndexId())) continue; + if (parent_decl_ctx && GetDeclContextContainingUID( + result->getSymIndexId()) != *parent_decl_ctx) + continue; + auto iter = m_types.find(result->getSymIndexId()); if (iter == m_types.end()) continue; @@ -1417,7 +1570,7 @@ void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol, } size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, - uint32_t type_mask, + TypeClass type_mask, lldb_private::TypeList &type_list) { TypeCollection type_collection; uint32_t old_size = type_list.GetSize(); @@ -1454,11 +1607,40 @@ SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { return type_system; } +PDBASTParser *SymbolFilePDB::GetPDBAstParser() { + auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + auto clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system); + if (!clang_type_system) + return nullptr; + + return clang_type_system->GetPDBParser(); +} + + lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace( - const lldb_private::SymbolContext &sc, const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx) { - return lldb_private::CompilerDeclContext(); + auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + auto clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system); + if (!clang_type_system) + return CompilerDeclContext(); + + PDBASTParser *pdb = clang_type_system->GetPDBParser(); + if (!pdb) + return CompilerDeclContext(); + + clang::DeclContext *decl_context = nullptr; + if (parent_decl_ctx) + decl_context = static_cast<clang::DeclContext *>( + parent_decl_ctx->GetOpaqueDeclContext()); + + auto namespace_decl = + pdb->FindNamespaceDecl(decl_context, name.GetStringRef()); + if (!namespace_decl) + return CompilerDeclContext(); + + return CompilerDeclContext(type_system, + static_cast<clang::DeclContext *>(namespace_decl)); } lldb_private::ConstString SymbolFilePDB::GetPluginName() { @@ -1516,11 +1698,9 @@ lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForUID(uint32_t id, return cu_sp; } -bool SymbolFilePDB::ParseCompileUnitLineTable( - const lldb_private::SymbolContext &sc, uint32_t match_line) { - lldbassert(sc.comp_unit); - - auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID()); +bool SymbolFilePDB::ParseCompileUnitLineTable(CompileUnit &comp_unit, + uint32_t match_line) { + auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID()); if (!compiland_up) return false; @@ -1530,10 +1710,10 @@ bool SymbolFilePDB::ParseCompileUnitLineTable( // to do a mapping so that we can hand out indices. llvm::DenseMap<uint32_t, uint32_t> index_map; BuildSupportFileIdToSupportFileIndexMap(*compiland_up, index_map); - auto line_table = llvm::make_unique<LineTable>(sc.comp_unit); + auto line_table = llvm::make_unique<LineTable>(&comp_unit); // Find contributions to `compiland` from all source and header files. - std::string path = sc.comp_unit->GetPath(); + std::string path = comp_unit.GetPath(); auto files = m_session_up->getSourceFilesForCompiland(*compiland_up); if (!files) return false; @@ -1617,7 +1797,7 @@ bool SymbolFilePDB::ParseCompileUnitLineTable( } if (line_table->GetSize()) { - sc.comp_unit->SetLineTable(line_table.release()); + comp_unit.SetLineTable(line_table.release()); return true; } return false; @@ -1747,3 +1927,68 @@ bool SymbolFilePDB::DeclContextMatchesThisSymbolFile( return false; } + +uint32_t SymbolFilePDB::GetCompilandId(const llvm::pdb::PDBSymbolData &data) { + static const auto pred_upper = [](uint32_t lhs, SecContribInfo rhs) { + return lhs < rhs.Offset; + }; + + // Cache section contributions + if (m_sec_contribs.empty()) { + if (auto SecContribs = m_session_up->getSectionContribs()) { + while (auto SectionContrib = SecContribs->getNext()) { + auto comp_id = SectionContrib->getCompilandId(); + if (!comp_id) + continue; + + auto sec = SectionContrib->getAddressSection(); + auto &sec_cs = m_sec_contribs[sec]; + + auto offset = SectionContrib->getAddressOffset(); + auto it = + std::upper_bound(sec_cs.begin(), sec_cs.end(), offset, pred_upper); + + auto size = SectionContrib->getLength(); + sec_cs.insert(it, {offset, size, comp_id}); + } + } + } + + // Check by line number + if (auto Lines = data.getLineNumbers()) { + if (auto FirstLine = Lines->getNext()) + return FirstLine->getCompilandId(); + } + + // Retrieve section + offset + uint32_t DataSection = data.getAddressSection(); + uint32_t DataOffset = data.getAddressOffset(); + if (DataSection == 0) { + if (auto RVA = data.getRelativeVirtualAddress()) + m_session_up->addressForRVA(RVA, DataSection, DataOffset); + } + + if (DataSection) { + // Search by section contributions + auto &sec_cs = m_sec_contribs[DataSection]; + auto it = + std::upper_bound(sec_cs.begin(), sec_cs.end(), DataOffset, pred_upper); + if (it != sec_cs.begin()) { + --it; + if (DataOffset < it->Offset + it->Size) + return it->CompilandId; + } + } else { + // Search in lexical tree + auto LexParentId = data.getLexicalParentId(); + while (auto LexParent = m_session_up->getSymbolById(LexParentId)) { + if (LexParent->getSymTag() == PDB_SymType::Exe) + break; + if (LexParent->getSymTag() == PDB_SymType::Compiland) + return LexParentId; + LexParentId = LexParent->getRawSymbol().getLexicalParentId(); + } + } + + return 0; +} diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h index 96b62d68a6c2..81288093b7d8 100644 --- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -20,6 +20,8 @@ #include "llvm/DebugInfo/PDB/PDB.h" #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +class PDBASTParser; + class SymbolFilePDB : public lldb_private::SymbolFile { public: //------------------------------------------------------------------ @@ -58,33 +60,32 @@ public: lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override; lldb::LanguageType - ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) override; + ParseLanguage(lldb_private::CompileUnit &comp_unit) override; - size_t - ParseCompileUnitFunctions(const lldb_private::SymbolContext &sc) override; + size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override; - bool - ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc) override; + bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override; - bool - ParseCompileUnitDebugMacros(const lldb_private::SymbolContext &sc) override; + bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; - bool ParseCompileUnitSupportFiles( - const lldb_private::SymbolContext &sc, - lldb_private::FileSpecList &support_files) override; + bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, + lldb_private::FileSpecList &support_files) override; + + size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override; bool ParseImportedModules( const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules) override; - size_t ParseFunctionBlocks(const lldb_private::SymbolContext &sc) override; - - size_t ParseTypes(const lldb_private::SymbolContext &sc) override; + size_t ParseBlocksRecursive(lldb_private::Function &func) override; size_t ParseVariablesForContext(const lldb_private::SymbolContext &sc) override; lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override; + llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID( + lldb::user_id_t type_uid, + const lldb_private::ExecutionContext *exe_ctx) override; bool CompleteType(lldb_private::CompilerType &compiler_type) override; @@ -100,12 +101,13 @@ public: ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override; uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr, - uint32_t resolve_scope, + lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) override; uint32_t ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line, - bool check_inlines, uint32_t resolve_scope, + bool check_inlines, + lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) override; uint32_t @@ -121,8 +123,8 @@ public: uint32_t FindFunctions(const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, - uint32_t name_type_mask, bool include_inlines, bool append, - lldb_private::SymbolContextList &sc_list) override; + lldb::FunctionNameType name_type_mask, bool include_inlines, + bool append, lldb_private::SymbolContextList &sc_list) override; uint32_t FindFunctions(const lldb_private::RegularExpression ®ex, bool include_inlines, bool append, @@ -132,9 +134,10 @@ public: const std::string &scope_qualified_name, std::vector<lldb_private::ConstString> &mangled_names) override; + void AddSymbols(lldb_private::Symtab &symtab) override; + uint32_t - FindTypes(const lldb_private::SymbolContext &sc, - const lldb_private::ConstString &name, + FindTypes(const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, @@ -149,14 +152,13 @@ public: lldb_private::TypeList *GetTypeList() override; size_t GetTypes(lldb_private::SymbolContextScope *sc_scope, - uint32_t type_mask, + lldb::TypeClass type_mask, lldb_private::TypeList &type_list) override; lldb_private::TypeSystem * GetTypeSystemForLanguage(lldb::LanguageType language) override; lldb_private::CompilerDeclContext FindNamespace( - const lldb_private::SymbolContext &sc, const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx) override; @@ -168,19 +170,29 @@ public: const llvm::pdb::IPDBSession &GetPDBSession() const; + void DumpClangAST(lldb_private::Stream &s) override; + private: + struct SecContribInfo { + uint32_t Offset; + uint32_t Size; + uint32_t CompilandId; + }; + using SecContribsMap = std::map<uint32_t, std::vector<SecContribInfo>>; + lldb::CompUnitSP ParseCompileUnitForUID(uint32_t id, uint32_t index = UINT32_MAX); - bool ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc, + bool ParseCompileUnitLineTable(lldb_private::CompileUnit &comp_unit, uint32_t match_line); void BuildSupportFileIdToSupportFileIndexMap( const llvm::pdb::PDBSymbolCompiland &pdb_compiland, llvm::DenseMap<uint32_t, uint32_t> &index_map) const; - void FindTypesByName(const std::string &name, uint32_t max_matches, - lldb_private::TypeMap &types); + void FindTypesByName(llvm::StringRef name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, + uint32_t max_matches, lldb_private::TypeMap &types); std::string GetMangledForPDBData(const llvm::pdb::PDBSymbolData &pdb_data); @@ -203,11 +215,13 @@ private: lldb_private::Function * ParseCompileUnitFunctionForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func, - const lldb_private::SymbolContext &sc); + lldb_private::CompileUnit &comp_unit); void GetCompileUnitIndex(const llvm::pdb::PDBSymbolCompiland &pdb_compiland, uint32_t &index); + PDBASTParser *GetPDBAstParser(); + std::unique_ptr<llvm::pdb::PDBSymbolCompiland> GetPDBCompilandByUID(uint32_t uid); @@ -226,9 +240,14 @@ private: bool DeclContextMatchesThisSymbolFile( const lldb_private::CompilerDeclContext *decl_ctx); + uint32_t GetCompilandId(const llvm::pdb::PDBSymbolData &data); + llvm::DenseMap<uint32_t, lldb::CompUnitSP> m_comp_units; llvm::DenseMap<uint32_t, lldb::TypeSP> m_types; llvm::DenseMap<uint32_t, lldb::VariableSP> m_variables; + llvm::DenseMap<uint64_t, std::string> m_public_names; + + SecContribsMap m_sec_contribs; std::vector<lldb::TypeSP> m_builtin_types; std::unique_ptr<llvm::pdb::IPDBSession> m_session_up; |
