[PDB] Support executables and source/line info.
authorZachary Turner <zturner@google.com>
Fri, 17 Apr 2015 22:40:36 +0000 (22:40 +0000)
committerZachary Turner <zturner@google.com>
Fri, 17 Apr 2015 22:40:36 +0000 (22:40 +0000)
Previously DebugInfoPDB could only load data for a PDB given a
path to the PDB.  It could not open an EXE and find the matching
PDB and verify it matched, etc.  This patch adds support for that
so that we can simply load debug information for a PDB directly.

Additionally, this patch extends DebugInfoPDB to support getting
source and line information for symbols.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235237 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/DebugInfo/PDB/DIA/DIASession.h
include/llvm/DebugInfo/PDB/IPDBSession.h
include/llvm/DebugInfo/PDB/PDB.h
include/llvm/DebugInfo/PDB/PDBTypes.h
lib/DebugInfo/PDB/DIA/DIASession.cpp
lib/DebugInfo/PDB/PDB.cpp
tools/llvm-pdbdump/llvm-pdbdump.cpp
unittests/DebugInfo/PDB/PDBApiTest.cpp

index 6c72c3e6fc60dca280e7e09ac734fe15104ac8da..b8d1f1ca5bf92fbbd0f02f69ce9c448573fe6996 100644 (file)
@@ -21,12 +21,19 @@ public:
 
   static PDB_ErrorCode createFromPdb(StringRef Path,
                                      std::unique_ptr<IPDBSession> &Session);
+  static PDB_ErrorCode createFromExe(StringRef Path,
+                                     std::unique_ptr<IPDBSession> &Session);
 
   uint64_t getLoadAddress() const override;
   void setLoadAddress(uint64_t Address) override;
   std::unique_ptr<PDBSymbolExe> getGlobalScope() const override;
   std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override;
 
+  std::unique_ptr<PDBSymbol>
+  findSymbolByAddress(uint64_t Address) const override;
+  std::unique_ptr<IPDBEnumLineNumbers>
+  findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override;
+
   std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const override;
   std::unique_ptr<IPDBEnumSourceFiles> getSourceFilesForCompiland(
       const PDBSymbolCompiland &Compiland) const override;
index 60d6f62068eb34bd052af822a7270e925e5a2054..f1debc02bc602b4b3e9db2258646519746733289 100644 (file)
@@ -43,6 +43,11 @@ public:
     return std::unique_ptr<T>(ConcreteSymbol);
   }
 
+  virtual std::unique_ptr<PDBSymbol>
+  findSymbolByAddress(uint64_t Address) const = 0;
+  virtual std::unique_ptr<IPDBEnumLineNumbers>
+  findLineNumbersByAddress(uint64_t Address, uint32_t Length) const = 0;
+
   virtual std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const = 0;
   virtual std::unique_ptr<IPDBEnumSourceFiles>
   getSourceFilesForCompiland(const PDBSymbolCompiland &Compiland) const = 0;
index 67878e9ccf600707636d0f6d3accb9eb2d4ef2bf..5df3be85e381b50ac1ebe1deedb98f6fa68095fc 100644 (file)
 namespace llvm {
 class StringRef;
 
-PDB_ErrorCode createPDBReader(PDB_ReaderType Type, StringRef Path,
-                              std::unique_ptr<IPDBSession> &Session);
+PDB_ErrorCode loadDataForPDB(PDB_ReaderType Type, StringRef Path,
+                             std::unique_ptr<IPDBSession> &Session);
+
+PDB_ErrorCode loadDataForEXE(PDB_ReaderType Type, StringRef Path,
+                             std::unique_ptr<IPDBSession> &Session);
 }
 
 #endif
index 686e08f81a1f29be6d1a7226cdfd380873c11426..2d19e792d3d09b8f29e9c0eea464d2c1971a7bef 100644 (file)
@@ -21,6 +21,7 @@ class PDBSymbol;
 
 class IPDBDataStream;
 template <class T> class IPDBEnumChildren;
+class IPDBLineNumber;
 class IPDBRawSymbol;
 class IPDBSession;
 class IPDBSourceFile;
@@ -28,6 +29,7 @@ class IPDBSourceFile;
 typedef IPDBEnumChildren<PDBSymbol> IPDBEnumSymbols;
 typedef IPDBEnumChildren<IPDBSourceFile> IPDBEnumSourceFiles;
 typedef IPDBEnumChildren<IPDBDataStream> IPDBEnumDataStreams;
+typedef IPDBEnumChildren<IPDBLineNumber> IPDBEnumLineNumbers;
 
 class PDBSymbolExe;
 class PDBSymbolCompiland;
