From e09af84db50570b56379bfef95d37ceaf6674c16 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Sat, 28 Feb 2015 20:23:18 +0000 Subject: [PATCH] [llvm-pdbdump] Better error handling. Previously it was impossible to distinguish between "There is no PDB implementation for this platform" and "I tried to load the PDB, but couldn't find the file", making it hard to figure out if you built llvm-pdbdump incorrectly or if you just mistyped a file name. This patch adds proper error handling so that we can know exactly what went wrong. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230868 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DebugInfo/PDB/DIA/DIASession.h | 3 +- include/llvm/DebugInfo/PDB/PDB.h | 4 +- include/llvm/DebugInfo/PDB/PDBTypes.h | 11 ++++++ lib/DebugInfo/PDB/DIA/DIASession.cpp | 43 ++++++++++++++------- lib/DebugInfo/PDB/PDB.cpp | 8 ++-- tools/llvm-pdbdump/llvm-pdbdump.cpp | 25 +++++++++--- 6 files changed, 69 insertions(+), 25 deletions(-) diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/include/llvm/DebugInfo/PDB/DIA/DIASession.h index 141b9b0d989..6c72c3e6fc6 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIASession.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIASession.h @@ -19,7 +19,8 @@ class DIASession : public IPDBSession { public: explicit DIASession(CComPtr DiaSession); - static DIASession *createFromPdb(StringRef Path); + static PDB_ErrorCode createFromPdb(StringRef Path, + std::unique_ptr &Session); uint64_t getLoadAddress() const override; void setLoadAddress(uint64_t Address) override; diff --git a/include/llvm/DebugInfo/PDB/PDB.h b/include/llvm/DebugInfo/PDB/PDB.h index 7193eef1b3c..67878e9ccf6 100644 --- a/include/llvm/DebugInfo/PDB/PDB.h +++ b/include/llvm/DebugInfo/PDB/PDB.h @@ -16,8 +16,8 @@ namespace llvm { class StringRef; -std::unique_ptr createPDBReader(PDB_ReaderType Type, - StringRef Path); +PDB_ErrorCode createPDBReader(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 75b64750129..2bee60860b0 100644 --- a/include/llvm/DebugInfo/PDB/PDBTypes.h +++ b/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -418,6 +418,17 @@ enum class PDB_RegisterId { enum class PDB_MemberAccess { Private = 1, Protected = 2, Public = 3 }; +enum class PDB_ErrorCode { + Success, + NoPdbImpl, + InvalidPath, + InvalidFileFormat, + InvalidParameter, + AlreadyLoaded, + UnknownError, + NoMemory +}; + struct VersionInfo { uint32_t Major; uint32_t Minor; diff --git a/lib/DebugInfo/PDB/DIA/DIASession.cpp b/lib/DebugInfo/PDB/DIA/DIASession.cpp index 24791f2afa1..4966bea96f6 100644 --- a/lib/DebugInfo/PDB/DIA/DIASession.cpp +++ b/lib/DebugInfo/PDB/DIA/DIASession.cpp @@ -23,28 +23,45 @@ namespace {} DIASession::DIASession(CComPtr DiaSession) : Session(DiaSession) {} -DIASession *DIASession::createFromPdb(StringRef Path) { - CComPtr DataSource; - CComPtr Session; +PDB_ErrorCode DIASession::createFromPdb(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(&DataSource)); + HRESULT Result = ::CoCreateInstance( + CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource, + reinterpret_cast(&DiaDataSource)); if (FAILED(Result)) - return nullptr; + return PDB_ErrorCode::NoPdbImpl; llvm::SmallVector Path16; if (!llvm::convertUTF8ToUTF16String(Path, Path16)) - return nullptr; + return PDB_ErrorCode::InvalidPath; const wchar_t *Path16Str = reinterpret_cast(Path16.data()); - if (FAILED(DataSource->loadDataFromPdb(Path16Str))) - return nullptr; + if (FAILED(Result = DiaDataSource->loadDataFromPdb(Path16Str))) { + if (Result == E_PDB_NOT_FOUND) + return PDB_ErrorCode::InvalidPath; + else if (Result == E_PDB_FORMAT) + return PDB_ErrorCode::InvalidFileFormat; + 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(DataSource->openSession(&Session))) - return nullptr; - return new DIASession(Session); + 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 { diff --git a/lib/DebugInfo/PDB/PDB.cpp b/lib/DebugInfo/PDB/PDB.cpp index aa84c288287..a07396d1a17 100644 --- a/lib/DebugInfo/PDB/PDB.cpp +++ b/lib/DebugInfo/PDB/PDB.cpp @@ -20,11 +20,11 @@ using namespace llvm; -std::unique_ptr llvm::createPDBReader(PDB_ReaderType Type, - StringRef Path) { +PDB_ErrorCode llvm::createPDBReader(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 std::unique_ptr(DIASession::createFromPdb(Path)); + return DIASession::createFromPdb(Path, Session); #endif - return nullptr; + return PDB_ErrorCode::NoPdbImpl; } diff --git a/tools/llvm-pdbdump/llvm-pdbdump.cpp b/tools/llvm-pdbdump/llvm-pdbdump.cpp index 5bc33d06e38..98b26144e34 100644 --- a/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -66,11 +66,26 @@ cl::opt ClassDefs("class-definitions", } static void dumpInput(StringRef Path) { - std::unique_ptr Session( - llvm::createPDBReader(PDB_ReaderType::DIA, Path)); - if (!Session) { - outs() << "Unable to create PDB reader. Check that a valid implementation"; - outs() << " is available for your platform."; + std::unique_ptr Session; + PDB_ErrorCode Error = + llvm::createPDBReader(PDB_ReaderType::DIA, Path, Session); + switch (Error) { + case PDB_ErrorCode::Success: + break; + case PDB_ErrorCode::NoPdbImpl: + outs() << "Reading PDBs is not supported on this platform.\n"; + return; + case PDB_ErrorCode::InvalidPath: + outs() << "Unable to load PDB at '" << Path + << "'. Check that the file exists and is readable.\n"; + return; + case PDB_ErrorCode::InvalidFileFormat: + outs() << "Unable to load PDB at '" << Path + << "'. The file has an unrecognized format.\n"; + return; + default: + outs() << "Unable to load PDB at '" << Path + << "'. An unknown error occured.\n"; return; }