<div dir="ltr"><div class="gmail_quote"><div>FYI, this produces warnings for me:</div><div><br></div><div><div>[4255/4427] Building CXX object tools/lldb/unittests/SymbolFile/PDB/CMakeFiles/SymbolFilePDBTests.dir/SymbolFilePDBTests.cpp.o</div><div>../tools/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp:111:27: warning: comparison of integers of different signs: 'int' and 'uint32_t' (aka 'unsigned int') [-Wsign-compare]</div><div>        for (int i = 0; i < sc_list.GetSize(); ++i)</div><div>                        ~ ^ ~~~~~~~~~~~~~~~~~</div><div>In file included from ../tools/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp:10:</div><div>../utils/unittest/googletest/include/gtest/gtest.h:1320:16: warning: comparison of integers of different signs: 'const int' and 'const unsigned int' [-Wsign-compare]</div><div>  if (expected == actual) {</div><div>      ~~~~~~~~ ^  ~~~~~~</div><div>../utils/unittest/googletest/include/gtest/gtest.h:1356:12: note: in instantiation of function template specialization 'testing::internal::CmpHelperEQ<int, unsigned int>' requested here</div><div>    return CmpHelperEQ(expected_expression, actual_expression, expected,</div><div>           ^</div><div>../tools/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp:176:5: note: in instantiation of function template specialization 'testing::internal::EqHelper<false>::Compare<int, unsigned int>' requested h</div><div>ere</div><div>    EXPECT_EQ(1, result_count);</div><div>    ^</div><div>../utils/unittest/googletest/include/gtest/gtest.h:1852:67: note: expanded from macro 'EXPECT_EQ'</div><div>                      EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \</div><div>                                                                  ^</div><div>../utils/unittest/googletest/include/gtest/gtest.h:1455:28: warning: comparison of integers of different signs: 'const int' and 'const unsigned int' [-Wsign-compare]</div></div><div><br></div><div dir="ltr">On Wed, Mar 2, 2016 at 11:10 PM Zachary Turner via lldb-commits <<a href="mailto:lldb-commits@lists.llvm.org">lldb-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: zturner<br>
Date: Wed Mar  2 16:05:52 2016<br>
New Revision: 262528<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=262528&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=262528&view=rev</a><br>
Log:<br>
Add support for reading line tables from PDB files.<br>
<br>
PDB is Microsoft's debug information format, and although we<br>
cannot yet generate it, we still must be able to consume it.<br>
Reason for this is that debug information for system libraries<br>
(e.g. kernel32, C Runtime Library, etc) only have debug info<br>
in PDB format, so in order to be able to support debugging<br>
of system code, we must support it.<br>
<br>
Currently this code should compile on every platform, but on<br>
non-Windows platforms the PDB plugin will return 0 capabilities,<br>
meaning that for now PDB is only supported on Windows.  This<br>
may change in the future, but the API is designed in such a way<br>
that this will require few (if any) changes on the LLDB side.<br>
In the future we can just flip a switch and everything will<br>
work.<br>
<br>
This patch only adds support for line tables.  It does not return<br>
information about functions, types, global variables, or anything<br>
else.  This functionality will be added in a followup patch.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D17363" rel="noreferrer" target="_blank">http://reviews.llvm.org/D17363</a><br>
Reviewed by: Greg Clayton<br>
<br>
Added:<br>
    lldb/trunk/source/Plugins/SymbolFile/PDB/<br>
    lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt<br>
    lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp<br>
    lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h<br>
    lldb/trunk/unittests/SymbolFile/<br>
    lldb/trunk/unittests/SymbolFile/CMakeLists.txt<br>
    lldb/trunk/unittests/SymbolFile/PDB/<br>
    lldb/trunk/unittests/SymbolFile/PDB/CMakeLists.txt<br>
    lldb/trunk/unittests/SymbolFile/PDB/Inputs/<br>
    lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-dwarf.cpp<br>
    lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-dwarf.exe<br>
    lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-alt.cpp<br>
    lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-nested.h<br>
    lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.cpp<br>
    lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.exe<br>
    lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.h<br>
    lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.pdb<br>
    lldb/trunk/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp<br>
Modified:<br>
    lldb/trunk/cmake/LLDBDependencies.cmake<br>
    lldb/trunk/cmake/modules/AddLLDB.cmake<br>
    lldb/trunk/include/lldb/Host/FileSpec.h<br>
    lldb/trunk/include/lldb/Host/windows/HostInfoWindows.h<br>
    lldb/trunk/source/API/SystemInitializerFull.cpp<br>
    lldb/trunk/source/Host/common/FileSpec.cpp<br>
    lldb/trunk/source/Host/windows/HostInfoWindows.cpp<br>
    lldb/trunk/source/Initialization/SystemInitializerCommon.cpp<br>
    lldb/trunk/source/Plugins/SymbolFile/CMakeLists.txt<br>
    lldb/trunk/unittests/CMakeLists.txt<br>
<br>
Modified: lldb/trunk/cmake/LLDBDependencies.cmake<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/cmake/LLDBDependencies.cmake?rev=262528&r1=262527&r2=262528&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/cmake/LLDBDependencies.cmake?rev=262528&r1=262527&r2=262528&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/cmake/LLDBDependencies.cmake (original)<br>
+++ lldb/trunk/cmake/LLDBDependencies.cmake Wed Mar  2 16:05:52 2016<br>
@@ -15,6 +15,7 @@ set( LLDB_USED_LIBS<br>
   # Plugins<br>
   lldbPluginDisassemblerLLVM<br>
   lldbPluginSymbolFileDWARF<br>
+  lldbPluginSymbolFilePDB<br>
   lldbPluginSymbolFileSymtab<br>
   lldbPluginDynamicLoaderStatic<br>
   lldbPluginDynamicLoaderPosixDYLD<br>
@@ -174,7 +175,7 @@ if (LLVM_BUILD_STATIC)<br>
   endif()<br>
 endif()<br>
<br>
-set( LLVM_LINK_COMPONENTS<br>
+set(LLVM_LINK_COMPONENTS<br>
   ${LLVM_TARGETS_TO_BUILD}<br>
   interpreter<br>
   asmparser<br>
<br>
Modified: lldb/trunk/cmake/modules/AddLLDB.cmake<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/cmake/modules/AddLLDB.cmake?rev=262528&r1=262527&r2=262528&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/cmake/modules/AddLLDB.cmake?rev=262528&r1=262527&r2=262528&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/cmake/modules/AddLLDB.cmake (original)<br>
+++ lldb/trunk/cmake/modules/AddLLDB.cmake Wed Mar  2 16:05:52 2016<br>
@@ -68,7 +68,7 @@ macro(add_lldb_library name)<br>
         target_link_libraries(${name} ${cmake_2_8_12_PUBLIC} ${CLANG_USED_LIBS})<br>
       endif()<br>
     endif()<br>
-    llvm_config(${name} ${LLVM_LINK_COMPONENTS})<br>
+    llvm_config(${name} ${LLVM_LINK_COMPONENTS} ${LLVM_PRIVATE_LINK_COMPONENTS})<br>
<br>
     if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "liblldb")<br>
       if (PARAM_SHARED)<br>
<br>
Modified: lldb/trunk/include/lldb/Host/FileSpec.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/FileSpec.h?rev=262528&r1=262527&r2=262528&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/FileSpec.h?rev=262528&r1=262527&r2=262528&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Host/FileSpec.h (original)<br>
+++ lldb/trunk/include/lldb/Host/FileSpec.h Wed Mar  2 16:05:52 2016<br>
@@ -117,6 +117,12 @@ public:<br>
     //------------------------------------------------------------------<br>
     ~FileSpec ();<br>
<br>
+    bool<br>
+    DirectoryEquals(const FileSpec &other) const;<br>
+<br>
+    bool<br>
+    FileEquals(const FileSpec &other) const;<br>
+<br>
     //------------------------------------------------------------------<br>
     /// Assignment operator.<br>
     ///<br>
<br>
Modified: lldb/trunk/include/lldb/Host/windows/HostInfoWindows.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/windows/HostInfoWindows.h?rev=262528&r1=262527&r2=262528&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/windows/HostInfoWindows.h?rev=262528&r1=262527&r2=262528&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Host/windows/HostInfoWindows.h (original)<br>
+++ lldb/trunk/include/lldb/Host/windows/HostInfoWindows.h Wed Mar  2 16:05:52 2016<br>
@@ -26,14 +26,26 @@ class HostInfoWindows : public HostInfoB<br>
     ~HostInfoWindows();<br>
<br>
   public:<br>
-    static size_t GetPageSize();<br>
+      static void<br>
+      Initialize();<br>
+      static void<br>
+      Terminate();<br>
<br>
-    static bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update);<br>
-    static bool GetOSBuildString(std::string &s);<br>
-    static bool GetOSKernelDescription(std::string &s);<br>
-    static bool GetHostname(std::string &s);<br>
-    static FileSpec GetProgramFileSpec();<br>
-    static FileSpec GetDefaultShell();<br>
+      static size_t<br>
+      GetPageSize();<br>
+<br>
+      static bool<br>
+      GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update);<br>
+      static bool<br>
+      GetOSBuildString(std::string &s);<br>
+      static bool<br>
+      GetOSKernelDescription(std::string &s);<br>
+      static bool<br>
+      GetHostname(std::string &s);<br>
+      static FileSpec<br>
+      GetProgramFileSpec();<br>
+      static FileSpec<br>
+      GetDefaultShell();<br>
<br>
   protected:<br>
     static bool ComputePythonDirectory(FileSpec &file_spec);<br>
<br>
Modified: lldb/trunk/source/API/SystemInitializerFull.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SystemInitializerFull.cpp?rev=262528&r1=262527&r2=262528&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SystemInitializerFull.cpp?rev=262528&r1=262527&r2=262528&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/API/SystemInitializerFull.cpp (original)<br>
+++ lldb/trunk/source/API/SystemInitializerFull.cpp Wed Mar  2 16:05:52 2016<br>
@@ -28,18 +28,18 @@<br>
 #include "lldb/Symbol/GoASTContext.h"<br>
 #include "lldb/Symbol/JavaASTContext.h"<br>
<br>
-#include "Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h"<br>
 #include "Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h"<br>
 #include "Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h"<br>
+#include "Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h"<br>
 #include "Plugins/ABI/SysV-arm/ABISysV_arm.h"<br>
 #include "Plugins/ABI/SysV-arm64/ABISysV_arm64.h"<br>
 #include "Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h"<br>
 #include "Plugins/ABI/SysV-i386/ABISysV_i386.h"<br>
-#include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h"<br>
-#include "Plugins/ABI/SysV-ppc/ABISysV_ppc.h"<br>
-#include "Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h"<br>
 #include "Plugins/ABI/SysV-mips/ABISysV_mips.h"<br>
 #include "Plugins/ABI/SysV-mips64/ABISysV_mips64.h"<br>
+#include "Plugins/ABI/SysV-ppc/ABISysV_ppc.h"<br>
+#include "Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h"<br>
+#include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h"<br>
 #include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h"<br>
 #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"<br>
 #include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h"<br>
@@ -51,10 +51,10 @@<br>
 #include "Plugins/Language/ObjC/ObjCLanguage.h"<br>
 #include "Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h"<br>
 #include "Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h"<br>
-#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h"<br>
-#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h"<br>
 #include "Plugins/LanguageRuntime/Go/GoLanguageRuntime.h"<br>
 #include "Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h"<br>
+#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h"<br>
+#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h"<br>
 #include "Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h"<br>
 #include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h"<br>
 #include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h"<br>
@@ -63,11 +63,12 @@<br>
 #include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h"<br>
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"<br>
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h"<br>
+#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"<br>
 #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"<br>
 #include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h"<br>
 #include "Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h"<br>
-#include "Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h"<br>
 #include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"<br>
+#include "Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h"<br>
<br>
 #if defined(__APPLE__)<br>
 #include "Plugins/Process/mach-core/ProcessMachCore.h"<br>
@@ -301,6 +302,7 @@ SystemInitializerFull::Initialize()<br>
<br>
     SymbolVendorELF::Initialize();<br>
     SymbolFileDWARF::Initialize();<br>
+    SymbolFilePDB::Initialize();<br>
     SymbolFileSymtab::Initialize();<br>
     UnwindAssemblyInstEmulation::Initialize();<br>
     UnwindAssembly_x86::Initialize();<br>
@@ -422,6 +424,7 @@ SystemInitializerFull::Terminate()<br>
     AddressSanitizerRuntime::Terminate();<br>
     SymbolVendorELF::Terminate();<br>
     SymbolFileDWARF::Terminate();<br>
+    SymbolFilePDB::Terminate();<br>
     SymbolFileSymtab::Terminate();<br>
     UnwindAssembly_x86::Terminate();<br>
     UnwindAssemblyInstEmulation::Terminate();<br>
<br>
Modified: lldb/trunk/source/Host/common/FileSpec.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/FileSpec.cpp?rev=262528&r1=262527&r2=262528&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/FileSpec.cpp?rev=262528&r1=262527&r2=262528&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Host/common/FileSpec.cpp (original)<br>
+++ lldb/trunk/source/Host/common/FileSpec.cpp Wed Mar  2 16:05:52 2016<br>
@@ -390,19 +390,29 @@ FileSpec::operator!() const<br>
     return !m_directory && !m_filename;<br>
 }<br>
<br>
+bool<br>
+FileSpec::DirectoryEquals(const FileSpec &rhs) const<br>
+{<br>
+    const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive();<br>
+    return ConstString::Equals(m_directory, rhs.m_directory, case_sensitive);<br>
+}<br>
+<br>
+bool<br>
+FileSpec::FileEquals(const FileSpec &rhs) const<br>
+{<br>
+    const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive();<br>
+    return ConstString::Equals(m_filename, rhs.m_filename, case_sensitive);<br>
+}<br>
+<br>
 //------------------------------------------------------------------<br>
 // Equal to operator<br>
 //------------------------------------------------------------------<br>
 bool<br>
 FileSpec::operator== (const FileSpec& rhs) const<br>
 {<br>
-    // case sensitivity of equality test<br>
-    const bool case_sensitive = IsCaseSensitive() || rhs.IsCaseSensitive();<br>
-<br>
-    if (!ConstString::Equals(m_filename, rhs.m_filename, case_sensitive))<br>
+    if (!FileEquals(rhs))<br>
         return false;<br>
-<br>
-    if (ConstString::Equals(m_directory, rhs.m_directory, case_sensitive))<br>
+    if (DirectoryEquals(rhs))<br>
         return true;<br>
<br>
     // TODO: determine if we want to keep this code in here.<br>
@@ -451,7 +461,7 @@ FileSpec::operator== (const FileSpec& rh<br>
     // If we reach this point in the code we were able to resolve both paths<br>
     // and since we only resolve the paths if the basenames are equal, then<br>
     // we can just check if both directories are equal...<br>
-    return ConstString::Equals(m_directory, rhs.m_directory, case_sensitive);<br>
+    return DirectoryEquals(rhs);<br>
 }<br>
<br>
 //------------------------------------------------------------------<br>
<br>
Modified: lldb/trunk/source/Host/windows/HostInfoWindows.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/HostInfoWindows.cpp?rev=262528&r1=262527&r2=262528&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/windows/HostInfoWindows.cpp?rev=262528&r1=262527&r2=262528&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Host/windows/HostInfoWindows.cpp (original)<br>
+++ lldb/trunk/source/Host/windows/HostInfoWindows.cpp Wed Mar  2 16:05:52 2016<br>
@@ -9,6 +9,8 @@<br>
<br>
 #include "lldb/Host/windows/windows.h"<br>
<br>
+#include <objbase.h><br>
+<br>
 #include <mutex> // std::once<br>
<br>
 #include "lldb/Host/windows/HostInfoWindows.h"<br>
@@ -21,6 +23,20 @@ using namespace lldb_private;<br>
<br>
 FileSpec HostInfoWindows::m_program_filespec;<br>
<br>
+void<br>
+HostInfoWindows::Initialize()<br>
+{<br>
+    ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);<br>
+    HostInfoBase::Initialize();<br>
+}<br>
+<br>
+void<br>
+HostInfoWindows::Terminate()<br>
+{<br>
+    HostInfoBase::Terminate();<br>
+    ::CoUninitialize();<br>
+}<br>
+<br>
 size_t<br>
 HostInfoWindows::GetPageSize()<br>
 {<br>
<br>
Modified: lldb/trunk/source/Initialization/SystemInitializerCommon.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Initialization/SystemInitializerCommon.cpp?rev=262528&r1=262527&r2=262528&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Initialization/SystemInitializerCommon.cpp?rev=262528&r1=262527&r2=262528&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Initialization/SystemInitializerCommon.cpp (original)<br>
+++ lldb/trunk/source/Initialization/SystemInitializerCommon.cpp Wed Mar  2 16:05:52 2016<br>
@@ -49,8 +49,8 @@<br>
 #endif<br>
<br>
 #if defined(_MSC_VER)<br>
-#include "lldb/Host/windows/windows.h"<br>
 #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h"<br>
+#include "lldb/Host/windows/windows.h"<br>
 #endif<br>
<br>
 #include "llvm/Support/TargetSelect.h"<br>
<br>
Modified: lldb/trunk/source/Plugins/SymbolFile/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/CMakeLists.txt?rev=262528&r1=262527&r2=262528&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/CMakeLists.txt?rev=262528&r1=262527&r2=262528&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/SymbolFile/CMakeLists.txt (original)<br>
+++ lldb/trunk/source/Plugins/SymbolFile/CMakeLists.txt Wed Mar  2 16:05:52 2016<br>
@@ -1,2 +1,3 @@<br>
 add_subdirectory(DWARF)<br>
 add_subdirectory(Symtab)<br>
+add_subdirectory(PDB)<br>
<br>
Added: lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt?rev=262528&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt (added)<br>
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt Wed Mar  2 16:05:52 2016<br>
@@ -0,0 +1,6 @@<br>
+set(LLVM_PRIVATE_LINK_COMPONENTS<br>
+    DebugInfoPDB)<br>
+<br>
+add_lldb_library(lldbPluginSymbolFilePDB<br>
+  SymbolFilePDB.cpp<br>
+  )<br>
<br>
Added: lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp?rev=262528&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp (added)<br>
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp Wed Mar  2 16:05:52 2016<br>
@@ -0,0 +1,549 @@<br>
+//===-- SymbolFilePDB.cpp ---------------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "SymbolFilePDB.h"<br>
+<br>
+#include "lldb/Core/Module.h"<br>
+#include "lldb/Core/PluginManager.h"<br>
+#include "lldb/Symbol/CompileUnit.h"<br>
+#include "lldb/Symbol/LineTable.h"<br>
+#include "lldb/Symbol/ObjectFile.h"<br>
+#include "lldb/Symbol/SymbolContext.h"<br>
+<br>
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"<br>
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"<br>
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"<br>
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"<br>
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"<br>
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"<br>
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"<br>
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"<br>
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"<br>
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"<br>
+<br>
+using namespace lldb_private;<br>
+<br>
+namespace<br>
+{<br>
+    lldb::LanguageType TranslateLanguage(llvm::PDB_Lang lang)<br>
+    {<br>
+        switch (lang)<br>
+        {<br>
+        case llvm::PDB_Lang::Cpp:<br>
+            return lldb::LanguageType::eLanguageTypeC_plus_plus;<br>
+        case llvm::PDB_Lang::C:<br>
+            return lldb::LanguageType::eLanguageTypeC;<br>
+        default:<br>
+            return lldb::LanguageType::eLanguageTypeUnknown;<br>
+        }<br>
+    }<br>
+}<br>
+<br>
+void<br>
+SymbolFilePDB::Initialize()<br>
+{<br>
+    PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,<br>
+                                  DebuggerInitialize);<br>
+}<br>
+<br>
+void<br>
+SymbolFilePDB::Terminate()<br>
+{<br>
+    PluginManager::UnregisterPlugin(CreateInstance);<br>
+}<br>
+<br>
+void<br>
+SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger)<br>
+{<br>
+}<br>
+<br>
+lldb_private::ConstString<br>
+SymbolFilePDB::GetPluginNameStatic()<br>
+{<br>
+    static ConstString g_name("pdb");<br>
+    return g_name;<br>
+}<br>
+<br>
+const char *<br>
+SymbolFilePDB::GetPluginDescriptionStatic()<br>
+{<br>
+    return "Microsoft PDB debug symbol file reader.";<br>
+}<br>
+<br>
+lldb_private::SymbolFile *<br>
+SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file)<br>
+{<br>
+    return new SymbolFilePDB(obj_file);<br>
+}<br>
+<br>
+SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file)<br>
+    : SymbolFile(object_file), m_cached_compile_unit_count(0)<br>
+{<br>
+}<br>
+<br>
+SymbolFilePDB::~SymbolFilePDB()<br>
+{<br>
+}<br>
+<br>
+uint32_t<br>
+SymbolFilePDB::CalculateAbilities()<br>
+{<br>
+    if (!m_session_up)<br>
+    {<br>
+        // Lazily load and match the PDB file, but only do this once.<br>
+        std::string exePath = m_obj_file->GetFileSpec().GetPath();<br>
+        auto error = llvm::loadDataForEXE(llvm::PDB_ReaderType::DIA, llvm::StringRef(exePath), m_session_up);<br>
+        if (error != llvm::PDB_ErrorCode::Success)<br>
+            return 0;<br>
+    }<br>
+    return CompileUnits | LineTables;<br>
+}<br>
+<br>
+void<br>
+SymbolFilePDB::InitializeObject()<br>
+{<br>
+    lldb::addr_t obj_load_address = m_obj_file->GetFileOffset();<br>
+    m_session_up->setLoadAddress(obj_load_address);<br>
+}<br>
+<br>
+uint32_t<br>
+SymbolFilePDB::GetNumCompileUnits()<br>
+{<br>
+    if (m_cached_compile_unit_count == 0)<br>
+    {<br>
+        auto global = m_session_up->getGlobalScope();<br>
+        auto compilands = global->findAllChildren<llvm::PDBSymbolCompiland>();<br>
+        m_cached_compile_unit_count = compilands->getChildCount();<br>
+<br>
+        // The linker can inject an additional "dummy" compilation unit into the PDB.<br>
+        // Ignore this special compile unit for our purposes, if it is there.  It is<br>
+        // always the last one.<br>
+        auto last_cu = compilands->getChildAtIndex(m_cached_compile_unit_count - 1);<br>
+        std::string name = last_cu->getName();<br>
+        if (name == "* Linker *")<br>
+            --m_cached_compile_unit_count;<br>
+    }<br>
+    return m_cached_compile_unit_count;<br>
+}<br>
+<br>
+lldb::CompUnitSP<br>
+SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index)<br>
+{<br>
+    auto global = m_session_up->getGlobalScope();<br>
+    auto compilands = global->findAllChildren<llvm::PDBSymbolCompiland>();<br>
+    auto cu = compilands->getChildAtIndex(index);<br>
+<br>
+    uint32_t id = cu->getSymIndexId();<br>
+<br>
+    return ParseCompileUnitForSymIndex(id);<br>
+}<br>
+<br>
+lldb::LanguageType<br>
+SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc)<br>
+{<br>
+    // What fields should I expect to be filled out on the SymbolContext?  Is it<br>
+    // safe to assume that `sc.comp_unit` is valid?<br>
+    if (!sc.comp_unit)<br>
+        return lldb::eLanguageTypeUnknown;<br>
+<br>
+    auto cu = m_session_up->getConcreteSymbolById<llvm::PDBSymbolCompiland>(sc.comp_unit->GetID());<br>
+    if (!cu)<br>
+        return lldb::eLanguageTypeUnknown;<br>
+    auto details = cu->findOneChild<llvm::PDBSymbolCompilandDetails>();<br>
+    if (!details)<br>
+        return lldb::eLanguageTypeUnknown;<br>
+    return TranslateLanguage(details->getLanguage());<br>
+}<br>
+<br>
+size_t<br>
+SymbolFilePDB::ParseCompileUnitFunctions(const lldb_private::SymbolContext &sc)<br>
+{<br>
+    // TODO: Implement this<br>
+    return size_t();<br>
+}<br>
+<br>
+bool<br>
+SymbolFilePDB::ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc)<br>
+{<br>
+    return ParseCompileUnitLineTable(sc, 0);<br>
+}<br>
+<br>
+bool<br>
+SymbolFilePDB::ParseCompileUnitDebugMacros(const lldb_private::SymbolContext &sc)<br>
+{<br>
+    // PDB doesn't contain information about macros<br>
+    return false;<br>
+}<br>
+<br>
+bool<br>
+SymbolFilePDB::ParseCompileUnitSupportFiles(const lldb_private::SymbolContext &sc,<br>
+                                            lldb_private::FileSpecList &support_files)<br>
+{<br>
+    if (!sc.comp_unit)<br>
+        return false;<br>
+<br>
+    // In theory this is unnecessary work for us, because all of this information is easily<br>
+    // (and quickly) accessible from DebugInfoPDB, so caching it a second time seems like a waste.<br>
+    // Unfortunately, there's no good way around this short of a moderate refactor, since SymbolVendor<br>
+    // depends on being able to cache this list.<br>
+    auto cu = m_session_up->getConcreteSymbolById<llvm::PDBSymbolCompiland>(sc.comp_unit->GetID());<br>
+    if (!cu)<br>
+        return false;<br>
+    auto files = m_session_up->getSourceFilesForCompiland(*cu);<br>
+    if (!files || files->getChildCount() == 0)<br>
+        return false;<br>
+<br>
+    while (auto file = files->getNext())<br>
+    {<br>
+        FileSpec spec(file->getFileName(), false);<br>
+        support_files.Append(spec);<br>
+    }<br>
+    return true;<br>
+}<br>
+<br>
+bool<br>
+SymbolFilePDB::ParseImportedModules(const lldb_private::SymbolContext &sc,<br>
+                                    std::vector<lldb_private::ConstString> &imported_modules)<br>
+{<br>
+    // PDB does not yet support module debug info<br>
+    return false;<br>
+}<br>
+<br>
+size_t<br>
+SymbolFilePDB::ParseFunctionBlocks(const lldb_private::SymbolContext &sc)<br>
+{<br>
+    // TODO: Implement this<br>
+    return size_t();<br>
+}<br>
+<br>
+size_t<br>
+SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc)<br>
+{<br>
+    // TODO: Implement this<br>
+    return size_t();<br>
+}<br>
+<br>
+size_t<br>
+SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc)<br>
+{<br>
+    // TODO: Implement this<br>
+    return size_t();<br>
+}<br>
+<br>
+lldb_private::Type *<br>
+SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid)<br>
+{<br>
+    return nullptr;<br>
+}<br>
+<br>
+bool<br>
+SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type)<br>
+{<br>
+    // TODO: Implement this<br>
+    return false;<br>
+}<br>
+<br>
+lldb_private::CompilerDecl<br>
+SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid)<br>
+{<br>
+    return lldb_private::CompilerDecl();<br>
+}<br>
+<br>
+lldb_private::CompilerDeclContext<br>
+SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid)<br>
+{<br>
+    return lldb_private::CompilerDeclContext();<br>
+}<br>
+<br>
+lldb_private::CompilerDeclContext<br>
+SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid)<br>
+{<br>
+    return lldb_private::CompilerDeclContext();<br>
+}<br>
+<br>
+void<br>
+SymbolFilePDB::ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx)<br>
+{<br>
+}<br>
+<br>
+uint32_t<br>
+SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, uint32_t resolve_scope,<br>
+                                    lldb_private::SymbolContext &sc)<br>
+{<br>
+    return uint32_t();<br>
+}<br>
+<br>
+uint32_t<br>
+SymbolFilePDB::ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines,<br>
+                                    uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list)<br>
+{<br>
+    if (resolve_scope & lldb::eSymbolContextCompUnit)<br>
+    {<br>
+        // Locate all compilation units with line numbers referencing the specified file.  For example, if<br>
+        // `file_spec` is <vector>, then this should return all source files and header files that reference<br>
+        // <vector>, either directly or indirectly.<br>
+        auto compilands =<br>
+            m_session_up->findCompilandsForSourceFile(file_spec.GetPath(), llvm::PDB_NameSearchFlags::NS_CaseInsensitive);<br>
+<br>
+        // For each one, either find get its previously parsed data, or parse it afresh and add it to<br>
+        // the symbol context list.<br>
+        while (auto compiland = compilands->getNext())<br>
+        {<br>
+            // If we're not checking inlines, then don't add line information for this file unless the FileSpec<br>
+            // matches.<br>
+            if (!check_inlines)<br>
+            {<br>
+                // `getSourceFileName` returns the basename of the original source file used to generate this compiland.<br>
+                // It does not return the full path.  Currently the only way to get that is to do a basename lookup to<br>
+                // get the IPDBSourceFile, but this is ambiguous in the case of two source files with the same name<br>
+                // contributing to the same compiland.  This is a moderately extreme edge case, so we consider this ok<br>
+                // for now, although we need to find a long term solution.<br>
+                std::string source_file = compiland->getSourceFileName();<br>
+                auto pdb_file = m_session_up->findOneSourceFile(compiland.get(), source_file,<br>
+                                                                llvm::PDB_NameSearchFlags::NS_CaseInsensitive);<br>
+                source_file = pdb_file->getFileName();<br>
+                FileSpec this_spec(source_file, false, FileSpec::ePathSyntaxWindows);<br>
+                if (!file_spec.FileEquals(this_spec))<br>
+                    continue;<br>
+            }<br>
+<br>
+            SymbolContext sc;<br>
+            auto cu = ParseCompileUnitForSymIndex(compiland->getSymIndexId());<br>
+            sc.comp_unit = cu.get();<br>
+            sc.module_sp = cu->GetModule();<br>
+            sc_list.Append(sc);<br>
+<br>
+            // If we were asked to resolve line entries, add all entries to the line table that match the requested<br>
+            // line (or all lines if `line` == 0)<br>
+            if (resolve_scope & lldb::eSymbolContextLineEntry)<br>
+                ParseCompileUnitLineTable(sc, line);<br>
+        }<br>
+    }<br>
+    return sc_list.GetSize();<br>
+}<br>
+<br>
+uint32_t<br>
+SymbolFilePDB::FindGlobalVariables(const lldb_private::ConstString &name,<br>
+                                   const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append,<br>
+                                   uint32_t max_matches, lldb_private::VariableList &variables)<br>
+{<br>
+    return uint32_t();<br>
+}<br>
+<br>
+uint32_t<br>
+SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression &regex, bool append, uint32_t max_matches,<br>
+                                   lldb_private::VariableList &variables)<br>
+{<br>
+    return uint32_t();<br>
+}<br>
+<br>
+uint32_t<br>
+SymbolFilePDB::FindFunctions(const lldb_private::ConstString &name,<br>
+                             const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask,<br>
+                             bool include_inlines, bool append, lldb_private::SymbolContextList &sc_list)<br>
+{<br>
+    return uint32_t();<br>
+}<br>
+<br>
+uint32_t<br>
+SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression &regex, bool include_inlines, bool append,<br>
+                             lldb_private::SymbolContextList &sc_list)<br>
+{<br>
+    return uint32_t();<br>
+}<br>
+<br>
+void<br>
+SymbolFilePDB::GetMangledNamesForFunction(const std::string &scope_qualified_name,<br>
+                                          std::vector<lldb_private::ConstString> &mangled_names)<br>
+{<br>
+}<br>
+<br>
+uint32_t<br>
+SymbolFilePDB::FindTypes(const lldb_private::SymbolContext &sc, const lldb_private::ConstString &name,<br>
+                         const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches,<br>
+                         llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,<br>
+                         lldb_private::TypeMap &types)<br>
+{<br>
+    return uint32_t();<br>
+}<br>
+<br>
+size_t<br>
+SymbolFilePDB::FindTypes(const std::vector<lldb_private::CompilerContext> &context, bool append,<br>
+                         lldb_private::TypeMap &types)<br>
+{<br>
+    return size_t();<br>
+}<br>
+<br>
+lldb_private::TypeList *<br>
+SymbolFilePDB::GetTypeList()<br>
+{<br>
+    return nullptr;<br>
+}<br>
+<br>
+size_t<br>
+SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, uint32_t type_mask,<br>
+                        lldb_private::TypeList &type_list)<br>
+{<br>
+    return size_t();<br>
+}<br>
+<br>
+lldb_private::TypeSystem *<br>
+SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language)<br>
+{<br>
+    auto type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language);<br>
+    if (type_system)<br>
+        type_system->SetSymbolFile(this);<br>
+    return type_system;<br>
+}<br>
+<br>
+lldb_private::CompilerDeclContext<br>
+SymbolFilePDB::FindNamespace(const lldb_private::SymbolContext &sc, const lldb_private::ConstString &name,<br>
+                             const lldb_private::CompilerDeclContext *parent_decl_ctx)<br>
+{<br>
+    return lldb_private::CompilerDeclContext();<br>
+}<br>
+<br>
+lldb_private::ConstString<br>
+SymbolFilePDB::GetPluginName()<br>
+{<br>
+    static ConstString g_name("pdb");<br>
+    return g_name;<br>
+}<br>
+<br>
+uint32_t<br>
+SymbolFilePDB::GetPluginVersion()<br>
+{<br>
+    return 1;<br>
+}<br>
+<br>
+lldb::CompUnitSP<br>
+SymbolFilePDB::ParseCompileUnitForSymIndex(uint32_t id)<br>
+{<br>
+    auto found_cu = m_comp_units.find(id);<br>
+    if (found_cu != m_comp_units.end())<br>
+        return found_cu->second;<br>
+<br>
+    auto cu = m_session_up->getConcreteSymbolById<llvm::PDBSymbolCompiland>(id);<br>
+<br>
+    // `getSourceFileName` returns the basename of the original source file used to generate this compiland.  It does<br>
+    // not return the full path.  Currently the only way to get that is to do a basename lookup to get the<br>
+    // IPDBSourceFile, but this is ambiguous in the case of two source files with the same name contributing to the<br>
+    // same compiland. This is a moderately extreme edge case, so we consider this ok for now, although we need to find<br>
+    // a long term solution.<br>
+    auto file = m_session_up->findOneSourceFile(cu.get(), cu->getSourceFileName(),<br>
+                                                llvm::PDB_NameSearchFlags::NS_CaseInsensitive);<br>
+    std::string path = file->getFileName();<br>
+<br>
+    lldb::LanguageType lang;<br>
+    auto details = cu->findOneChild<llvm::PDBSymbolCompilandDetails>();<br>
+    if (!details)<br>
+        lang = lldb::eLanguageTypeC_plus_plus;<br>
+    else<br>
+        lang = TranslateLanguage(details->getLanguage());<br>
+<br>
+    // Don't support optimized code for now, DebugInfoPDB does not return this information.<br>
+    bool optimized = false;<br>
+    auto result = std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, path.c_str(), id, lang, optimized);<br>
+    m_comp_units.insert(std::make_pair(id, result));<br>
+    return result;<br>
+}<br>
+<br>
+bool<br>
+SymbolFilePDB::ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc, uint32_t match_line)<br>
+{<br>
+    auto global = m_session_up->getGlobalScope();<br>
+    auto cu = m_session_up->getConcreteSymbolById<llvm::PDBSymbolCompiland>(sc.comp_unit->GetID());<br>
+<br>
+    // LineEntry needs the *index* of the file into the list of support files returned by<br>
+    // ParseCompileUnitSupportFiles.  But the underlying SDK gives us a globally unique<br>
+    // idenfitifier in the namespace of the PDB.  So, we have to do a mapping so that we<br>
+    // can hand out indices.<br>
+    std::unordered_map<uint32_t, uint32_t> index_map;<br>
+    BuildSupportFileIdToSupportFileIndexMap(*cu, index_map);<br>
+    auto line_table = llvm::make_unique<LineTable>(sc.comp_unit);<br>
+<br>
+    // Find contributions to `cu` from all source and header files.<br>
+    std::string path = sc.comp_unit->GetPath();<br>
+    auto files = m_session_up->getSourceFilesForCompiland(*cu);<br>
+<br>
+    // For each source and header file, create a LineSequence for contributions to the cu<br>
+    // from that file, and add the sequence.<br>
+    while (auto file = files->getNext())<br>
+    {<br>
+        std::unique_ptr<LineSequence> sequence(line_table->CreateLineSequenceContainer());<br>
+        auto lines = m_session_up->findLineNumbers(*cu, *file);<br>
+        int entry_count = lines->getChildCount();<br>
+<br>
+        for (int i = 0; i < entry_count; ++i)<br>
+        {<br>
+            auto line = lines->getChildAtIndex(i);<br>
+            uint32_t lno = line->getLineNumber();<br>
+<br>
+            // If `match_line` == 0 we add any line no matter what.  Otherwise, we only add<br>
+            // lines that match the requested line number.<br>
+            if (match_line != 0 && lno != match_line)<br>
+                continue;<br>
+<br>
+            uint64_t va = line->getVirtualAddress();<br>
+            uint32_t cno = line->getColumnNumber();<br>
+            uint32_t source_id = line->getSourceFileId();<br>
+            uint32_t source_idx = index_map[source_id];<br>
+<br>
+            bool is_basic_block = false; // PDB doesn't even have this concept, but LLDB doesn't use it anyway.<br>
+            bool is_prologue = false;<br>
+            bool is_epilogue = false;<br>
+            bool is_statement = line->isStatement();<br>
+            auto func = m_session_up->findSymbolByAddress(va, llvm::PDB_SymType::Function);<br>
+            if (func)<br>
+            {<br>
+                auto prologue = func->findOneChild<llvm::PDBSymbolFuncDebugStart>();<br>
+                is_prologue = (va == prologue->getVirtualAddress());<br>
+<br>
+                auto epilogue = func->findOneChild<llvm::PDBSymbolFuncDebugEnd>();<br>
+                is_epilogue = (va == epilogue->getVirtualAddress());<br>
+<br>
+                if (is_epilogue)<br>
+                {<br>
+                    // Once per function, add a termination entry after the last byte of the function.<br>
+                    // TODO: This makes the assumption that all functions are laid out contiguously in<br>
+                    // memory and have no gaps.  This is a wrong assumption in the general case, but is<br>
+                    // good enough to allow simple scenarios to work.  This needs to be revisited.<br>
+                    auto concrete_func = llvm::dyn_cast<llvm::PDBSymbolFunc>(func.get());<br>
+                    lldb::addr_t end_addr = concrete_func->getVirtualAddress() + concrete_func->getLength();<br>
+                    line_table->InsertLineEntry(end_addr, lno, 0, source_idx, false, false, false, false, true);<br>
+                }<br>
+            }<br>
+<br>
+            line_table->InsertLineEntry(va, lno, cno, source_idx, is_statement, is_basic_block, is_prologue,<br>
+                                        is_epilogue, false);<br>
+        }<br>
+    }<br>
+<br>
+    sc.comp_unit->SetLineTable(line_table.release());<br>
+    return true;<br>
+}<br>
+<br>
+void<br>
+SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(const llvm::PDBSymbolCompiland &cu,<br>
+                                                       std::unordered_map<uint32_t, uint32_t> &index_map) const<br>
+{<br>
+    // This is a hack, but we need to convert the source id into an index into the support<br>
+    // files array.  We don't want to do path comparisons to avoid basename / full path<br>
+    // issues that may or may not even be a problem, so we use the globally unique source<br>
+    // file identifiers.  Ideally we could use the global identifiers everywhere, but LineEntry<br>
+    // currently assumes indices.<br>
+    auto source_files = m_session_up->getSourceFilesForCompiland(cu);<br>
+    int index = 0;<br>
+<br>
+    while (auto file = source_files->getNext())<br>
+    {<br>
+        uint32_t source_id = file->getUniqueId();<br>
+        index_map[source_id] = index++;<br>
+    }<br>
+}<br>
<br>
Added: lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h?rev=262528&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h (added)<br>
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h Wed Mar  2 16:05:52 2016<br>
@@ -0,0 +1,190 @@<br>
+//===-- SymbolFilePDB.h -------------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_<br>
+#define lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_<br>
+<br>
+#include <unordered_map><br>
+<br>
+#include "lldb/Core/UserID.h"<br>
+#include "lldb/Symbol/SymbolFile.h"<br>
+<br>
+#include "llvm/DebugInfo/PDB/IPDBSession.h"<br>
+#include "llvm/DebugInfo/PDB/PDB.h"<br>
+<br>
+class SymbolFilePDB : public lldb_private::SymbolFile<br>
+{<br>
+public:<br>
+    //------------------------------------------------------------------<br>
+    // Static Functions<br>
+    //------------------------------------------------------------------<br>
+    static void<br>
+    Initialize();<br>
+<br>
+    static void<br>
+    Terminate();<br>
+<br>
+    static void<br>
+    DebuggerInitialize(lldb_private::Debugger &debugger);<br>
+<br>
+    static lldb_private::ConstString<br>
+    GetPluginNameStatic();<br>
+<br>
+    static const char *<br>
+    GetPluginDescriptionStatic();<br>
+<br>
+    static lldb_private::SymbolFile *<br>
+    CreateInstance(lldb_private::ObjectFile *obj_file);<br>
+<br>
+    //------------------------------------------------------------------<br>
+    // Constructors and Destructors<br>
+    //------------------------------------------------------------------<br>
+    SymbolFilePDB(lldb_private::ObjectFile *ofile);<br>
+<br>
+    ~SymbolFilePDB() override;<br>
+<br>
+    uint32_t<br>
+    CalculateAbilities() override;<br>
+<br>
+    void<br>
+    InitializeObject() override;<br>
+<br>
+    //------------------------------------------------------------------<br>
+    // Compile Unit function calls<br>
+    //------------------------------------------------------------------<br>
+<br>
+    uint32_t<br>
+    GetNumCompileUnits() override;<br>
+<br>
+    lldb::CompUnitSP<br>
+    ParseCompileUnitAtIndex(uint32_t index) override;<br>
+<br>
+    lldb::LanguageType<br>
+    ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) override;<br>
+<br>
+    size_t<br>
+    ParseCompileUnitFunctions(const lldb_private::SymbolContext &sc) override;<br>
+<br>
+    bool<br>
+    ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc) override;<br>
+<br>
+    bool<br>
+    ParseCompileUnitDebugMacros(const lldb_private::SymbolContext &sc) override;<br>
+<br>
+    bool<br>
+    ParseCompileUnitSupportFiles(const lldb_private::SymbolContext &sc,<br>
+                                 lldb_private::FileSpecList &support_files) override;<br>
+<br>
+    bool<br>
+    ParseImportedModules(const lldb_private::SymbolContext &sc,<br>
+                         std::vector<lldb_private::ConstString> &imported_modules) override;<br>
+<br>
+    size_t<br>
+    ParseFunctionBlocks(const lldb_private::SymbolContext &sc) override;<br>
+<br>
+    size_t<br>
+    ParseTypes(const lldb_private::SymbolContext &sc) override;<br>
+<br>
+    size_t<br>
+    ParseVariablesForContext(const lldb_private::SymbolContext &sc) override;<br>
+<br>
+    lldb_private::Type *<br>
+    ResolveTypeUID(lldb::user_id_t type_uid) override;<br>
+<br>
+    bool<br>
+    CompleteType(lldb_private::CompilerType &compiler_type) override;<br>
+<br>
+    lldb_private::CompilerDecl<br>
+    GetDeclForUID(lldb::user_id_t uid) override;<br>
+<br>
+    lldb_private::CompilerDeclContext<br>
+    GetDeclContextForUID(lldb::user_id_t uid) override;<br>
+<br>
+    lldb_private::CompilerDeclContext<br>
+    GetDeclContextContainingUID(lldb::user_id_t uid) override;<br>
+<br>
+    void<br>
+    ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override;<br>
+<br>
+    uint32_t<br>
+    ResolveSymbolContext(const lldb_private::Address &so_addr, uint32_t resolve_scope,<br>
+                         lldb_private::SymbolContext &sc) override;<br>
+<br>
+    uint32_t<br>
+    ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines,<br>
+                         uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list) override;<br>
+<br>
+    uint32_t<br>
+    FindGlobalVariables(const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx,<br>
+                        bool append, uint32_t max_matches, lldb_private::VariableList &variables) override;<br>
+<br>
+    uint32_t<br>
+    FindGlobalVariables(const lldb_private::RegularExpression &regex, bool append, uint32_t max_matches,<br>
+                        lldb_private::VariableList &variables) override;<br>
+<br>
+    uint32_t<br>
+    FindFunctions(const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx,<br>
+                  uint32_t name_type_mask, bool include_inlines, bool append,<br>
+                  lldb_private::SymbolContextList &sc_list) override;<br>
+<br>
+    uint32_t<br>
+    FindFunctions(const lldb_private::RegularExpression &regex, bool include_inlines, bool append,<br>
+                  lldb_private::SymbolContextList &sc_list) override;<br>
+<br>
+    void<br>
+    GetMangledNamesForFunction(const std::string &scope_qualified_name,<br>
+                               std::vector<lldb_private::ConstString> &mangled_names) override;<br>
+<br>
+    uint32_t<br>
+    FindTypes(const lldb_private::SymbolContext &sc, const lldb_private::ConstString &name,<br>
+              const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches,<br>
+              llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, lldb_private::TypeMap &types) override;<br>
+<br>
+    size_t<br>
+    FindTypes(const std::vector<lldb_private::CompilerContext> &context, bool append,<br>
+              lldb_private::TypeMap &types) override;<br>
+<br>
+    lldb_private::TypeList *<br>
+    GetTypeList() override;<br>
+<br>
+    size_t<br>
+    GetTypes(lldb_private::SymbolContextScope *sc_scope, uint32_t type_mask,<br>
+             lldb_private::TypeList &type_list) override;<br>
+<br>
+    lldb_private::TypeSystem *<br>
+    GetTypeSystemForLanguage(lldb::LanguageType language) override;<br>
+<br>
+    lldb_private::CompilerDeclContext<br>
+    FindNamespace(const lldb_private::SymbolContext &sc, const lldb_private::ConstString &name,<br>
+                  const lldb_private::CompilerDeclContext *parent_decl_ctx) override;<br>
+<br>
+    lldb_private::ConstString<br>
+    GetPluginName() override;<br>
+<br>
+    uint32_t<br>
+    GetPluginVersion() override;<br>
+<br>
+private:<br>
+    lldb::CompUnitSP<br>
+    ParseCompileUnitForSymIndex(uint32_t id);<br>
+<br>
+    bool<br>
+    ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc, uint32_t match_line);<br>
+<br>
+    void<br>
+    BuildSupportFileIdToSupportFileIndexMap(const llvm::PDBSymbolCompiland &cu,<br>
+                                            std::unordered_map<uint32_t, uint32_t> &index_map) const;<br>
+<br>
+    std::unordered_map<uint32_t, lldb::CompUnitSP> m_comp_units;<br>
+<br>
+    std::unique_ptr<llvm::IPDBSession> m_session_up;<br>
+    uint32_t m_cached_compile_unit_count;<br>
+};<br>
+<br>
+#endif // lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_<br>
<br>
Modified: lldb/trunk/unittests/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/CMakeLists.txt?rev=262528&r1=262527&r2=262528&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/CMakeLists.txt?rev=262528&r1=262527&r2=262528&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/unittests/CMakeLists.txt (original)<br>
+++ lldb/trunk/unittests/CMakeLists.txt Wed Mar  2 16:05:52 2016<br>
@@ -18,15 +18,31 @@ function(add_lldb_unittest test_name)<br>
     ${ARGN}<br>
     )<br>
