diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/include/llvm/DebugInfo/PDB/DIA/DIASession.h index 6c72c3e6fc6..b8d1f1ca5bf 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIASession.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIASession.h @@ -21,12 +21,19 @@ public: static PDB_ErrorCode createFromPdb(StringRef Path, std::unique_ptr &Session); + static PDB_ErrorCode createFromExe(StringRef Path, + std::unique_ptr &Session); uint64_t getLoadAddress() const override; void setLoadAddress(uint64_t Address) override; std::unique_ptr getGlobalScope() const override; std::unique_ptr getSymbolById(uint32_t SymbolId) const override; + std::unique_ptr + findSymbolByAddress(uint64_t Address) const override; + std::unique_ptr + findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override; + std::unique_ptr getAllSourceFiles() const override; std::unique_ptr getSourceFilesForCompiland( const PDBSymbolCompiland &Compiland) const override; diff --git a/include/llvm/DebugInfo/PDB/IPDBSession.h b/include/llvm/DebugInfo/PDB/IPDBSession.h index 60d6f62068e..f1debc02bc6 100644 --- a/include/llvm/DebugInfo/PDB/IPDBSession.h +++ b/include/llvm/DebugInfo/PDB/IPDBSession.h @@ -43,6 +43,11 @@ public: return std::unique_ptr(ConcreteSymbol); } + virtual std::unique_ptr + findSymbolByAddress(uint64_t Address) const = 0; + virtual std::unique_ptr + findLineNumbersByAddress(uint64_t Address, uint32_t Length) const = 0; + virtual std::unique_ptr getAllSourceFiles() const = 0; virtual std::unique_ptr getSourceFilesForCompiland(const PDBSymbolCompiland &Compiland) const = 0; diff --git a/include/llvm/DebugInfo/PDB/PDB.h b/include/llvm/DebugInfo/PDB/PDB.h index 67878e9ccf6..5df3be85e38 100644 --- a/include/llvm/DebugInfo/PDB/PDB.h +++ b/include/llvm/DebugInfo/PDB/PDB.h @@ -16,8 +16,11 @@ namespace llvm { class StringRef; -PDB_ErrorCode createPDBReader(PDB_ReaderType Type, StringRef Path, - std::unique_ptr &Session); +PDB_ErrorCode loadDataForPDB(PDB_ReaderType Type, StringRef Path, + std::unique_ptr &Session); + +PDB_ErrorCode loadDataForEXE(PDB_ReaderType Type, StringRef Path, + std::unique_ptr &Session); } #endif diff --git a/include/llvm/DebugInfo/PDB/PDBTypes.h b/include/llvm/DebugInfo/PDB/PDBTypes.h index 686e08f81a1..2d19e792d3d 100644 --- a/include/llvm/DebugInfo/PDB/PDBTypes.h +++ b/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -21,6 +21,7 @@ class PDBSymbol; class IPDBDataStream; template class IPDBEnumChildren; +class IPDBLineNumber; class IPDBRawSymbol; class IPDBSession; class IPDBSourceFile; @@ -28,6 +29,7 @@ class IPDBSourceFile; typedef IPDBEnumChildren IPDBEnumSymbols; typedef IPDBEnumChildren IPDBEnumSourceFiles; typedef IPDBEnumChildren IPDBEnumDataStreams; +typedef IPDBEnumChildren IPDBEnumLineNumbers; class PDBSymbolExe; class PDBSymbolCompiland; @@ -426,7 +428,8 @@ enum class PDB_ErrorCode { InvalidParameter, AlreadyLoaded, UnknownError, - NoMemory + NoMemory, + DebugInfoMismatch }; struct VersionInfo { diff --git a/lib/DebugInfo/PDB/DIA/DIASession.cpp b/lib/DebugInfo/PDB/DIA/DIASession.cpp index 4966bea96f6..e3e3fc05ab3 100644 --- a/lib/DebugInfo/PDB/DIA/DIASession.cpp +++ b/lib/DebugInfo/PDB/DIA/DIASession.cpp @@ -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 &Session) { + CComPtr DiaDataSource; + CComPtr 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(&DiaDataSource)); + if (FAILED(Result)) + return PDB_ErrorCode::NoPdbImpl; + + llvm::SmallVector Path16; + if (!llvm::convertUTF8ToUTF16String(Path, Path16)) + return PDB_ErrorCode::InvalidPath; + + const wchar_t *Path16Str = reinterpret_cast(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 DIASession::getSymbolById(uint32_t SymbolId) const { return PDBSymbol::create(*this, std::move(RawSymbol)); } +std::unique_ptr +DIASession::findSymbolByAddress(uint64_t Address) const { + CComPtr Symbol; + if (S_OK != Session->findSymbolByVA(Address, SymTagNull, &Symbol)) + return nullptr; + auto RawSymbol = llvm::make_unique(*this, Symbol); + return PDBSymbol::create(*this, std::move(RawSymbol)); +} + +std::unique_ptr +DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const { + CComPtr LineNumbers; + if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers)) + return nullptr; + + return llvm::make_unique(LineNumbers); +} + std::unique_ptr DIASession::getAllSourceFiles() const { CComPtr Files; if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files)) diff --git a/lib/DebugInfo/PDB/PDB.cpp b/lib/DebugInfo/PDB/PDB.cpp index a07396d1a17..13201bbaa64 100644 --- a/lib/DebugInfo/PDB/PDB.cpp +++ b/lib/DebugInfo/PDB/PDB.cpp @@ -20,11 +20,20 @@ using namespace llvm; -PDB_ErrorCode llvm::createPDBReader(PDB_ReaderType Type, StringRef Path, - std::unique_ptr &Session) { +PDB_ErrorCode llvm::loadDataForPDB(PDB_ReaderType Type, StringRef Path, + std::unique_ptr &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 &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; +} diff --git a/tools/llvm-pdbdump/llvm-pdbdump.cpp b/tools/llvm-pdbdump/llvm-pdbdump.cpp index 78535ec0be9..597683291ff 100644 --- a/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -101,7 +101,7 @@ cl::opt NoEnumDefs("no-enum-definitions", static void dumpInput(StringRef Path) { std::unique_ptr 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; diff --git a/unittests/DebugInfo/PDB/PDBApiTest.cpp b/unittests/DebugInfo/PDB/PDBApiTest.cpp index 629c5f8bc0e..4f8e95d9078 100644 --- a/unittests/DebugInfo/PDB/PDBApiTest.cpp +++ b/unittests/DebugInfo/PDB/PDBApiTest.cpp @@ -72,6 +72,16 @@ class MockSession : public IPDBSession { getSourceFileById(uint32_t SymbolId) const override { return nullptr; } + + std::unique_ptr + findSymbolByAddress(uint64_t Address) const override { + return nullptr; + } + std::unique_ptr + findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override { + return nullptr; + } + std::unique_ptr getAllSourceFiles() const override { return nullptr; }