summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Smith <aaron.smith@microsoft.com>2018-06-05 17:19:21 +0000
committerAaron Smith <aaron.smith@microsoft.com>2018-06-05 17:19:21 +0000
commita642f8f343971430bf6d7dc354cfe9de85c418da (patch)
tree11b76b5ba990736779c77bf7089031e6e5bf7f3d
parenta9a6d54146f83d2c0354dcf61f5919bfedcc0a99 (diff)
downloadbcm5719-llvm-a642f8f343971430bf6d7dc354cfe9de85c418da.tar.gz
bcm5719-llvm-a642f8f343971430bf6d7dc354cfe9de85c418da.zip
PDB support of function-level linking and splitted functions
Summary: The patch adds support of splitted functions (when MSVC is used with PGO) and function-level linking feature. SymbolFilePDB::ParseCompileUnitLineTable function relies on fact that ranges of compiled source files in the binary are continuous and don't intersect each other. The function creates LineSequence for each file and inserts it into LineTable, and implementation of last one relies on continuity of the sequence. But it's not always true when function-level linking enabled, e.g. in added input test file test-pdb-function-level-linking.exe there is xstring's std__basic_string_char_std__char_traits_char__std__allocator_char_____max_size (.00454820) between test-pdb-function-level-linking.cpp's foo (.00454770) and main (.004548F0). To fix the problem this patch renews the sequence on each address gap. Reviewers: asmith, zturner Reviewed By: asmith Subscribers: mgorny, lldb-commits Differential Revision: https://reviews.llvm.org/D47708 llvm-svn: 334030
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp3
-rw-r--r--lldb/unittests/SymbolFile/PDB/CMakeLists.txt4
-rw-r--r--lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.cpp17
-rw-r--r--lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.exe0
-rw-r--r--lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.pdb0
-rw-r--r--lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.cpp27
-rw-r--r--lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.exe0
-rw-r--r--lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.pdb0
-rw-r--r--lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp56
9 files changed, 107 insertions, 0 deletions
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index f298749f10d..19a0e95d206 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -1571,6 +1571,9 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(
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)) {
diff --git a/lldb/unittests/SymbolFile/PDB/CMakeLists.txt b/lldb/unittests/SymbolFile/PDB/CMakeLists.txt
index dd7e2248aed..b9dada09b91 100644
--- a/lldb/unittests/SymbolFile/PDB/CMakeLists.txt
+++ b/lldb/unittests/SymbolFile/PDB/CMakeLists.txt
@@ -17,6 +17,10 @@ add_lldb_unittest(SymbolFilePDBTests
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)
diff --git a/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.cpp b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.cpp
new file mode 100644
index 00000000000..e1d5aabb357
--- /dev/null
+++ b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.cpp
@@ -0,0 +1,17 @@
+// Compile with "cl /c /ZI /sdl /EHsc /MTd /permissive-
+// test-pdb-function-level-linking.cpp"
+// Link with "link /debug:full test-pdb-function-level-linking.obj"
+
+#include <memory>
+#include <string>
+
+std::string foo()
+{
+ return "Hello!";
+}
+
+int main()
+{
+ auto x = foo();
+ return 0;
+}
diff --git a/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.exe b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.exe
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.exe
diff --git a/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.pdb b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.pdb
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-function-level-linking.pdb
diff --git a/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.cpp b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.cpp
new file mode 100644
index 00000000000..5155b8cdb6c
--- /dev/null
+++ b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.cpp
@@ -0,0 +1,27 @@
+// 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;
+}
diff --git a/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.exe b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.exe
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.exe
diff --git a/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.pdb b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.pdb
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/lldb/unittests/SymbolFile/PDB/Inputs/test-pdb-splitted-function.pdb
diff --git a/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp b/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
index 1e867b172ee..9b93ab0f0c7 100644
--- a/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
+++ b/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
@@ -56,6 +56,10 @@ public:
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 @@ public:
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 @@ TEST_F(SymbolFilePDBTests, TestLineTablesMatchSpecific) {
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");
OpenPOWER on IntegriCloud