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/DIAEnumLineNumbers.h"
13 #include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
14 #include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
15 #include "llvm/DebugInfo/PDB/DIA/DIASession.h"
16 #include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
17 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
18 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
19 #include "llvm/Support/ConvertUTF.h"
20
21 using namespace llvm;
22
23 namespace {}
24
DIASession(CComPtr<IDiaSession> DiaSession)25 DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
26
createFromPdb(StringRef Path,std::unique_ptr<IPDBSession> & Session)27 PDB_ErrorCode DIASession::createFromPdb(StringRef Path,
28 std::unique_ptr<IPDBSession> &Session) {
29 CComPtr<IDiaDataSource> DiaDataSource;
30 CComPtr<IDiaSession> DiaSession;
31
32 // We assume that CoInitializeEx has already been called by the executable.
33 HRESULT Result = ::CoCreateInstance(
34 CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource,
35 reinterpret_cast<LPVOID *>(&DiaDataSource));
36 if (FAILED(Result))
37 return PDB_ErrorCode::NoPdbImpl;
38
39 llvm::SmallVector<UTF16, 128> Path16;
40 if (!llvm::convertUTF8ToUTF16String(Path, Path16))
41 return PDB_ErrorCode::InvalidPath;
42
43 const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
44 if (FAILED(Result = DiaDataSource->loadDataFromPdb(Path16Str))) {
45 if (Result == E_PDB_NOT_FOUND)
46 return PDB_ErrorCode::InvalidPath;
47 else if (Result == E_PDB_FORMAT)
48 return PDB_ErrorCode::InvalidFileFormat;
49 else if (Result == E_INVALIDARG)
50 return PDB_ErrorCode::InvalidParameter;
51 else if (Result == E_UNEXPECTED)
52 return PDB_ErrorCode::AlreadyLoaded;
53 else
54 return PDB_ErrorCode::UnknownError;
55 }
56
57 if (FAILED(Result = DiaDataSource->openSession(&DiaSession))) {
58 if (Result == E_OUTOFMEMORY)
59 return PDB_ErrorCode::NoMemory;
60 else
61 return PDB_ErrorCode::UnknownError;
62 }
63
64 Session.reset(new DIASession(DiaSession));
65 return PDB_ErrorCode::Success;
66 }
67
createFromExe(StringRef Path,std::unique_ptr<IPDBSession> & Session)68 PDB_ErrorCode DIASession::createFromExe(StringRef Path,
69 std::unique_ptr<IPDBSession> &Session) {
70 CComPtr<IDiaDataSource> DiaDataSource;
71 CComPtr<IDiaSession> DiaSession;
72
73 // We assume that CoInitializeEx has already been called by the executable.
74 HRESULT Result = ::CoCreateInstance(
75 CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource,
76 reinterpret_cast<LPVOID *>(&DiaDataSource));
77 if (FAILED(Result))
78 return PDB_ErrorCode::NoPdbImpl;
79
80 llvm::SmallVector<UTF16, 128> Path16;
81 if (!llvm::convertUTF8ToUTF16String(Path, Path16))
82 return PDB_ErrorCode::InvalidPath;
83
84 const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
85 if (FAILED(Result =
86 DiaDataSource->loadDataForExe(Path16Str, nullptr, nullptr))) {
87 if (Result == E_PDB_NOT_FOUND)
88 return PDB_ErrorCode::InvalidPath;
89 else if (Result == E_PDB_FORMAT)
90 return PDB_ErrorCode::InvalidFileFormat;
91 else if (Result == E_PDB_INVALID_SIG || Result == E_PDB_INVALID_AGE)
92 return PDB_ErrorCode::DebugInfoMismatch;
93 else if (Result == E_INVALIDARG)
94 return PDB_ErrorCode::InvalidParameter;
95 else if (Result == E_UNEXPECTED)
96 return PDB_ErrorCode::AlreadyLoaded;
97 else
98 return PDB_ErrorCode::UnknownError;
99 }
100
101 if (FAILED(Result = DiaDataSource->openSession(&DiaSession))) {
102 if (Result == E_OUTOFMEMORY)
103 return PDB_ErrorCode::NoMemory;
104 else
105 return PDB_ErrorCode::UnknownError;
106 }
107
108 Session.reset(new DIASession(DiaSession));
109 return PDB_ErrorCode::Success;
110 }
111
getLoadAddress() const112 uint64_t DIASession::getLoadAddress() const {
113 uint64_t LoadAddress;
114 bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
115 return (success) ? LoadAddress : 0;
116 }
117
setLoadAddress(uint64_t Address)118 void DIASession::setLoadAddress(uint64_t Address) {
119 Session->put_loadAddress(Address);
120 }
121
getGlobalScope() const122 std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const {
123 CComPtr<IDiaSymbol> GlobalScope;
124 if (S_OK != Session->get_globalScope(&GlobalScope))
125 return nullptr;
126
127 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, GlobalScope);
128 auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
129 std::unique_ptr<PDBSymbolExe> ExeSymbol(
130 static_cast<PDBSymbolExe *>(PdbSymbol.release()));
131 return ExeSymbol;
132 }
133
getSymbolById(uint32_t SymbolId) const134 std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const {
135 CComPtr<IDiaSymbol> LocatedSymbol;
136 if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol))
137 return nullptr;
138
139 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, LocatedSymbol);
140 return PDBSymbol::create(*this, std::move(RawSymbol));
141 }
142
143 std::unique_ptr<PDBSymbol>
findSymbolByAddress(uint64_t Address,PDB_SymType Type) const144 DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
145 enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
146
147 CComPtr<IDiaSymbol> Symbol;
148 if (S_OK != Session->findSymbolByVA(Address, EnumVal, &Symbol)) {
149 ULONGLONG LoadAddr = 0;
150 if (S_OK != Session->get_loadAddress(&LoadAddr))
151 return nullptr;
152 DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
153 if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
154 return nullptr;
155 }
156 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
157 return PDBSymbol::create(*this, std::move(RawSymbol));
158 }
159
160 std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbersByAddress(uint64_t Address,uint32_t Length) const161 DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
162 CComPtr<IDiaEnumLineNumbers> LineNumbers;
163 if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers))
164 return nullptr;
165
166 return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
167 }
168
getAllSourceFiles() const169 std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
170 CComPtr<IDiaEnumSourceFiles> Files;
171 if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
172 return nullptr;
173
174 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
175 }
176
getSourceFilesForCompiland(const PDBSymbolCompiland & Compiland) const177 std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland(
178 const PDBSymbolCompiland &Compiland) const {
179 CComPtr<IDiaEnumSourceFiles> Files;
180
181 const DIARawSymbol &RawSymbol =
182 static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
183 if (S_OK !=
184 Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files))
185 return nullptr;
186
187 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
188 }
189
190 std::unique_ptr<IPDBSourceFile>
getSourceFileById(uint32_t FileId) const191 DIASession::getSourceFileById(uint32_t FileId) const {
192 CComPtr<IDiaSourceFile> LocatedFile;
193 if (S_OK != Session->findFileById(FileId, &LocatedFile))
194 return nullptr;
195
196 return llvm::make_unique<DIASourceFile>(*this, LocatedFile);
197 }
198
getDebugStreams() const199 std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
200 CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
201 if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
202 return nullptr;
203
204 return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator);
205 }
206