1*cffff26bSZachary Turner //===- DIASession.cpp - DIA implementation of IPDBSession -------*- C++ -*-===//
2*cffff26bSZachary Turner //
3*cffff26bSZachary Turner //                     The LLVM Compiler Infrastructure
4*cffff26bSZachary Turner //
5*cffff26bSZachary Turner // This file is distributed under the University of Illinois Open Source
6*cffff26bSZachary Turner // License. See LICENSE.TXT for details.
7*cffff26bSZachary Turner //
8*cffff26bSZachary Turner //===----------------------------------------------------------------------===//
9*cffff26bSZachary Turner 
10*cffff26bSZachary Turner #include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
11*cffff26bSZachary Turner #include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
12*cffff26bSZachary Turner #include "llvm/DebugInfo/PDB/DIA/DIASession.h"
13*cffff26bSZachary Turner #include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
14*cffff26bSZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
15*cffff26bSZachary Turner #include "llvm/Support/ConvertUTF.h"
16*cffff26bSZachary Turner 
17*cffff26bSZachary Turner using namespace llvm;
18*cffff26bSZachary Turner 
19*cffff26bSZachary Turner namespace {}
20*cffff26bSZachary Turner 
21*cffff26bSZachary Turner DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
22*cffff26bSZachary Turner 
23*cffff26bSZachary Turner DIASession *DIASession::createFromPdb(StringRef Path) {
24*cffff26bSZachary Turner   CComPtr<IDiaDataSource> DataSource;
25*cffff26bSZachary Turner   CComPtr<IDiaSession> Session;
26*cffff26bSZachary Turner 
27*cffff26bSZachary Turner   // We assume that CoInitializeEx has already been called by the executable.
28*cffff26bSZachary Turner   HRESULT Result = ::CoCreateInstance(CLSID_DiaSource, nullptr,
29*cffff26bSZachary Turner                                       CLSCTX_INPROC_SERVER, IID_IDiaDataSource,
30*cffff26bSZachary Turner                                       reinterpret_cast<LPVOID *>(&DataSource));
31*cffff26bSZachary Turner   if (FAILED(Result))
32*cffff26bSZachary Turner     return nullptr;
33*cffff26bSZachary Turner 
34*cffff26bSZachary Turner   llvm::SmallVector<UTF16, 128> Path16;
35*cffff26bSZachary Turner   if (!llvm::convertUTF8ToUTF16String(Path, Path16))
36*cffff26bSZachary Turner     return nullptr;
37*cffff26bSZachary Turner 
38*cffff26bSZachary Turner   const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
39*cffff26bSZachary Turner   if (FAILED(DataSource->loadDataFromPdb(Path16Str)))
40*cffff26bSZachary Turner     return nullptr;
41*cffff26bSZachary Turner 
42*cffff26bSZachary Turner   if (FAILED(DataSource->openSession(&Session)))
43*cffff26bSZachary Turner     return nullptr;
44*cffff26bSZachary Turner   return new DIASession(Session);
45*cffff26bSZachary Turner }
46*cffff26bSZachary Turner 
47*cffff26bSZachary Turner uint64_t DIASession::getLoadAddress() const {
48*cffff26bSZachary Turner   uint64_t LoadAddress;
49*cffff26bSZachary Turner   bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
50*cffff26bSZachary Turner   return (success) ? LoadAddress : 0;
51*cffff26bSZachary Turner }
52*cffff26bSZachary Turner 
53*cffff26bSZachary Turner void DIASession::setLoadAddress(uint64_t Address) {
54*cffff26bSZachary Turner   Session->put_loadAddress(Address);
55*cffff26bSZachary Turner }
56*cffff26bSZachary Turner 
57*cffff26bSZachary Turner std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const {
58*cffff26bSZachary Turner   CComPtr<IDiaSymbol> GlobalScope;
59*cffff26bSZachary Turner   if (S_OK != Session->get_globalScope(&GlobalScope))
60*cffff26bSZachary Turner     return nullptr;
61*cffff26bSZachary Turner 
62*cffff26bSZachary Turner   auto RawSymbol = std::make_unique<DIARawSymbol>(*this, GlobalScope);
63*cffff26bSZachary Turner   auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
64*cffff26bSZachary Turner   std::unique_ptr<PDBSymbolExe> ExeSymbol(
65*cffff26bSZachary Turner       static_cast<PDBSymbolExe *>(PdbSymbol.release()));
66*cffff26bSZachary Turner   return ExeSymbol;
67*cffff26bSZachary Turner }
68*cffff26bSZachary Turner 
69*cffff26bSZachary Turner std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const {
70*cffff26bSZachary Turner   CComPtr<IDiaSymbol> LocatedSymbol;
71*cffff26bSZachary Turner   if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol))
72*cffff26bSZachary Turner     return nullptr;
73*cffff26bSZachary Turner 
74*cffff26bSZachary Turner   auto RawSymbol = std::make_unique<DIARawSymbol>(*this, LocatedSymbol);
75*cffff26bSZachary Turner   return PDBSymbol::create(*this, std::move(RawSymbol));
76*cffff26bSZachary Turner }
77*cffff26bSZachary Turner 
78*cffff26bSZachary Turner std::unique_ptr<IPDBSourceFile>
79*cffff26bSZachary Turner DIASession::getSourceFileById(uint32_t FileId) const {
80*cffff26bSZachary Turner   CComPtr<IDiaSourceFile> LocatedFile;
81*cffff26bSZachary Turner   if (S_OK != Session->findFileById(FileId, &LocatedFile))
82*cffff26bSZachary Turner     return nullptr;
83*cffff26bSZachary Turner 
84*cffff26bSZachary Turner   return std::make_unique<DIASourceFile>(*this, LocatedFile);
85*cffff26bSZachary Turner }
86*cffff26bSZachary Turner 
87*cffff26bSZachary Turner std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
88*cffff26bSZachary Turner   CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
89*cffff26bSZachary Turner   if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
90*cffff26bSZachary Turner     return nullptr;
91*cffff26bSZachary Turner 
92*cffff26bSZachary Turner   return std::unique_ptr<IPDBEnumDataStreams>(
93*cffff26bSZachary Turner       new DIAEnumDebugStreams(DiaEnumerator));
94*cffff26bSZachary Turner }
95