[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
This commit is contained in:
Zachary Turner 2015-02-28 20:23:18 +00:00
parent ce770dda2c
commit e09af84db5
6 changed files with 69 additions and 25 deletions

View 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;

View 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

View 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;

View 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(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 {

View File

@ -20,11 +20,11 @@
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;
}

View 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;
}