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