[llvm-pdbdump] Better error handling.
authorZachary Turner <zturner@google.com>
Sat, 28 Feb 2015 20:23:18 +0000 (20:23 +0000)
committerZachary Turner <zturner@google.com>
Sat, 28 Feb 2015 20:23:18 +0000 (20:23 +0000)
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
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

index 141b9b0d98987f65a3206a1c374bef1415e11df0..6c72c3e6fc60dca280e7e09ac734fe15104ac8da 100644 (file)
@@ -19,7 +19,8 @@ class DIASession : public IPDBSession {
 public:
   explicit DIASession(CComPtr<IDiaSession> DiaSession);
 
-  static DIASession *createFromPdb(StringRef Path);
+  static PDB_ErrorCode createFromPdb(StringRef Path,
+                                     std::unique_ptr<IPDBSession> &Session);
 
   uint64_t getLoadAddress() const override;
   void setLoadAddress(uint64_t Address) override;
index 7193eef1b3c3d21fc28315d2f1eebc38236609a4..67878e9ccf600707636d0f6d3accb9eb2d4ef2bf 100644 (file)
@@ -16,8 +16,8 @@
 namespace llvm {
 class StringRef;
 
-std::unique_ptr<IPDBSession> createPDBReader(PDB_ReaderType Type,
-                                             StringRef Path);
+PDB_ErrorCode createPDBReader(PDB_ReaderType Type, StringRef Path,
+                              std::unique_ptr<IPDBSession> &Session);
 }
 
 #endif
index 75b64750129dc5a14c705590cae2e7ce634689dc..2bee60860b0ad1aeaa2e28d5d230d4eccd67a05e 100644 (file)
@@ -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;
index 24791f2afa11b0915197e43f8f3b6346db1af4bd..4966bea96f6c208baaae369ae6c872edbe693505 100644 (file)
@@ -23,28 +23,45 @@ namespace {}
 
 DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
 
-DIASession *DIASession::createFromPdb(StringRef Path) {
-  CComPtr<IDiaDataSource> DataSource;
-  CComPtr<IDiaSession> Session;
+PDB_ErrorCode DIASession::createFromPdb(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 *>(&DataSource));
+  HRESULT Result = ::CoCreateInstance(
+      CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource,
+      reinterpret_cast<LPVOID *>(&DiaDataSource));
   if (FAILED(Result))
-    return nullptr;
+    return PDB_ErrorCode::NoPdbImpl;
 
   llvm::SmallVector<UTF16, 128> Path16;
   if (!llvm::convertUTF8ToUTF16String(Path, Path16))
-    return nullptr;
+    return PDB_ErrorCode::InvalidPath;
 
   const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
-  if (FAILED(DataSource->loadDataFromPdb(Path16Str)))
-    return nullptr;
-
-  if (FAILED(DataSource->openSession(&Session)))
-    return nullptr;
-  return new DIASession(Session);
+  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(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 {
index aa84c28828769193db2a0742f763203fd19626f5..a07396d1a175503cfbdf492d50710af7bff73611 100644 (file)
 
 using namespace llvm;
 
-std::unique_ptr<IPDBSession> llvm::createPDBReader(PDB_ReaderType Type,
-                                                   StringRef Path) {
+PDB_ErrorCode llvm::createPDBReader(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 std::unique_ptr<DIASession>(DIASession::createFromPdb(Path));
+  return DIASession::createFromPdb(Path, Session);
 #endif
-  return nullptr;
+  return PDB_ErrorCode::NoPdbImpl;
 }
index 5bc33d06e3814312e1500a92b442e393ac5ee350..98b26144e3489703d3ae61346198bd4393e1ebdf 100644 (file)
@@ -66,11 +66,26 @@ cl::opt<bool> ClassDefs("class-definitions",
 }
 
 static void dumpInput(StringRef Path) {
-  std::unique_ptr<IPDBSession> 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<IPDBSession> 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;
   }