aleksandr.urakov created this revision.
aleksandr.urakov added reviewers: asmith, zturner.
Herald added a subscriber: mgorny.

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.


https://reviews.llvm.org/D47708

Files:
  source/Plugins/SymbolFile/PDB/SymbolFilePDB.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.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,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;
+}
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,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;
+}
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: 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
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to