[llvm-pdbdump] Better error handling.
[oota-llvm.git] / lib / DebugInfo / PDB / DIA / DIASession.cpp
1 //===- DIASession.cpp - DIA implementation of IPDBSession -------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
12 #include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
13 #include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
14 #include "llvm/DebugInfo/PDB/DIA/DIASession.h"
15 #include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
16 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
17 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
18 #include "llvm/Support/ConvertUTF.h"
19
20 using namespace llvm;
21
22 namespace {}
23
24 DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
25
26 PDB_ErrorCode DIASession::createFromPdb(StringRef Path,
27                                         std::unique_ptr<IPDBSession> &Session) {
28   CComPtr<IDiaDataSource> DiaDataSource;
29   CComPtr<IDiaSession> DiaSession;
30
31   // We assume that CoInitializeEx has already been called by the executable.
32   HRESULT Result = ::CoCreateInstance(
33       CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource,
34       reinterpret_cast<LPVOID *>(&DiaDataSource));
35   if (FAILED(Result))
36     return PDB_ErrorCode::NoPdbImpl;
37
38   llvm::SmallVector<UTF16, 128> Path16;
39   if (!llvm::convertUTF8ToUTF16String(Path, Path16))
40     return PDB_ErrorCode::InvalidPath;
41
42   const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
43   if (FAILED(Result = DiaDataSource->loadDataFromPdb(Path16Str))) {
44     if (Result == E_PDB_NOT_FOUND)
45       return PDB_ErrorCode::InvalidPath;
46     else if (Result == E_PDB_FORMAT)
47       return PDB_ErrorCode::InvalidFileFormat;
48     else if (Result == E_INVALIDARG)
49       return PDB_ErrorCode::InvalidParameter;
50     else if (Result == E_UNEXPECTED)
51       return PDB_ErrorCode::AlreadyLoaded;
52     else
53       return PDB_ErrorCode::UnknownError;
54   }
55
56   if (FAILED(Result = DiaDataSource->openSession(&DiaSession))) {
57     if (Result == E_OUTOFMEMORY)
58       return PDB_ErrorCode::NoMemory;
59     else
60       return PDB_ErrorCode::UnknownError;
61   }
62
63   Session.reset(new DIASession(DiaSession));
64   return PDB_ErrorCode::Success;
65 }
66
67 uint64_t DIASession::getLoadAddress() const {
68   uint64_t LoadAddress;
69   bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
70   return (success) ? LoadAddress : 0;
71 }
72
73 void DIASession::setLoadAddress(uint64_t Address) {
74   Session->put_loadAddress(Address);
75 }
76
77 std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const {
78   CComPtr<IDiaSymbol> GlobalScope;
79   if (S_OK != Session->get_globalScope(&GlobalScope))
80     return nullptr;
81
82   auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, GlobalScope);
83   auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
84   std::unique_ptr<PDBSymbolExe> ExeSymbol(
85       static_cast<PDBSymbolExe *>(PdbSymbol.release()));
86   return ExeSymbol;
87 }
88
89 std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const {
90   CComPtr<IDiaSymbol> LocatedSymbol;
91   if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol))
92     return nullptr;
93
94   auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, LocatedSymbol);
95   return PDBSymbol::create(*this, std::move(RawSymbol));
96 }
97
98 std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
99   CComPtr<IDiaEnumSourceFiles> Files;
100   if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
101     return nullptr;
102
103   return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
104 }
105
106 std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland(
107     const PDBSymbolCompiland &Compiland) const {
108   CComPtr<IDiaEnumSourceFiles> Files;
109
110   const DIARawSymbol &RawSymbol =
111       static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
112   if (S_OK !=
113       Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files))
114     return nullptr;
115
116   return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
117 }
118
119 std::unique_ptr<IPDBSourceFile>
120 DIASession::getSourceFileById(uint32_t FileId) const {
121   CComPtr<IDiaSourceFile> LocatedFile;
122   if (S_OK != Session->findFileById(FileId, &LocatedFile))
123     return nullptr;
124
125   return llvm::make_unique<DIASourceFile>(*this, LocatedFile);
126 }
127
128 std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
129   CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
130   if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
131     return nullptr;
132
133   return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator);
134 }