summaryrefslogtreecommitdiffstats
path: root/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp')
-rw-r--r--lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp246
1 files changed, 242 insertions, 4 deletions
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