<br>
+  add_custom_command(<br>
+    TARGET ${test_name}<br>
+    POST_BUILD<br>
+    COMMAND "${CMAKE_COMMAND}" -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/Inputs)<br>
+<br>
   lldb_link_common_libs(${test_name} EXE)<br>
   target_link_libraries(${test_name} ${CLANG_USED_LIBS} ${LLDB_SYSTEM_LIBS})<br>
   llvm_config(${test_name} ${LLVM_LINK_COMPONENTS})<br>
 endfunction()<br>
<br>
+function(add_unittest_inputs test_name inputs)<br>
+  foreach (INPUT ${inputs})<br>
+    add_custom_command(<br>
+      TARGET ${test_name}<br>
+      POST_BUILD<br>
+      COMMAND "${CMAKE_COMMAND}" -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Inputs/${INPUT} ${CMAKE_CURRENT_BINARY_DIR}/Inputs<br>
+      COMMENT "Copying ${INPUT} to binary directory.")<br>
+  endforeach()<br>
+endfunction()<br>
+<br>
 add_subdirectory(Core)<br>
 add_subdirectory(Editline)<br>
 add_subdirectory(Expression)<br>
 add_subdirectory(Host)<br>
 add_subdirectory(Interpreter)<br>
 add_subdirectory(ScriptInterpreter)<br>