@@ -426,7 +428,8 @@ enum class PDB_ErrorCode {
   InvalidParameter,
   AlreadyLoaded,
   UnknownError,
-  NoMemory
+  NoMemory,
+  DebugInfoMismatch
 };
 
 struct VersionInfo {
index 4966bea96f6c208baaae369ae6c872edbe693505..e3e3fc05ab30adc7cc6ef1715ad8f0d11f5071b9 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
 #include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
 #include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
 #include "llvm/DebugInfo/PDB/DIA/DIASession.h"
@@ -64,6 +65,50 @@ PDB_ErrorCode DIASession::createFromPdb(StringRef Path,
   return PDB_ErrorCode::Success;
 }
 
+PDB_ErrorCode DIASession::createFromExe(StringRef Path,
+                                        std::unique_ptr<IPDBSession> &Session) {
+  CComPtr<IDiaDataSource> DiaDataSource;
+  CComPtr<IDiaSession> DiaSession;
+
+  // We assume that CoInitializeEx has already been called by the executable.
+  HRESULT Result = ::CoCreateInstance(
+      CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource,
+      reinterpret_cast<LPVOID *>(&DiaDataSource));
+  if (FAILED(Result))
+    return PDB_ErrorCode::NoPdbImpl;
+
+  llvm::SmallVector<UTF16, 128> Path16;
+  if (!llvm::convertUTF8ToUTF16String(Path, Path16))
+    return PDB_ErrorCode::InvalidPath;
+
+  const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
+  if (FAILED(Result =
+                 DiaDataSource->loadDataForExe(Path16Str, nullptr, nullptr))) {
+    if (Result == E_PDB_NOT_FOUND)
+      return PDB_ErrorCode::InvalidPath;
+    else if (Result == E_PDB_FORMAT)
+      return PDB_ErrorCode::InvalidFileFormat;
+    else if (Result == E_PDB_INVALID_SIG || Result == E_PDB_INVALID_AGE)
+      return PDB_ErrorCode::DebugInfoMismatch;
+    else if (Result == E_INVALIDARG)
+      return PDB_ErrorCode::InvalidParameter;
+    else if (Result == E_UNEXPECTED)
+      return PDB_ErrorCode::AlreadyLoaded;
+    else
+      return PDB_ErrorCode::UnknownError;
+  }
+
+  if (FAILED(Result = DiaDataSource->openSession(&DiaSession))) {
+    if (Result == E_OUTOFMEMORY)
+      return PDB_ErrorCode::NoMemory;
+    else
+      return PDB_ErrorCode::UnknownError;
+  }
+
+  Session.reset(new DIASession(DiaSession));
+  return PDB_ErrorCode::Success;
+}
+
 uint64_t DIASession::getLoadAddress() const {
   uint64_t LoadAddress;
   bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
@@ -95,6 +140,24 @@ std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const {
   return PDBSymbol::create(*this, std::move(RawSymbol));
 }
 
+std::unique_ptr<PDBSymbol>
+DIASession::findSymbolByAddress(uint64_t Address) const {
+  CComPtr<IDiaSymbol> Symbol;
+  if (S_OK != Session->findSymbolByVA(Address, SymTagNull, &Symbol))
+    return nullptr;
+  auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
+  return PDBSymbol::create(*this, std::move(RawSymbol));
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
+  CComPtr<IDiaEnumLineNumbers> LineNumbers;
+  if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers))
+    return nullptr;
+
+  return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
+}
+
 std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
   CComPtr<IDiaEnumSourceFiles> Files;
   if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
index a07396d1a175503cfbdf492d50710af7bff73611..13201bbaa641d518e154708cd248fa83b5338636 100644 (file)
 
 using namespace llvm;
 
-PDB_ErrorCode llvm::createPDBReader(PDB_ReaderType Type, StringRef Path,
-                                    std::unique_ptr<IPDBSession> &Session) {
+PDB_ErrorCode llvm::loadDataForPDB(PDB_ReaderType Type, StringRef Path,
+                                   std::unique_ptr<IPDBSession> &Session) {
   // Create the correct concrete instance type based on the value of Type.
 #if HAVE_DIA_SDK
   return DIASession::createFromPdb(Path, Session);
 #endif
   return PDB_ErrorCode::NoPdbImpl;
 }
+
+PDB_ErrorCode llvm::loadDataForEXE(PDB_ReaderType Type, StringRef Path,
+                                   std::unique_ptr<IPDBSession> &Session) {
+// Create the correct concrete instance type based on the value of Type.
+#if HAVE_DIA_SDK
+  return DIASession::createFromExe(Path, Session);
+#endif
+  return PDB_ErrorCode::NoPdbImpl;
+}
index 78535ec0be9f930afe2a4e62797307f73c5366b5..597683291ffd9a3c7383383031f528219dfac810 100644 (file)
@@ -101,7 +101,7 @@ cl::opt<bool> NoEnumDefs("no-enum-definitions",
 static void dumpInput(StringRef Path) {
   std::unique_ptr<IPDBSession> Session;
   PDB_ErrorCode Error =
-      llvm::createPDBReader(PDB_ReaderType::DIA, Path, Session);
+      llvm::loadDataForPDB(PDB_ReaderType::DIA, Path, Session);
   switch (Error) {
   case PDB_ErrorCode::Success:
     break;
index 629c5f8bc0ec70ae8856701d2c756f49c6da1119..4f8e95d9078f83c64f216a23a5bbe759199c82db 100644 (file)
@@ -72,6 +72,16 @@ class MockSession : public IPDBSession {
   getSourceFileById(uint32_t SymbolId) const override {
     return nullptr;
   }
+
+  std::unique_ptr<PDBSymbol>
+  findSymbolByAddress(uint64_t Address) const override {
+    return nullptr;
+  }
+  std::unique_ptr<IPDBEnumLineNumbers>
+  findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override {
+    return nullptr;
+  }
+
   std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const override {
     return nullptr;
   }