summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Symbol/ClangASTContext.h12
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt1
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp236
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h55
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp170
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h22
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp32
-rw-r--r--lldb/unittests/SymbolFile/PDB/CMakeLists.txt4
-rw-r--r--lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp86
-rw-r--r--lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdbbin0 -> 143360 bytes
-rw-r--r--lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp246
11 files changed, 844 insertions, 20 deletions
diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h
index 922ce695b58..edfa3d1c2a7 100644
--- a/lldb/include/lldb/Symbol/ClangASTContext.h
+++ b/lldb/include/lldb/Symbol/ClangASTContext.h
@@ -37,6 +37,7 @@
#include "lldb/lldb-enumerations.h"
class DWARFASTParserClang;
+class PDBASTParser;
namespace lldb_private {
@@ -524,6 +525,8 @@ public:
//------------------------------------------------------------------
DWARFASTParser *
GetDWARFParser() override;
+ PDBASTParser *
+ GetPDBParser();
//------------------------------------------------------------------
// ClangASTContext callbacks for external source lookups.
@@ -696,7 +699,13 @@ public:
bool
IsPolymorphicClass (lldb::opaque_compiler_type_t type) override;
-
+
+ static bool
+ IsClassType(lldb::opaque_compiler_type_t type);
+
+ static bool
+ IsEnumType(lldb::opaque_compiler_type_t type);
+
bool
IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
CompilerType *target_type, // Can pass nullptr
@@ -1189,6 +1198,7 @@ protected:
std::unique_ptr<clang::SelectorTable> m_selector_table_ap;
std::unique_ptr<clang::Builtin::Context> m_builtins_ap;
std::unique_ptr<DWARFASTParserClang> m_dwarf_ast_parser_ap;
+ std::unique_ptr<PDBASTParser> m_pdb_ast_parser_ap;
std::unique_ptr<ClangASTSource> m_scratch_ast_source_ap;
std::unique_ptr<clang::MangleContext> m_mangle_ctx_ap;
CompleteTagDeclCallback m_callback_tag_decl;
diff --git a/lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt
index 4e7913b610a..79d8a25d697 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt
+++ b/lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt
@@ -2,5 +2,6 @@ set(LLVM_PRIVATE_LINK_COMPONENTS
DebugInfoPDB)
add_lldb_library(lldbPluginSymbolFilePDB
+ PDBASTParser.cpp
SymbolFilePDB.cpp
)
diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
new file mode 100644
index 00000000000..d4e92bf4f32
--- /dev/null
+++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -0,0 +1,236 @@
+//===-- PDBASTParser.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PDBASTParser.h"
+
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangUtil.h"
+#include "lldb/Symbol/Declaration.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/TypeSystem.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm;
+
+namespace
+{
+int
+TranslateUdtKind(PDB_UdtType pdb_kind)
+{
+ switch (pdb_kind)
+ {
+ case PDB_UdtType::Class:
+ return clang::TTK_Class;
+ case PDB_UdtType::Struct:
+ return clang::TTK_Struct;
+ case PDB_UdtType::Union:
+ return clang::TTK_Union;
+ case PDB_UdtType::Interface:
+ return clang::TTK_Interface;
+ }
+ return clang::TTK_Class;
+}
+
+lldb::Encoding
+TranslateBuiltinEncoding(PDB_BuiltinType type)
+{
+ switch (type)
+ {
+ case PDB_BuiltinType::Float:
+ return lldb::eEncodingIEEE754;
+ case PDB_BuiltinType::Int:
+ case PDB_BuiltinType::Long:
+ case PDB_BuiltinType::Char:
+ return lldb::eEncodingSint;
+ case PDB_BuiltinType::Bool:
+ case PDB_BuiltinType::UInt:
+ case PDB_BuiltinType::ULong:
+ case PDB_BuiltinType::HResult:
+ return lldb::eEncodingUint;
+ default:
+ return lldb::eEncodingInvalid;
+ }
+}
+}
+
+PDBASTParser::PDBASTParser(lldb_private::ClangASTContext &ast) : m_ast(ast)
+{
+}
+
+PDBASTParser::~PDBASTParser()
+{
+}
+
+// DebugInfoASTParser interface
+
+lldb::TypeSP
+PDBASTParser::CreateLLDBTypeFromPDBType(const llvm::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;
+
+ if (auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&type))
+ {
+ AccessType access = lldb::eAccessPublic;
+ PDB_UdtType udt_kind = udt->getUdtKind();
+
+ if (udt_kind == PDB_UdtType::Class)
+ access = lldb::eAccessPrivate;
+
+ CompilerType clang_type =
+ m_ast.CreateRecordType(tu_decl_ctx, access, udt->getName().c_str(), TranslateUdtKind(udt_kind),
+ lldb::eLanguageTypeC_plus_plus, nullptr);
+
+ m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
+
+ return std::make_shared<Type>(type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(udt->getName()),
+ udt->getLength(), nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
+ clang_type, Type::eResolveStateForward);
+ }
+ else if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type))
+ {
+ std::string name = enum_type->getName();
+ lldb::Encoding encoding = TranslateBuiltinEncoding(enum_type->getBuiltinType());
+ uint64_t bytes = enum_type->getLength();
+ CompilerType builtin_type = m_ast.GetBuiltinTypeForEncodingAndBitSize(encoding, bytes * 8);
+
+ CompilerType ast_enum = m_ast.CreateEnumerationType(name.c_str(), tu_decl_ctx, decl, builtin_type);
+ auto enum_values = enum_type->findAllChildren<PDBSymbolData>();
+ while (auto enum_value = enum_values->getNext())
+ {
+ if (enum_value->getDataKind() != PDB_DataKind::Constant)
+ continue;
+ AddEnumValue(ast_enum, *enum_value);
+ }
+
+ return std::make_shared<Type>(type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes, nullptr,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ast_enum, Type::eResolveStateFull);
+ }
+ else if (auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type))
+ {
+ Type *target_type = m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId());
+ std::string name = type_def->getName();
+ uint64_t bytes = type_def->getLength();
+ if (!target_type)
+ return nullptr;
+ CompilerType target_ast_type = target_type->GetFullCompilerType();
+ CompilerDeclContext target_decl_ctx = m_ast.GetSymbolFile()->GetDeclContextForUID(target_type->GetID());
+ CompilerType ast_typedef = m_ast.CreateTypedefType(target_ast_type, name.c_str(), target_decl_ctx);
+ return std::make_shared<Type>(type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes,
+ nullptr, target_type->GetID(), Type::eEncodingIsTypedefUID, decl, ast_typedef,
+ Type::eResolveStateFull);
+ }
+ else if (auto func_sig = llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type))
+ {
+ auto arg_enum = func_sig->getArguments();
+ uint32_t num_args = arg_enum->getChildCount();
+ std::vector<CompilerType> arg_list(num_args);
+ while (auto arg = arg_enum->getNext())
+ {
+ Type *arg_type = m_ast.GetSymbolFile()->ResolveTypeUID(arg->getSymIndexId());
+ // If there's some error looking up one of the dependent types of this function signature, bail.
+ if (!arg_type)
+ return nullptr;
+ CompilerType arg_ast_type = arg_type->GetFullCompilerType();
+ arg_list.push_back(arg_ast_type);
+ }
+ auto pdb_return_type = func_sig->getReturnType();
+ Type *return_type = m_ast.GetSymbolFile()->ResolveTypeUID(pdb_return_type->getSymIndexId());
+ // If there's some error looking up one of the dependent types of this function signature, bail.
+ if (!return_type)
+ return nullptr;
+ CompilerType return_ast_type = return_type->GetFullCompilerType();
+ uint32_t type_quals = 0;
+ if (func_sig->isConstType())
+ type_quals |= clang::Qualifiers::Const;
+ if (func_sig->isVolatileType())
+ type_quals |= clang::Qualifiers::Volatile;
+ CompilerType func_sig_ast_type =
+ m_ast.CreateFunctionType(return_ast_type, &arg_list[0], num_args, false, type_quals);
+
+ return std::make_shared<Type>(func_sig->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), 0, nullptr,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_sig_ast_type,
+ Type::eResolveStateFull);
+ }
+ else if (auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type))
+ {
+ uint32_t num_elements = array_type->getCount();
+ uint32_t element_uid = array_type->getElementType()->getSymIndexId();
+ uint32_t bytes = array_type->getLength();
+
+ Type *element_type = m_ast.GetSymbolFile()->ResolveTypeUID(element_uid);
+ CompilerType element_ast_type = element_type->GetFullCompilerType();
+ CompilerType array_ast_type = m_ast.CreateArrayType(element_ast_type, num_elements, false);
+ return std::make_shared<Type>(array_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), bytes, nullptr,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, decl, array_ast_type,
+ Type::eResolveStateFull);
+ }
+ return nullptr;
+}
+
+bool
+PDBASTParser::AddEnumValue(CompilerType enum_type, const llvm::PDBSymbolData &enum_value) const
+{
+ Declaration decl;
+ Variant v = enum_value.getValue();
+ std::string name = enum_value.getName();
+ int64_t raw_value;
+ switch (v.Type)
+ {
+ case PDB_VariantType::Int8:
+ raw_value = v.Value.Int8;
+ break;
+ case PDB_VariantType::Int16:
+ raw_value = v.Value.Int16;
+ break;
+ case PDB_VariantType::Int32:
+ raw_value = v.Value.Int32;
+ break;
+ case PDB_VariantType::Int64:
+ raw_value = v.Value.Int64;
+ break;
+ case PDB_VariantType::UInt8:
+ raw_value = v.Value.UInt8;
+ break;
+ case PDB_VariantType::UInt16:
+ raw_value = v.Value.UInt16;
+ break;
+ case PDB_VariantType::UInt32:
+ raw_value = v.Value.UInt32;
+ break;
+ case PDB_VariantType::UInt64:
+ raw_value = v.Value.UInt64;
+ break;
+ default:
+ return false;
+ }
+ CompilerType underlying_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);
+}
diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h
new file mode 100644
index 00000000000..b82620148ca
--- /dev/null
+++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.h
@@ -0,0 +1,55 @@
+//===-- PDBASTParser.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SYMBOLFILE_PDB_PDBASTPARSER_H
+#define LLDB_PLUGINS_SYMBOLFILE_PDB_PDBASTPARSER_H
+
+#include "lldb/lldb-forward.h"
+
+#include "lldb/Symbol/ClangASTImporter.h"
+
+namespace clang
+{
+class CharUnits;
+class CXXRecordDecl;
+class FieldDecl;
+class RecordDecl;
+}
+
+namespace lldb_private
+{
+class ClangASTContext;
+class CompilerType;
+}
+
+namespace llvm
+{
+class PDBSymbol;
+class PDBSymbolData;
+class PDBSymbolTypeBuiltin;
+}
+
+class PDBASTParser
+{
+public:
+ PDBASTParser(lldb_private::ClangASTContext &ast);
+ ~PDBASTParser();
+
+ lldb::TypeSP
+ CreateLLDBTypeFromPDBType(const llvm::PDBSymbol &type);
+
+private:
+ bool
+ AddEnumValue(lldb_private::CompilerType enum_type, const llvm::PDBSymbolData &data) const;
+
+ lldb_private::ClangASTContext &m_ast;
+ lldb_private::ClangASTImporter m_ast_importer;
+};
+
+#endif // SymbolFileDWARF_DWARFASTParserClang_h_
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index a6357408551..9a82f4d40fd 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -9,12 +9,16 @@
#include "SymbolFilePDB.h"
+#include "clang/Lex/Lexer.h"
+
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/TypeMap.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
@@ -26,6 +30,13 @@
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
+
+#include <regex>
using namespace lldb_private;
@@ -116,6 +127,10 @@ SymbolFilePDB::InitializeObject()
{
lldb::addr_t obj_load_address = m_obj_file->GetFileOffset();
m_session_up->setLoadAddress(obj_load_address);
+
+ TypeSystem *type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ ClangASTContext *clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system);
+ m_tu_decl_ctx_up = llvm::make_unique<CompilerDeclContext>(type_system, clang_type_system->GetTranslationUnitDecl());
}
uint32_t
@@ -245,7 +260,25 @@ SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc)
lldb_private::Type *
SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid)
{
- return nullptr;
+ auto find_result = m_types.find(type_uid);
+ if (find_result != m_types.end())
+ return find_result->second.get();
+
+ TypeSystem *type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ ClangASTContext *clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system);
+ if (!clang_type_system)
+ return nullptr;
+ PDBASTParser *pdb = llvm::dyn_cast<PDBASTParser>(clang_type_system->GetPDBParser());
+ if (!pdb)
+ return nullptr;
+
+ auto pdb_type = m_session_up->getSymbolById(type_uid);
+ if (pdb_type == nullptr)
+ return nullptr;
+
+ lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type);
+ m_types.insert(std::make_pair(type_uid, result));
+ return result.get();
}
bool
@@ -264,13 +297,15 @@ SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid)
lldb_private::CompilerDeclContext
SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid)
{
- return lldb_private::CompilerDeclContext();
+ // 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;
}
lldb_private::CompilerDeclContext
SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid)
{
- return lldb_private::CompilerDeclContext();
+ return *m_tu_decl_ctx_up;
}
void
@@ -376,14 +411,121 @@ SymbolFilePDB::FindTypes(const lldb_private::SymbolContext &sc, const lldb_priva
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types)
{
- return uint32_t();
+ if (!append)
+ types.Clear();
+ if (!name)
+ return 0;
+
+ searched_symbol_files.clear();
+ searched_symbol_files.insert(this);
+
+ std::string name_str = name.AsCString();
+
+ // If this might be a regex, we have to return EVERY symbol and process them one by one, which is going
+ // to destroy performance on large PDB files. So try really hard not to use a regex match.
+ if (name_str.find_first_of("[]?*.-+\\") != std::string::npos)
+ FindTypesByRegex(name_str, max_matches, types);
+ else
+ FindTypesByName(name_str, max_matches, types);
+ return types.GetSize();
+}
+
+void
+SymbolFilePDB::FindTypesByRegex(const std::string &regex, uint32_t max_matches, lldb_private::TypeMap &types)
+{
+ // When searching by regex, we need to go out of our way to limit the search space as much as possible, since
+ // the way this is implemented is by searching EVERYTHING in the PDB and manually doing a regex compare. PDB
+ // library isn't optimized for regex searches or searches across multiple symbol types at the same time, so the
+ // best we can do is to search enums, then typedefs, then classes one by one, and do a regex compare against all
+ // of them.
+ llvm::PDB_SymType tags_to_search[] = {llvm::PDB_SymType::Enum, llvm::PDB_SymType::Typedef, llvm::PDB_SymType::UDT};
+ auto global = m_session_up->getGlobalScope();
+ std::unique_ptr<llvm::IPDBEnumSymbols> results;
+
+ std::regex re(regex);
+
+ uint32_t matches = 0;
+
+ for (auto tag : tags_to_search)
+ {
+ results = global->findAllChildren(tag);
+ while (auto result = results->getNext())
+ {
+ if (max_matches > 0 && matches >= max_matches)
+ break;
+
+ std::string type_name;
+ if (auto enum_type = llvm::dyn_cast<llvm::PDBSymbolTypeEnum>(result.get()))
+ type_name = enum_type->getName();
+ else if (auto typedef_type = llvm::dyn_cast<llvm::PDBSymbolTypeTypedef>(result.get()))
+ type_name = typedef_type->getName();
+ else if (auto class_type = llvm::dyn_cast<llvm::PDBSymbolTypeUDT>(result.get()))
+ type_name = class_type->getName();
+ else
+ {
+ // We're only looking for types that have names. Skip symbols, as well as
+ // unnamed types such as arrays, pointers, etc.
+ continue;
+ }
+
+ if (!std::regex_match(type_name, re))
+ continue;
+
+ // This should cause the type to get cached and stored in the `m_types` lookup.
+ if (!ResolveTypeUID(result->getSymIndexId()))
+ continue;
+
+ auto iter = m_types.find(result->getSymIndexId());
+ if (iter == m_types.end())
+ continue;
+ types.Insert(iter->second);
+ ++matches;
+ }
+ }
+}
+
+void
+SymbolFilePDB::FindTypesByName(const std::string &name, uint32_t max_matches, lldb_private::TypeMap &types)
+{
+ auto global = m_session_up->getGlobalScope();
+ std::unique_ptr<llvm::IPDBEnumSymbols> results;
+ results = global->findChildren(llvm::PDB_SymType::None, name.c_str(), llvm::PDB_NameSearchFlags::NS_Default);
+
+ uint32_t matches = 0;
+
+ while (auto result = results->getNext())
+ {
+ if (max_matches > 0 && matches >= max_matches)
+ break;
+ switch (result->getSymTag())
+ {
+ case llvm::PDB_SymType::Enum:
+ case llvm::PDB_SymType::UDT:
+ case llvm::PDB_SymType::Typedef:
+ break;
+ default:
+ // We're only looking for types that have names. Skip symbols, as well as
+ // unnamed types such as arrays, pointers, etc.
+ continue;
+ }
+
+ // This should cause the type to get cached and stored in the `m_types` lookup.
+ if (!ResolveTypeUID(result->getSymIndexId()))
+ continue;
+
+ auto iter = m_types.find(result->getSymIndexId());
+ if (iter == m_types.end())
+ continue;
+ types.Insert(iter->second);
+ ++matches;
+ }
}
size_t
-SymbolFilePDB::FindTypes(const std::vector<lldb_private::CompilerContext> &context, bool append,
+SymbolFilePDB::FindTypes(const std::vector<lldb_private::CompilerContext> &contexts, bool append,
lldb_private::TypeMap &types)
{
- return size_t();
+ return 0;
}
lldb_private::TypeList *
@@ -428,6 +570,18 @@ SymbolFilePDB::GetPluginVersion()
return 1;
}
+llvm::IPDBSession &
+SymbolFilePDB::GetPDBSession()
+{
+ return *m_session_up;
+}
+
+const llvm::IPDBSession &
+SymbolFilePDB::GetPDBSession() const
+{
+ return *m_session_up;
+}
+
lldb::CompUnitSP
SymbolFilePDB::ParseCompileUnitForSymIndex(uint32_t id)
{
@@ -470,7 +624,7 @@ SymbolFilePDB::ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc,
// ParseCompileUnitSupportFiles. But the underlying SDK gives us a globally unique
// idenfitifier in the namespace of the PDB. So, we have to do a mapping so that we
// can hand out indices.
- std::unordered_map<uint32_t, uint32_t> index_map;
+ llvm::DenseMap<uint32_t, uint32_t> index_map;
BuildSupportFileIdToSupportFileIndexMap(*cu, index_map);
auto line_table = llvm::make_unique<LineTable>(sc.comp_unit);
@@ -555,7 +709,7 @@ SymbolFilePDB::ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc,
void
SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(const llvm::PDBSymbolCompiland &cu,
- std::unordered_map<uint32_t, uint32_t> &index_map) const
+ llvm::DenseMap<uint32_t, uint32_t> &index_map) const
{
// This is a hack, but we need to convert the source id into an index into the support
// files array. We don't want to do path comparisons to avoid basename / full path
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
index 019b4767955..112b54c5901 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -10,11 +10,10 @@
#ifndef lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
#define lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
-#include <unordered_map>
-
#include "lldb/Core/UserID.h"
#include "lldb/Symbol/SymbolFile.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDB.h"
@@ -170,6 +169,12 @@ public:
uint32_t
GetPluginVersion() override;
+ llvm::IPDBSession &
+ GetPDBSession();
+
+ const llvm::IPDBSession &
+ GetPDBSession() const;
+
private:
lldb::CompUnitSP
ParseCompileUnitForSymIndex(uint32_t id);
@@ -179,12 +184,21 @@ private:
void
BuildSupportFileIdToSupportFileIndexMap(const llvm::PDBSymbolCompiland &cu,
- std::unordered_map<uint32_t, uint32_t> &index_map) const;
+ llvm::DenseMap<uint32_t, uint32_t> &index_map) const;
+
+ void
+ FindTypesByRegex(const std::string &regex, uint32_t max_matches, lldb_private::TypeMap &types);
+
+ void
+ FindTypesByName(const std::string &name, uint32_t max_matches, lldb_private::TypeMap &types);
- std::unordered_map<uint32_t, lldb::CompUnitSP> m_comp_units;
+ llvm::DenseMap<uint32_t, lldb::CompUnitSP> m_comp_units;
+ llvm::DenseMap<uint32_t, lldb::TypeSP> m_types;
+ std::vector<lldb::TypeSP> m_builtin_types;
std::unique_ptr<llvm::IPDBSession> m_session_up;
uint32_t m_cached_compile_unit_count;
+ std::unique_ptr<lldb_private::CompilerDeclContext> m_tu_decl_ctx_up;
};
#endif // lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp
index 7a62f82532b..aab4593a313 100644
--- a/lldb/source/Symbol/ClangASTContext.cpp
+++ b/lldb/source/Symbol/ClangASTContext.cpp
@@ -90,6 +90,7 @@
#include "lldb/Target/Target.h"
#include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
+#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
#include <stdio.h>
@@ -3442,7 +3443,27 @@ ClangASTContext::IsObjCObjectOrInterfaceType (const CompilerType& type)
}
bool
-ClangASTContext::IsPolymorphicClass (lldb::opaque_compiler_type_t type)
+ClangASTContext::IsClassType(lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return false;
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ return (type_class == clang::Type::Record);
+}
+
+bool
+ClangASTContext::IsEnumType(lldb::opaque_compiler_type_t type)
+{
+ if (!type)
+ return false;
+ clang::QualType qual_type(GetCanonicalQualType(type));
+ const clang::Type::TypeClass type_class = qual_type->getTypeClass();
+ return (type_class == clang::Type::Enum);
+}
+
+bool
+ClangASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type)
{
if (type)
{
@@ -5204,7 +5225,7 @@ ClangASTContext::GetNumChildren (lldb::opaque_compiler_type_t type, bool omit_em
CompilerType
ClangASTContext::GetBuiltinTypeByName (const ConstString &name)
{
- return GetBasicType (GetBasicTypeEnumeration (name));
+ return GetBasicType(GetBasicTypeEnumeration(name));
}
lldb::BasicType
@@ -9472,6 +9493,13 @@ ClangASTContext::GetDWARFParser()
return m_dwarf_ast_parser_ap.get();
}
+PDBASTParser *
+ClangASTContext::GetPDBParser()
+{
+ if (!m_pdb_ast_parser_ap)
+ m_pdb_ast_parser_ap.reset(new PDBASTParser(*this));
+ return m_pdb_ast_parser_ap.get();
+}
bool
ClangASTContext::LayoutRecordType(void *baton,
diff --git a/lldb/unittests/SymbolFile/PDB/CMakeLists.txt b/lldb/unittests/SymbolFile/PDB/CMakeLists.txt
index 4cb49435b39..fcfb5e3062c 100644
--- a/lldb/unittests/SymbolFile/PDB/CMakeLists.txt
+++ b/lldb/unittests/SymbolFile/PDB/CMakeLists.txt
@@ -5,6 +5,8 @@ add_lldb_unittest(SymbolFilePDBTests
set(test_inputs
test-pdb.exe
test-pdb.pdb
- test-dwarf.exe)
+ test-dwarf.exe
+ test-pdb-types.exe
+ test-pdb-types.pdb)
add_unittest_inputs(SymbolFilePDBTests "${test_inputs}")
diff --git a/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp
new file mode 100644
index 00000000000..9639a3f4b72
--- /dev/null
+++ b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp
@@ -0,0 +1,86 @@
+// Compile with "cl /c /Zi /GR- /EHsc test-pdb-types.cpp"
+// Link with "link test-pdb-types.obj /debug /nodefaultlib /entry:main /out:test-pdb-types.exe"
+
+using namespace std;
+
+// Sizes of builtin types
+static const int sizeof_char = sizeof(char);
+static const int sizeof_uchar = sizeof(unsigned char);
+static const int sizeof_short = sizeof(short);
+static const int sizeof_ushort = sizeof(unsigned short);
+static const int sizeof_int = sizeof(int);
+static const int sizeof_uint = sizeof(unsigned int);
+static const int sizeof_long = sizeof(long);
+static const int sizeof_ulong = sizeof(unsigned long);
+static const int sizeof_longlong = sizeof(long long);
+static const int sizeof_ulonglong = sizeof(unsigned long long);
+static const int sizeof_int64 = sizeof(__int64);
+static const int sizeof_uint64 = sizeof(unsigned __int64);
+static const int sizeof_float = sizeof(float);
+static const int sizeof_double = sizeof(double);
+static const int sizeof_bool = sizeof(bool);
+static const int sizeof_wchar = sizeof(wchar_t);
+
+enum Enum
+{
+ EValue1 = 1,
+ EValue2 = 2,
+};
+
+enum ShortEnum : short
+{
+ ESValue1 = 1,
+ ESValue2 = 2
+};
+
+namespace NS
+{
+class NSClass
+{
+ float f;
+ double d;
+};
+}
+
+class Class
+{
+public:
+ class NestedClass
+ {
+ Enum e;
+ };
+ ShortEnum se;
+};
+
+int
+test_func(int a, int b)
+{
+ return a + b;
+}
+
+typedef Class ClassTypedef;
+typedef NS::NSClass NSClassTypedef;
+int GlobalArray[10];
+
+static const int sizeof_NSClass = sizeof(NS::NSClass);
+static const int sizeof_Class = sizeof(Class);
+static const int sizeof_NestedClass = sizeof(Class::NestedClass);
+static const int sizeof_Enum = sizeof(Enum);
+static const int sizeof_ShortEnum = sizeof(ShortEnum);
+static const int sizeof_ClassTypedef = sizeof(ClassTypedef);
+static const int sizeof_NSClassTypedef = sizeof(NSClassTypedef);
+static const int sizeof_GlobalArray = sizeof(GlobalArray);
+
+int
+main(int argc, char **argv)
+{
+ ShortEnum e1;
+ Enum e2;
+ Class c1;
+ Class::NestedClass c2;
+ NS::NSClass c3;
+
+ ClassTypedef t1;
+ NSClassTypedef t2;
+ return test_func(1, 2);
+}
diff --git a/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdb b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdb
new file mode 100644
index 00000000000..acf241bcb5d
--- /dev/null
+++ b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdb
Binary files differ
diff --git a/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp b/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
index b1914997be7..0b96723b6cf 100644
--- a/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
+++ b/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
@@ -11,6 +11,8 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/config.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -20,6 +22,7 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/SymbolVendor.h"
@@ -29,9 +32,12 @@
#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
#if defined(_MSC_VER)
+#include "lldb/Host/windows/windows.h"
#include <objbase.h>
#endif
+#include <algorithm>
+
extern const char *TestMainArgv0;
using namespace lldb_private;
@@ -42,13 +48,17 @@ public:
void
SetUp() override
{
+// Initialize and TearDown the plugin every time, so we get a brand new
+// AST every time so that modifications to the AST from each test don't
+// leak into the next test.
#if defined(_MSC_VER)
::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
#endif
- HostInfoBase::Initialize();
+ HostInfo::Initialize();
ObjectFilePECOFF::Initialize();
SymbolFileDWARF::Initialize();
+ ClangASTContext::Initialize();
SymbolFilePDB::Initialize();
llvm::StringRef exe_folder = llvm::sys::path::parent_path(TestMainArgv0);
@@ -57,24 +67,30 @@ public:
m_pdb_test_exe = inputs_folder;
m_dwarf_test_exe = inputs_folder;
+ m_types_test_exe = inputs_folder;
llvm::sys::path::append(m_pdb_test_exe, "test-pdb.exe");
llvm::sys::path::append(m_dwarf_test_exe, "test-dwarf.exe");
+ llvm::sys::path::append(m_types_test_exe, "test-pdb-types.exe");
}
void
TearDown() override
{
-#if defined(_MSC_VER)
- ::CoUninitialize();
-#endif
SymbolFilePDB::Terminate();
+ ClangASTContext::Initialize();
SymbolFileDWARF::Terminate();
ObjectFilePECOFF::Terminate();
+ HostInfo::Terminate();
+
+#if defined(_MSC_VER)
+ ::CoUninitialize();
+#endif
}
protected:
llvm::SmallString<128> m_pdb_test_exe;
llvm::SmallString<128> m_dwarf_test_exe;
+ llvm::SmallString<128> m_types_test_exe;
bool
FileSpecMatchesAsBaseOrFull(const FileSpec &left, const FileSpec &right) const
@@ -116,6 +132,35 @@ protected:
}
return false;
}
+
+ int
+ GetGlobalConstantInteger(const llvm::IPDBSession &session, llvm::StringRef var) const
+ {
+ auto global = session.getGlobalScope();
+ auto results = global->findChildren(llvm::PDB_SymType::Data, var, llvm::PDB_NameSearchFlags::NS_Default);
+ uint32_t count = results->getChildCount();
+ if (count == 0)
+ return -1;
+
+ auto item = results->getChildAtIndex(0);
+ auto symbol = llvm::dyn_cast<llvm::PDBSymbolData>(item.get());
+ if (!symbol)
+ return -1;
+ llvm::Variant value = symbol->getValue();
+ switch (value.Type)
+ {
+ case llvm::PDB_VariantType::Int16:
+ return value.Value.Int16;
+ case llvm::PDB_VariantType::Int32:
+ return value.Value.Int32;
+ case llvm::PDB_VariantType::UInt16:
+ return value.Value.UInt16;
+ case llvm::PDB_VariantType::UInt32:
+ return value.Value.UInt32;
+ default:
+ return 0;
+ }
+ }
};
#if defined(HAVE_DIA_SDK)
@@ -342,3 +387,196 @@ TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLineTablesMatchSpecific))
VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045);
VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090);
}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestSimpleClassTypes))
+{
+ FileSpec fspec(m_types_test_exe.c_str(), false);
+ ArchSpec aspec("i686-pc-windows");
+ lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+ SymbolVendor *plugin = module->GetSymbolVendor();
+ SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+ const llvm::IPDBSession &session = symfile->GetPDBSession();
+ SymbolContext sc;
+ llvm::DenseSet<SymbolFile *> searched_files;
+ TypeMap results;
+ EXPECT_EQ(1, symfile->FindTypes(sc, ConstString("Class"), nullptr, false, 0, searched_files, results));
+ EXPECT_EQ(1, results.GetSize());
+ lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
+ EXPECT_EQ(ConstString("Class"), udt_type->GetName());
+ CompilerType compiler_type = udt_type->GetForwardCompilerType();
+ EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
+ EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_Class"), udt_type->GetByteSize());
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestNestedClassTypes))
+{
+ FileSpec fspec(m_types_test_exe.c_str(), false);
+ ArchSpec aspec("i686-pc-windows");
+ lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+ SymbolVendor *plugin = module->GetSymbolVendor();
+ SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+ const llvm::IPDBSession &session = symfile->GetPDBSession();
+ SymbolContext sc;
+ llvm::DenseSet<SymbolFile *> searched_files;
+ TypeMap results;
+ EXPECT_EQ(1, symfile->FindTypes(sc, ConstString("Class::NestedClass"), nullptr, false, 0, searched_files, results));
+ EXPECT_EQ(1, results.GetSize());
+ lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
+ EXPECT_EQ(ConstString("Class::NestedClass"), udt_type->GetName());
+ CompilerType compiler_type = udt_type->GetForwardCompilerType();
+ EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
+ EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NestedClass"), udt_type->GetByteSize());
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestClassInNamespace))
+{
+ FileSpec fspec(m_types_test_exe.c_str(), false);
+ ArchSpec aspec("i686-pc-windows");
+ lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+ SymbolVendor *plugin = module->GetSymbolVendor();
+ SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+ const llvm::IPDBSession &session = symfile->GetPDBSession();
+ SymbolContext sc;
+ llvm::DenseSet<SymbolFile *> searched_files;
+ TypeMap results;
+ EXPECT_EQ(1, symfile->FindTypes(sc, ConstString("NS::NSClass"), nullptr, false, 0, searched_files, results));
+ EXPECT_EQ(1, results.GetSize());
+ lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
+ EXPECT_EQ(ConstString("NS::NSClass"), udt_type->GetName());
+ CompilerType compiler_type = udt_type->GetForwardCompilerType();
+ EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
+ EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NSClass"), udt_type->GetByteSize());
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestEnumTypes))
+{
+ FileSpec fspec(m_types_test_exe.c_str(), false);
+ ArchSpec aspec("i686-pc-windows");
+ lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+ SymbolVendor *plugin = module->GetSymbolVendor();
+ SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+ const llvm::IPDBSession &session = symfile->GetPDBSession();
+ SymbolContext sc;
+ llvm::DenseSet<SymbolFile *> searched_files;
+ const char *EnumsToCheck[] = {"Enum", "ShortEnum"};
+ for (auto Enum : EnumsToCheck)
+ {
+ TypeMap results;
+ EXPECT_EQ(1, symfile->FindTypes(sc, ConstString(Enum), nullptr, false, 0, searched_files, results));
+ EXPECT_EQ(1, results.GetSize());
+ lldb::TypeSP enum_type = results.GetTypeAtIndex(0);
+ EXPECT_EQ(ConstString(Enum), enum_type->GetName());
+ CompilerType compiler_type = enum_type->GetFullCompilerType();
+ EXPECT_TRUE(ClangASTContext::IsEnumType(compiler_type.GetOpaqueQualType()));
+ clang::EnumDecl *enum_decl = ClangASTContext::GetAsEnumDecl(compiler_type);
+ EXPECT_NE(nullptr, enum_decl);
+ EXPECT_EQ(2, std::distance(enum_decl->enumerator_begin(), enum_decl->enumerator_end()));
+
+ std::string sizeof_var = "sizeof_";
+ sizeof_var.append(Enum);
+ EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var.c_str()), enum_type->GetByteSize());
+ }
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestArrayTypes))
+{
+ // In order to get this test working, we need to support lookup by symbol name. Because array
+ // types themselves do not have names, only the symbols have names (i.e. the name of the array).
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestFunctionTypes))
+{
+ // In order to get this test working, we need to support lookup by symbol name. Because array
+ // types themselves do not have names, only the symbols have names (i.e. the name of the array).
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestTypedefs))
+{
+ FileSpec fspec(m_types_test_exe.c_str(), false);
+ ArchSpec aspec("i686-pc-windows");
+ lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+ SymbolVendor *plugin = module->GetSymbolVendor();
+ SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+ const llvm::IPDBSession &session = symfile->GetPDBSession();
+ SymbolContext sc;
+ llvm::DenseSet<SymbolFile *> searched_files;
+ TypeMap results;
+
+ const char *TypedefsToCheck[] = {"ClassTypedef", "NSClassTypedef"};
+ for (auto Typedef : TypedefsToCheck)
+ {
+ TypeMap results;
+ EXPECT_EQ(1, symfile->FindTypes(sc, ConstString(Typedef), nullptr, false, 0, searched_files, results));
+ EXPECT_EQ(1, results.GetSize());
+ lldb::TypeSP typedef_type = results.GetTypeAtIndex(0);
+ EXPECT_EQ(ConstString(Typedef), typedef_type->GetName());
+ CompilerType compiler_type = typedef_type->GetFullCompilerType();
+ ClangASTContext *clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(compiler_type.GetTypeSystem());
+ EXPECT_TRUE(clang_type_system->IsTypedefType(compiler_type.GetOpaqueQualType()));
+
+ std::string sizeof_var = "sizeof_";
+ sizeof_var.append(Typedef);
+ EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var.c_str()), typedef_type->GetByteSize());
+ }
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestRegexNameMatch))
+{
+ FileSpec fspec(m_types_test_exe.c_str(), false);
+ ArchSpec aspec("i686-pc-windows");
+ lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+ SymbolVendor *plugin = module->GetSymbolVendor();
+ SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+ SymbolContext sc;
+ llvm::DenseSet<SymbolFile *> searched_files;
+ TypeMap results;
+ int num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, 0, searched_files, results);
+ EXPECT_GT(num_results, 1);
+ EXPECT_EQ(num_results, results.GetSize());
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestMaxMatches))
+{
+ FileSpec fspec(m_types_test_exe.c_str(), false);
+ ArchSpec aspec("i686-pc-windows");
+ lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+ SymbolVendor *plugin = module->GetSymbolVendor();
+ SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+ SymbolContext sc;
+ llvm::DenseSet<SymbolFile *> searched_files;
+ TypeMap results;
+ int num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, 0, searched_files, results);
+ // Try to limit ourselves from 1 to 10 results, otherwise we could be doing this thousands of times.
+ // The idea is just to make sure that for a variety of values, the number of limited results always
+ // comes out to the number we are expecting.
+ int iterations = std::min(num_results, 10);
+ for (int i = 1; i <= iterations; ++i)
+ {
+ int num_limited_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, i, searched_files, results);
+ EXPECT_EQ(i, num_limited_results);
+ EXPECT_EQ(num_limited_results, results.GetSize());
+ }
+}
+
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestNullName))
+{
+ FileSpec fspec(m_types_test_exe.c_str(), false);
+ ArchSpec aspec("i686-pc-windows");
+ lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+ SymbolVendor *plugin = module->GetSymbolVendor();
+ SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
+ SymbolContext sc;
+ llvm::DenseSet<SymbolFile *> searched_files;
+ TypeMap results;
+ int num_results = symfile->FindTypes(sc, ConstString(), nullptr, false, 0, searched_files, results);
+ EXPECT_EQ(0, num_results);
+ EXPECT_EQ(0, results.GetSize());
+}
OpenPOWER on IntegriCloud