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
DIASession(CComPtr<IDiaSession> DiaSession)24 DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
25
createFromPdb(StringRef Path,std::unique_ptr<IPDBSession> & Session)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
getLoadAddress() const67 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
setLoadAddress(uint64_t Address)73 void DIASession::setLoadAddress(uint64_t Address) {
74 Session->put_loadAddress(Address);
75 }
76
getGlobalScope() const77 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
getSymbolById(uint32_t SymbolId) const89 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
getAllSourceFiles() const98 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
getSourceFilesForCompiland(const PDBSymbolCompiland & Compiland) const106 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>
getSourceFileById(uint32_t FileId) const120 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
getDebugStreams() const128 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 }
135