+add_subdirectory(SymbolFile)<br>
 add_subdirectory(Utility)<br>
<br>
Added: lldb/trunk/unittests/SymbolFile/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/CMakeLists.txt?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/CMakeLists.txt?rev=262528&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/unittests/SymbolFile/CMakeLists.txt (added)<br>
+++ lldb/trunk/unittests/SymbolFile/CMakeLists.txt Wed Mar  2 16:05:52 2016<br>
@@ -0,0 +1 @@<br>
+add_subdirectory(PDB)<br>
<br>
Added: lldb/trunk/unittests/SymbolFile/PDB/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/CMakeLists.txt?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/CMakeLists.txt?rev=262528&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/unittests/SymbolFile/PDB/CMakeLists.txt (added)<br>
+++ lldb/trunk/unittests/SymbolFile/PDB/CMakeLists.txt Wed Mar  2 16:05:52 2016<br>
@@ -0,0 +1,10 @@<br>
+add_lldb_unittest(SymbolFilePDBTests<br>
+  SymbolFilePDBTests.cpp<br>
+  )<br>
+<br>
+set(test_inputs<br>
+   test-pdb.exe<br>
+   test-pdb.pdb<br>
+   test-dwarf.exe)<br>
+<br>
+add_unittest_inputs(SymbolFilePDBTests "${test_inputs}")<br>
<br>
Added: lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-dwarf.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-dwarf.cpp?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-dwarf.cpp?rev=262528&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-dwarf.cpp (added)<br>
+++ lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-dwarf.cpp Wed Mar  2 16:05:52 2016<br>
@@ -0,0 +1,14 @@<br>
+// Compile with "cl /c /Zi /GR- test.cpp"<br>
+// Link with "link test.obj /debug /nodefaultlib /entry:main /out:test.exe"<br>
+<br>
+int __cdecl _purecall(void)<br>
+{<br>
+    return 0;<br>
+}<br>
+<br>
+int<br>
+main(int argc, char **argv)<br>
+{<br>
+<br>
+    return 0;<br>
+}<br>
<br>
Added: lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-dwarf.exe<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-dwarf.exe?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-dwarf.exe?rev=262528&view=auto</a><br>
==============================================================================<br>
Binary files lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-dwarf.exe (added) and lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-dwarf.exe Wed Mar  2 16:05:52 2016 differ<br>
<br>
Added: lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-alt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-alt.cpp?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-alt.cpp?rev=262528&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-alt.cpp (added)<br>
+++ lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-alt.cpp Wed Mar  2 16:05:52 2016<br>
@@ -0,0 +1,9 @@<br>
+// Compile with "cl /c /Zi /GR- test-pdb-alt.cpp"<br>
+// Link with "link test-pdb.obj test-pdb-alt.obj /debug /nodefaultlib /entry:main /out:test-pdb.exe"<br>
+<br>
+#include "test-pdb.h"<br>
+<br>
+int bar(int n)<br>
+{<br>
+    return n-1;<br>
+}<br>
<br>
Added: lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-nested.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-nested.h?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-nested.h?rev=262528&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-nested.h (added)<br>
+++ lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb-nested.h Wed Mar  2 16:05:52 2016<br>
@@ -0,0 +1,9 @@<br>
+#ifndef TEST_PDB_NESTED_H<br>
+#define TEST_PDB_NESTED_H<br>
+<br>
+inline int baz(int n)<br>
+{<br>
+    return n+1;<br>
+}<br>
+<br>
+#endif<br>
\ No newline at end of file<br>
<br>
Added: lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.cpp?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.cpp?rev=262528&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.cpp (added)<br>
+++ lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.cpp Wed Mar  2 16:05:52 2016<br>
@@ -0,0 +1,15 @@<br>
+// Compile with "cl /c /Zi /GR- test-pdb.cpp"<br>
+// Link with "link test-pdb.obj /debug /nodefaultlib /entry:main /out:test-pdb.exe"<br>
+<br>
+#include "test-pdb.h"<br>
+<br>
+int __cdecl _purecall(void)<br>
+{<br>
+    return 0;<br>
+}<br>
+<br>
+int<br>
+main(int argc, char **argv)<br>
+{<br>
+    return foo(argc) + bar(argc);<br>
+}<br>
<br>
Added: lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.exe<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.exe?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.exe?rev=262528&view=auto</a><br>
==============================================================================<br>
Binary files lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.exe (added) and lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.exe Wed Mar  2 16:05:52 2016 differ<br>
<br>
Added: lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.h?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.h?rev=262528&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.h (added)<br>
+++ lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.h Wed Mar  2 16:05:52 2016<br>
@@ -0,0 +1,13 @@<br>
+#ifndef TEST_PDB_H<br>
+#define TEST_PDB_H<br>
+<br>
+#include "test-pdb-nested.h"<br>
+<br>
+int bar(int n);<br>
+<br>
+inline int foo(int n)<br>
+{<br>
+    return baz(n)+1;<br>
+}<br>
+<br>
+#endif<br>
\ No newline at end of file<br>
<br>
Added: lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.pdb<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.pdb?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.pdb?rev=262528&view=auto</a><br>
==============================================================================<br>
Binary files lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.pdb (added) and lldb/trunk/unittests/SymbolFile/PDB/Inputs/test-pdb.pdb Wed Mar  2 16:05:52 2016 differ<br>
<br>
Added: lldb/trunk/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp?rev=262528&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp?rev=262528&view=auto</a><br>
==============================================================================<br>
--- lldb/trunk/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp (added)<br>
+++ lldb/trunk/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp Wed Mar  2 16:05:52 2016<br>
@@ -0,0 +1,344 @@<br>
+//===-- PythonDataObjectsTests.cpp ------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "gtest/gtest.h"<br>
+<br>
+#include "llvm/ADT/STLExtras.h"<br>
+#include "llvm/Config/config.h"<br>
+#include "llvm/Support/FileSystem.h"<br>
+#include "llvm/Support/Path.h"<br>
+<br>
+#include "lldb/Core/Address.h"<br>
+#include "lldb/Core/ArchSpec.h"<br>
+#include "lldb/Core/Module.h"<br>
+#include "lldb/Core/ModuleSpec.h"<br>
+#include "lldb/Host/FileSpec.h"<br>
+#include "lldb/Host/HostInfo.h"<br>
+#include "lldb/Symbol/CompileUnit.h"<br>
+#include "lldb/Symbol/LineTable.h"<br>
+#include "lldb/Symbol/SymbolVendor.h"<br>
+<br>
+#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"<br>
+#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"<br>
+#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"<br>
+<br>
+#if defined(_MSC_VER)<br>
+#include <objbase.h><br>
+#endif<br>
+<br>
+extern const char *TestMainArgv0;<br>
+<br>
+using namespace lldb_private;<br>
+<br>
+class SymbolFilePDBTests : public testing::Test<br>
+{<br>
+public:<br>
+    void<br>
+    SetUp() override<br>
+    {<br>
+#if defined(_MSC_VER)<br>
+        ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);<br>
+#endif<br>
+<br>
+        HostInfoBase::Initialize();<br>
+        ObjectFilePECOFF::Initialize();<br>
+        SymbolFileDWARF::Initialize();<br>
+        SymbolFilePDB::Initialize();<br>
+<br>
+        llvm::StringRef exe_folder = llvm::sys::path::parent_path(TestMainArgv0);<br>
+        llvm::SmallString<128> inputs_folder = exe_folder;<br>
+        llvm::sys::path::append(inputs_folder, "Inputs");<br>
+<br>
+        m_pdb_test_exe = inputs_folder;<br>
+        m_dwarf_test_exe = inputs_folder;<br>
+        llvm::sys::path::append(m_pdb_test_exe, "test-pdb.exe");<br>
+        llvm::sys::path::append(m_dwarf_test_exe, "test-dwarf.exe");<br>
+    }<br>
+<br>
+    void<br>
+    TearDown() override<br>
+    {<br>
+#if defined(_MSC_VER)<br>
+        ::CoUninitialize();<br>
+#endif<br>
+        SymbolFilePDB::Terminate();<br>
+        SymbolFileDWARF::Terminate();<br>
+        ObjectFilePECOFF::Terminate();<br>
+    }<br>
+<br>
+protected:<br>
+    llvm::SmallString<128> m_pdb_test_exe;<br>
+    llvm::SmallString<128> m_dwarf_test_exe;<br>
+<br>
+    bool<br>
+    FileSpecMatchesAsBaseOrFull(const FileSpec &left, const FileSpec &right) const<br>
+    {<br>
+        // If the filenames don't match, the paths can't be equal<br>
+        if (!left.FileEquals(right))<br>
+            return false;<br>
+        // If BOTH have a directory, also compare the directories.<br>
+        if (left.GetDirectory() && right.GetDirectory())<br>
+            return left.DirectoryEquals(right);<br>
+<br>
+        // If one has a directory but not the other, they match.<br>
+        return true;<br>
+    }<br>
+<br>
+    void<br>
+    VerifyLineEntry(lldb::ModuleSP module, const SymbolContext &sc, const FileSpec &spec, LineTable &lt, uint32_t line,<br>
+                    lldb::addr_t addr)<br>
+    {<br>
+        LineEntry entry;<br>
+        Address address;<br>
+        EXPECT_TRUE(module->ResolveFileAddress(addr, address));<br>
+<br>
+        EXPECT_TRUE(lt.FindLineEntryByAddress(address, entry));<br>
+        EXPECT_EQ(line, entry.line);<br>
+        EXPECT_EQ(address, entry.range.GetBaseAddress());<br>
+<br>
+        EXPECT_TRUE(FileSpecMatchesAsBaseOrFull(spec, entry.file));<br>
+    }<br>
+<br>
+    bool<br>
+    ContainsCompileUnit(const SymbolContextList &sc_list, const FileSpec &spec) const<br>
+    {<br>
+        for (int i = 0; i < sc_list.GetSize(); ++i)<br>
+        {<br>
+            const SymbolContext &sc = sc_list[i];<br>
+            if (FileSpecMatchesAsBaseOrFull(*sc.comp_unit, spec))<br>
+                return true;<br>
+        }<br>
+        return false;<br>
+    }<br>
+};<br>
+<br>
+#if defined(HAVE_DIA_SDK)<br>
+#define REQUIRES_DIA_SDK(TestName) TestName<br>
+#else<br>
+#define REQUIRES_DIA_SDK(TestName) DISABLED_##TestName<br>
+#endif<br>
+<br>
+TEST_F(SymbolFilePDBTests, TestAbilitiesForDWARF)<br>
+{<br>
+    // Test that when we have Dwarf debug info, SymbolFileDWARF is used.<br>
+    FileSpec fspec(m_dwarf_test_exe.c_str(), false);<br>
+    ArchSpec aspec("i686-pc-windows");<br>
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);<br>
+<br>
+    SymbolVendor *plugin = module->GetSymbolVendor();<br>
+    EXPECT_NE(nullptr, plugin);<br>
+    SymbolFile *symfile = plugin->GetSymbolFile();<br>
+    EXPECT_NE(nullptr, symfile);<br>
+    EXPECT_EQ(symfile->GetPluginName(), SymbolFileDWARF::GetPluginNameStatic());<br>
+<br>
+    uint32_t expected_abilities = SymbolFile::kAllAbilities;<br>
+    EXPECT_EQ(expected_abilities, symfile->CalculateAbilities());<br>
+}<br>
+<br>
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestAbilitiesForPDB))<br>
+{<br>
+    // Test that when we have PDB debug info, SymbolFilePDB is used.<br>
+    FileSpec fspec(m_pdb_test_exe.c_str(), false);<br>
+    ArchSpec aspec("i686-pc-windows");<br>
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);<br>
+<br>
+    SymbolVendor *plugin = module->GetSymbolVendor();<br>
+    EXPECT_NE(nullptr, plugin);<br>
+    SymbolFile *symfile = plugin->GetSymbolFile();<br>
+    EXPECT_NE(nullptr, symfile);<br>
+    EXPECT_EQ(symfile->GetPluginName(), SymbolFilePDB::GetPluginNameStatic());<br>
+<br>
+    uint32_t expected_abilities = SymbolFile::CompileUnits | SymbolFile::LineTables;<br>
+    EXPECT_EQ(expected_abilities, symfile->CalculateAbilities());<br>
+}<br>
+<br>
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestResolveSymbolContextBasename))<br>
+{<br>
+    // Test that attempting to call ResolveSymbolContext with only a basename finds all full paths<br>
+    // with the same basename<br>
+    FileSpec fspec(m_pdb_test_exe.c_str(), false);<br>
+    ArchSpec aspec("i686-pc-windows");<br>
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);<br>
+<br>
+    SymbolVendor *plugin = module->GetSymbolVendor();<br>
+    EXPECT_NE(nullptr, plugin);<br>
+    SymbolFile *symfile = plugin->GetSymbolFile();<br>
+<br>
+    FileSpec header_spec("test-pdb.cpp", false);<br>
+    SymbolContextList sc_list;<br>
+    uint32_t result_count = symfile->ResolveSymbolContext(header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list);<br>
+    EXPECT_EQ(1, result_count);<br>
+    EXPECT_TRUE(ContainsCompileUnit(sc_list, header_spec));<br>
+}<br>
+<br>
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestResolveSymbolContextFullPath))<br>
+{<br>
+    // Test that attempting to call ResolveSymbolContext with a full path only finds the one source<br>
+    // file that matches the full path.<br>
+    FileSpec fspec(m_pdb_test_exe.c_str(), false);<br>
+    ArchSpec aspec("i686-pc-windows");<br>
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);<br>
+<br>
+    SymbolVendor *plugin = module->GetSymbolVendor();<br>
+    EXPECT_NE(nullptr, plugin);<br>
+    SymbolFile *symfile = plugin->GetSymbolFile();<br>
+<br>
+    FileSpec header_spec(R"spec(D:\src\llvm\tools\lldb\unittests\SymbolFile\PDB\Inputs\test-pdb.cpp)spec", false);<br>
+    SymbolContextList sc_list;<br>
+    uint32_t result_count = symfile->ResolveSymbolContext(header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list);<br>
+    EXPECT_GE(1, result_count);<br>
+    EXPECT_TRUE(ContainsCompileUnit(sc_list, header_spec));<br>
+}<br>
+<br>
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLookupOfHeaderFileWithInlines))<br>
+{<br>
+    // Test that when looking up a header file via ResolveSymbolContext (i.e. a file that was not by itself<br>
+    // compiled, but only contributes to the combined code of other source files), a SymbolContext is returned<br>
+    // for each compiland which has line contributions from the requested header.<br>
+    FileSpec fspec(m_pdb_test_exe.c_str(), false);<br>
+    ArchSpec aspec("i686-pc-windows");<br>
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);<br>
+<br>
+    SymbolVendor *plugin = module->GetSymbolVendor();<br>
+    EXPECT_NE(nullptr, plugin);<br>
+    SymbolFile *symfile = plugin->GetSymbolFile();<br>
+<br>
+    FileSpec header_specs[] = {FileSpec("test-pdb.h", false), FileSpec("test-pdb-nested.h", false)};<br>
+    FileSpec main_cpp_spec("test-pdb.cpp", false);<br>
+    FileSpec alt_cpp_spec("test-pdb-alt.cpp", false);<br>
+    for (const auto &hspec : header_specs)<br>
+    {<br>
+        SymbolContextList sc_list;<br>
+        uint32_t result_count = symfile->ResolveSymbolContext(hspec, 0, true, lldb::eSymbolContextCompUnit, sc_list);<br>
+        EXPECT_EQ(2, result_count);<br>
+        EXPECT_TRUE(ContainsCompileUnit(sc_list, main_cpp_spec));<br>
+        EXPECT_TRUE(ContainsCompileUnit(sc_list, alt_cpp_spec));<br>
+    }<br>
+}<br>
+<br>
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLookupOfHeaderFileWithNoInlines))<br>
+{<br>
+    // Test that when looking up a header file via ResolveSymbolContext (i.e. a file that was not by itself<br>
+    // compiled, but only contributes to the combined code of other source files), that if check_inlines<br>
+    // is false, no SymbolContexts are returned.<br>
+    FileSpec fspec(m_pdb_test_exe.c_str(), false);<br>
+    ArchSpec aspec("i686-pc-windows");<br>
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);<br>
+<br>
+    SymbolVendor *plugin = module->GetSymbolVendor();<br>
+    EXPECT_NE(nullptr, plugin);<br>
+    SymbolFile *symfile = plugin->GetSymbolFile();<br>
+<br>
+    FileSpec header_specs[] = {FileSpec("test-pdb.h", false), FileSpec("test-pdb-nested.h", false)};<br>
+    for (const auto &hspec : header_specs)<br>
+    {<br>
+        SymbolContextList sc_list;<br>
+        uint32_t result_count = symfile->ResolveSymbolContext(hspec, 0, false, lldb::eSymbolContextCompUnit, sc_list);<br>
+        EXPECT_EQ(0, result_count);<br>
+    }<br>
+}<br>
+<br>
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLineTablesMatchAll))<br>
+{<br>
+    // Test that when calling ResolveSymbolContext with a line number of 0, all line entries from<br>
+    // the specified files are returned.<br>
+    FileSpec fspec(m_pdb_test_exe.c_str(), false);<br>
+    ArchSpec aspec("i686-pc-windows");<br>
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);<br>
+<br>
+    SymbolVendor *plugin = module->GetSymbolVendor();<br>
+    SymbolFile *symfile = plugin->GetSymbolFile();<br>
+<br>
+    FileSpec source_file("test-pdb.cpp", false);<br>
+    FileSpec header1("test-pdb.h", false);<br>
+    FileSpec header2("test-pdb-nested.h", false);<br>
+    uint32_t cus = symfile->GetNumCompileUnits();<br>
+    EXPECT_EQ(2, cus);<br>
+<br>
+    SymbolContextList sc_list;<br>
+    uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry;<br>
+<br>
+    uint32_t count = symfile->ResolveSymbolContext(source_file, 0, true, scope, sc_list);<br>
+    EXPECT_EQ(1, count);<br>
+    SymbolContext sc;<br>
+    EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));<br>
+<br>
+    LineTable *lt = sc.comp_unit->GetLineTable();<br>
+    EXPECT_NE(nullptr, lt);<br>
+    count = lt->GetSize();<br>
+    // We expect one extra entry for termination (per function)<br>
+    EXPECT_EQ(16, count);<br>
+<br>
+    VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040);<br>
+    VerifyLineEntry(module, sc, source_file, *lt, 8, 0x401043);<br>
+    VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045);<br>
+<br>
+    VerifyLineEntry(module, sc, source_file, *lt, 13, 0x401050);<br>
+    VerifyLineEntry(module, sc, source_file, *lt, 14, 0x401054);<br>
+    VerifyLineEntry(module, sc, source_file, *lt, 15, 0x401070);<br>
+<br>
+    VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090);<br>
+    VerifyLineEntry(module, sc, header1, *lt, 10, 0x401093);<br>
+    VerifyLineEntry(module, sc, header1, *lt, 11, 0x4010a2);<br>
+<br>
+    VerifyLineEntry(module, sc, header2, *lt, 5, 0x401080);<br>
+    VerifyLineEntry(module, sc, header2, *lt, 6, 0x401083);<br>
+    VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089);<br>
+}<br>
+<br>
+TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLineTablesMatchSpecific))<br>
+{<br>
+    // Test that when calling ResolveSymbolContext with a specific line number, only line entries<br>
+    // which match the requested line are returned.<br>
+    FileSpec fspec(m_pdb_test_exe.c_str(), false);<br>
+    ArchSpec aspec("i686-pc-windows");<br>
+    lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);<br>
+<br>
+    SymbolVendor *plugin = module->GetSymbolVendor();<br>
+    SymbolFile *symfile = plugin->GetSymbolFile();<br>
+<br>
+    FileSpec source_file("test-pdb.cpp", false);<br>
+    FileSpec header1("test-pdb.h", false);<br>
+    FileSpec header2("test-pdb-nested.h", false);<br>
+    uint32_t cus = symfile->GetNumCompileUnits();<br>
+    EXPECT_EQ(2, cus);<br>
+<br>
+    SymbolContextList sc_list;<br>
+    uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry;<br>
+<br>
+    // First test with line 7, and verify that only line 7 entries are added.<br>
+    uint32_t count = symfile->ResolveSymbolContext(source_file, 7, true, scope, sc_list);<br>
+    EXPECT_EQ(1, count);<br>
+    SymbolContext sc;<br>
+    EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));<br>
+<br>
+    LineTable *lt = sc.comp_unit->GetLineTable();<br>
+    EXPECT_NE(nullptr, lt);<br>
+    count = lt->GetSize();<br>
+    // We expect one extra entry for termination<br>
+    EXPECT_EQ(3, count);<br>
+<br>
+    VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040);<br>
+    VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089);<br>
+<br>
+    sc_list.Clear();<br>
+    // Then test with line 9, and verify that only line 9 entries are added.<br>
+    count = symfile->ResolveSymbolContext(source_file, 9, true, scope, sc_list);<br>
+    EXPECT_EQ(1, count);<br>
+    EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));<br>
+<br>
+    lt = sc.comp_unit->GetLineTable();<br>
+    EXPECT_NE(nullptr, lt);<br>
+    count = lt->GetSize();<br>
+    // We expect one extra entry for termination<br>
+    EXPECT_EQ(3, count);<br>
+<br>
+    VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045);<br>
+    VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090);<br>
+}<br>
<br>
<br>
_______________________________________________<br>
lldb-commits mailing list<br>
<a href="mailto:lldb-commits@lists.llvm.org" target="_blank">lldb-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits</a><br>
</blockquote></div></div>