aleksandr.urakov updated this revision to Diff 150322.
aleksandr.urakov added a comment.
The implementation of lldb-test symbols -verify option.
https://reviews.llvm.org/D47708
Files:
source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
tools/lldb-test/lldb-test.cpp
unittests/SymbolFile/PDB/CMakeLists.txt
unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.cpp
unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.exe
unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.h
unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.ord
unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.pdb
unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.cpp
unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.exe
unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.pdb
unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
Index: unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
===================================================================
--- unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
+++ unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
@@ -56,6 +56,10 @@
SymbolFilePDB::Initialize();
m_pdb_test_exe = GetInputFilePath("test-pdb.exe");
+ m_function_level_linking_test_exe =
+ GetInputFilePath("test-pdb-function-level-linking.exe");
+ m_splitted_function_test_exe =
+ GetInputFilePath("test-pdb-splitted-function.exe");
m_types_test_exe = GetInputFilePath("test-pdb-types.exe");
}
@@ -73,6 +77,8 @@
protected:
std::string m_pdb_test_exe;
+ std::string m_function_level_linking_test_exe;
+ std::string m_splitted_function_test_exe;
std::string m_types_test_exe;
bool FileSpecMatchesAsBaseOrFull(const FileSpec &left,
@@ -354,6 +360,56 @@
VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090);
}
+void TestLineTableConsistency(llvm::StringRef exe_path, llvm::StringRef source_name)
+{
+ // All line entries of compile unit's line table must be consistent
+ // even if compiled sources are not continuous in the binary file.
+ FileSpec fspec(exe_path, false);
+ ArchSpec aspec("i686-pc-windows");
+ lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+ SymbolVendor *plugin = module->GetSymbolVendor();
+ SymbolFile *symfile = plugin->GetSymbolFile();
+ FileSpec source_file(source_name, false);
+ uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry;
+ SymbolContextList sc_list;
+ uint32_t count =
+ symfile->ResolveSymbolContext(source_file, 0, true, scope, sc_list);
+ EXPECT_EQ(1u, count);
+
+ SymbolContext sc;
+ EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));
+
+ LineTable *lt = sc.comp_unit->GetLineTable();
+ EXPECT_NE(nullptr, lt);
+
+ count = lt->GetSize();
+ EXPECT_LT(0u, count);
+
+ LineEntry le;
+ EXPECT_TRUE(lt->GetLineEntryAtIndex(0, le));
+ for (int i = 1; i < count; i++)
+ {
+ lldb::addr_t curr_end =
+ le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
+
+ EXPECT_TRUE(lt->GetLineEntryAtIndex(i, le));
+
+ EXPECT_LE(curr_end, le.range.GetBaseAddress().GetFileAddress());
+ }
+}
+
+TEST_F(SymbolFilePDBTests, TestFunctionLevelLinking) {
+ TestLineTableConsistency(
+ m_function_level_linking_test_exe,
+ "test-pdb-function-level-linking.cpp");
+}
+
+TEST_F(SymbolFilePDBTests, TestSplittedFunction) {
+ TestLineTableConsistency(
+ m_splitted_function_test_exe,
+ "test-pdb-splitted-function.cpp");
+}
+
TEST_F(SymbolFilePDBTests, TestSimpleClassTypes) {
FileSpec fspec(m_types_test_exe.c_str(), false);
ArchSpec aspec("i686-pc-windows");
Index: unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.cpp
===================================================================
--- /dev/null
+++ unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.cpp
@@ -0,0 +1,24 @@
+// Compile with "cl /c /Zi /GL /O2 /EHsc /MTd test-pdb-splitted-function.cpp"
+// Link with "link /debug:full /LTCG /GENPROFILE
+// test-pdb-splitted-function.obj"
+// Run several times
+// Link with "link /debug:full /LTCG /USEPROFILE
+// test-pdb-splitted-function.obj"
+
+#include <cmath>
+#include <iostream>
+
+int main() {
+ auto b = false;
+ for (auto i = 1; i <= 1024; i++) {
+ if (b) {
+ std::cout << "Unreachable code" << std::endl;
+ auto x = std::sin(i);
+ return x;
+ }
+
+ b = (i % 2 + (i - 1) % 2) != 1;
+ }
+
+ return 0;
+}
Index: unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.ord
===================================================================
--- /dev/null
+++ unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.ord
@@ -0,0 +1,4 @@
+?foo@@YAHXZ
+?bar@@YAHXZ
+main
+?baz@@YAHXZ
Index: unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.h
===================================================================
--- /dev/null
+++ unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.h
@@ -0,0 +1,12 @@
+#ifndef TEST_PDB_FUNCTION_LEVEL_LINKING_H
+#define TEST_PDB_FUNCTION_LEVEL_LINKING_H
+
+int bar() {
+ return 0;
+}
+
+int baz() {
+ return 0;
+}
+
+#endif
Index: unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.cpp
===================================================================
--- /dev/null
+++ unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.cpp
@@ -0,0 +1,14 @@
+// Compile with "cl /c /Zi /Gy test-pdb-function-level-linking.cpp"
+// Link with "link /debug:full /nodefaultlib /entry:main
+// /order:@test-pdb-function-level-linking.ord
+// test-pdb-function-level-linking.obj"
+
+#include "test-pdb-function-level-linking.h"
+
+int foo() {
+ return 0;
+}
+
+int main() {
+ return foo() + bar() + baz();
+}
Index: unittests/SymbolFile/PDB/CMakeLists.txt
===================================================================
--- unittests/SymbolFile/PDB/CMakeLists.txt
+++ unittests/SymbolFile/PDB/CMakeLists.txt
@@ -17,6 +17,10 @@
set(test_inputs
test-pdb.exe
test-pdb.pdb
+ test-pdb-function-level-linking.exe
+ test-pdb-function-level-linking.pdb
+ test-pdb-splitted-function.exe
+ test-pdb-splitted-function.pdb
test-pdb-types.exe
test-pdb-types.pdb)
Index: tools/lldb-test/lldb-test.cpp
===================================================================
--- tools/lldb-test/lldb-test.cpp
+++ tools/lldb-test/lldb-test.cpp
@@ -21,6 +21,8 @@
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangASTImporter.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/VariableList.h"
@@ -143,13 +145,17 @@
return Result;
}
+static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
+ cl::sub(SymbolsSubcommand));
+
static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
static Error findFunctions(lldb_private::Module &Module);
static Error findNamespaces(lldb_private::Module &Module);
static Error findTypes(lldb_private::Module &Module);
static Error findVariables(lldb_private::Module &Module);
static Error dumpModule(lldb_private::Module &Module);
+static Error verify(lldb_private::Module &Module);
static int dumpSymbols(Debugger &Dbg);
}
@@ -412,7 +418,75 @@
return Error::success();
}
+Error opts::symbols::verify(lldb_private::Module &Module) {
+ SymbolVendor *plugin = Module.GetSymbolVendor();
+ if (!plugin)
+ return make_error<StringError>("Can't get a symbol vendor.",
+ inconvertibleErrorCode());
+
+ SymbolFile *symfile = plugin->GetSymbolFile();
+ if (!symfile)
+ return make_error<StringError>("Can't get a symbol file.",
+ inconvertibleErrorCode());
+
+ uint32_t comp_units_count = symfile->GetNumCompileUnits();
+
+ outs() << "Found " << comp_units_count << " compile units.\n";
+
+ for (uint32_t i = 0; i < comp_units_count; i++) {
+ lldb::CompUnitSP comp_unit = symfile->ParseCompileUnitAtIndex(i);
+ if (!comp_unit)
+ return make_error<StringError>("Can't get a compile unit.",
+ inconvertibleErrorCode());
+
+ outs() << "Processing '" << comp_unit->GetFilename().AsCString() <<
+ "' compile unit.\n";
+
+ LineTable *lt = comp_unit->GetLineTable();
+ if (!lt)
+ return make_error<StringError>(
+ "Can't get a line table of a compile unit.",
+ inconvertibleErrorCode());
+
+ uint32_t count = lt->GetSize();
+
+ outs() << "The line table contains " << count << " entries.\n";
+
+ if (count == 0)
+ continue;
+
+ LineEntry le;
+ if (!lt->GetLineEntryAtIndex(0, le))
+ return make_error<StringError>(
+ "Can't get a line entry of a compile unit",
+ inconvertibleErrorCode());
+
+ for (uint32_t i = 1; i < count; i++) {
+ lldb::addr_t curr_end =
+ le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize();
+
+ if (!lt->GetLineEntryAtIndex(i, le))
+ return make_error<StringError>(
+ "Can't get a line entry of a compile unit",
+ inconvertibleErrorCode());
+
+ if (curr_end > le.range.GetBaseAddress().GetFileAddress())
+ return make_error<StringError>(
+ "Line table of a compile unit is inconsistent",
+ inconvertibleErrorCode());
+ }
+ }
+
+ outs() << "The symbol information is verified.\n";
+
+ return Error::success();
+}
+
int opts::symbols::dumpSymbols(Debugger &Dbg) {
+ if (Verify && Find != FindType::None) {
+ WithColor::error() << "Cannot both search and verify symbol information.\n";
+ return 1;
+ }
if (Find != FindType::None && Regex && !Context.empty()) {
WithColor::error()
<< "Cannot search using both regular expressions and context.\n";
@@ -435,23 +509,26 @@
}
Error (*Action)(lldb_private::Module &);
- switch (Find) {
- case FindType::Function:
- Action = findFunctions;
- break;
- case FindType::Namespace:
- Action = findNamespaces;
- break;
- case FindType::Type:
- Action = findTypes;
- break;
- case FindType::Variable:
- Action = findVariables;
- break;
- case FindType::None:
- Action = dumpModule;
- break;
- }
+ if (!Verify) {
+ switch (Find) {
+ case FindType::Function:
+ Action = findFunctions;
+ break;
+ case FindType::Namespace:
+ Action = findNamespaces;
+ break;
+ case FindType::Type:
+ Action = findTypes;
+ break;
+ case FindType::Variable:
+ Action = findVariables;
+ break;
+ case FindType::None:
+ Action = dumpModule;
+ break;
+ }
+ } else
+ Action = verify;
int HadErrors = 0;
for (const auto &File : InputFilenames) {
Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
===================================================================
--- source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -1571,6 +1571,9 @@
line_table->AppendLineEntryToSequence(
sequence.get(), prev_addr + prev_length, prev_line, 0,
prev_source_idx, false, false, false, false, true);
+
+ line_table->InsertSequence(sequence.release());
+ sequence.reset(line_table->CreateLineSequenceContainer());
}
if (ShouldAddLine(match_line, lno, length)) {
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits