blob: 60894bbd0ce379d9d683353b39c5d6579b74278a [file] [log] [blame]
Zachary Turnercffff262015-02-10 21:17:52 +00001//===- 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
Zachary Turnerbe6d1e42015-02-10 23:46:48 +000010#include "llvm/ADT/STLExtras.h"
Zachary Turnercffff262015-02-10 21:17:52 +000011#include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
Zachary Turner4b083542015-04-17 22:40:36 +000012#include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
Zachary Turnera5549172015-02-10 22:43:25 +000013#include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
Zachary Turnercffff262015-02-10 21:17:52 +000014#include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
15#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
16#include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
Chandler Carruth71f308a2015-02-13 09:09:03 +000017#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
18#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
Zachary Turnercffff262015-02-10 21:17:52 +000019#include "llvm/Support/ConvertUTF.h"
20
Nico Weber73853ab2016-04-01 22:21:51 +000021#include <diacreate.h>
22
Zachary Turnercffff262015-02-10 21:17:52 +000023using namespace llvm;
24
Nico Weber73853ab2016-04-01 22:21:51 +000025namespace {
26
27bool LoadDIA(CComPtr<IDiaDataSource>& DiaDataSource) {
28 if (SUCCEEDED(CoCreateInstance(CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER,
29 IID_IDiaDataSource,
30 reinterpret_cast<LPVOID *>(&DiaDataSource))))
31 return true;
32
33 // If the CoCreateInstance call above failed, msdia*.dll is not registered.
34 // Try loading the DLL corresponding to the #included DIA SDK.
35#if !defined(_MSC_VER)
36 return false;
37#else
38 const wchar_t *msdia_dll = nullptr;
39#if _MSC_VER == 1900
40 msdia_dll = L"msdia140.dll"; // VS2015
41#elif _MSC_VER == 1800
42 msdia_dll = L"msdia120.dll"; // VS2013
43#else
44#error "Unknown Visual Studio version."
45#endif
46 return msdia_dll &&
47 SUCCEEDED(NoRegCoCreate(msdia_dll, CLSID_DiaSource, IID_IDiaDataSource,
48 reinterpret_cast<LPVOID *>(&DiaDataSource)));
49#endif
50}
51
52}
Zachary Turnercffff262015-02-10 21:17:52 +000053
54DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
55
Zachary Turnerccf04152015-02-28 20:23:18 +000056PDB_ErrorCode DIASession::createFromPdb(StringRef Path,
57 std::unique_ptr<IPDBSession> &Session) {
58 CComPtr<IDiaDataSource> DiaDataSource;
59 CComPtr<IDiaSession> DiaSession;
Zachary Turnercffff262015-02-10 21:17:52 +000060
61 // We assume that CoInitializeEx has already been called by the executable.
Nico Weber73853ab2016-04-01 22:21:51 +000062 if (!LoadDIA(DiaDataSource))
Zachary Turnerccf04152015-02-28 20:23:18 +000063 return PDB_ErrorCode::NoPdbImpl;
Zachary Turnercffff262015-02-10 21:17:52 +000064
65 llvm::SmallVector<UTF16, 128> Path16;
66 if (!llvm::convertUTF8ToUTF16String(Path, Path16))
Zachary Turnerccf04152015-02-28 20:23:18 +000067 return PDB_ErrorCode::InvalidPath;
Zachary Turnercffff262015-02-10 21:17:52 +000068
69 const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
Nico Weber73853ab2016-04-01 22:21:51 +000070 HRESULT Result;
Zachary Turnerccf04152015-02-28 20:23:18 +000071 if (FAILED(Result = DiaDataSource->loadDataFromPdb(Path16Str))) {
72 if (Result == E_PDB_NOT_FOUND)
73 return PDB_ErrorCode::InvalidPath;
74 else if (Result == E_PDB_FORMAT)
75 return PDB_ErrorCode::InvalidFileFormat;
76 else if (Result == E_INVALIDARG)
77 return PDB_ErrorCode::InvalidParameter;
78 else if (Result == E_UNEXPECTED)
79 return PDB_ErrorCode::AlreadyLoaded;
80 else
81 return PDB_ErrorCode::UnknownError;
82 }
Zachary Turnercffff262015-02-10 21:17:52 +000083
Zachary Turnerccf04152015-02-28 20:23:18 +000084 if (FAILED(Result = DiaDataSource->openSession(&DiaSession))) {
85 if (Result == E_OUTOFMEMORY)
86 return PDB_ErrorCode::NoMemory;
87 else
88 return PDB_ErrorCode::UnknownError;
89 }
90
91 Session.reset(new DIASession(DiaSession));
92 return PDB_ErrorCode::Success;
Zachary Turnercffff262015-02-10 21:17:52 +000093}
94
Zachary Turner4b083542015-04-17 22:40:36 +000095PDB_ErrorCode DIASession::createFromExe(StringRef Path,
96 std::unique_ptr<IPDBSession> &Session) {
97 CComPtr<IDiaDataSource> DiaDataSource;
98 CComPtr<IDiaSession> DiaSession;
99
100 // We assume that CoInitializeEx has already been called by the executable.
Nico Weber73853ab2016-04-01 22:21:51 +0000101 if (!LoadDIA(DiaDataSource))
Zachary Turner4b083542015-04-17 22:40:36 +0000102 return PDB_ErrorCode::NoPdbImpl;
103
104 llvm::SmallVector<UTF16, 128> Path16;
105 if (!llvm::convertUTF8ToUTF16String(Path, Path16))
106 return PDB_ErrorCode::InvalidPath;
107
108 const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
Nico Weber73853ab2016-04-01 22:21:51 +0000109 HRESULT Result;
Zachary Turner4b083542015-04-17 22:40:36 +0000110 if (FAILED(Result =
111 DiaDataSource->loadDataForExe(Path16Str, nullptr, nullptr))) {
112 if (Result == E_PDB_NOT_FOUND)
113 return PDB_ErrorCode::InvalidPath;
114 else if (Result == E_PDB_FORMAT)
115 return PDB_ErrorCode::InvalidFileFormat;
116 else if (Result == E_PDB_INVALID_SIG || Result == E_PDB_INVALID_AGE)
117 return PDB_ErrorCode::DebugInfoMismatch;
118 else if (Result == E_INVALIDARG)
119 return PDB_ErrorCode::InvalidParameter;
120 else if (Result == E_UNEXPECTED)
121 return PDB_ErrorCode::AlreadyLoaded;
122 else
123 return PDB_ErrorCode::UnknownError;
124 }
125
126 if (FAILED(Result = DiaDataSource->openSession(&DiaSession))) {
127 if (Result == E_OUTOFMEMORY)
128 return PDB_ErrorCode::NoMemory;
129 else
130 return PDB_ErrorCode::UnknownError;
131 }
132
133 Session.reset(new DIASession(DiaSession));
134 return PDB_ErrorCode::Success;
135}
136
Zachary Turnercffff262015-02-10 21:17:52 +0000137uint64_t DIASession::getLoadAddress() const {
138 uint64_t LoadAddress;
139 bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
140 return (success) ? LoadAddress : 0;
141}
142
143void DIASession::setLoadAddress(uint64_t Address) {
144 Session->put_loadAddress(Address);
145}
146
147std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const {
148 CComPtr<IDiaSymbol> GlobalScope;
149 if (S_OK != Session->get_globalScope(&GlobalScope))
150 return nullptr;
151
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000152 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, GlobalScope);
Zachary Turnercffff262015-02-10 21:17:52 +0000153 auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
154 std::unique_ptr<PDBSymbolExe> ExeSymbol(
155 static_cast<PDBSymbolExe *>(PdbSymbol.release()));
156 return ExeSymbol;
157}
158
159std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const {
160 CComPtr<IDiaSymbol> LocatedSymbol;
161 if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol))
162 return nullptr;
163
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000164 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, LocatedSymbol);
Zachary Turnercffff262015-02-10 21:17:52 +0000165 return PDBSymbol::create(*this, std::move(RawSymbol));
166}
167
Zachary Turner4b083542015-04-17 22:40:36 +0000168std::unique_ptr<PDBSymbol>
Zachary Turnere5cb2692015-05-01 20:24:26 +0000169DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
170 enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
171
Zachary Turner4b083542015-04-17 22:40:36 +0000172 CComPtr<IDiaSymbol> Symbol;
Zachary Turnere5cb2692015-05-01 20:24:26 +0000173 if (S_OK != Session->findSymbolByVA(Address, EnumVal, &Symbol)) {
174 ULONGLONG LoadAddr = 0;
175 if (S_OK != Session->get_loadAddress(&LoadAddr))
176 return nullptr;
177 DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
178 if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
179 return nullptr;
180 }
Zachary Turner4b083542015-04-17 22:40:36 +0000181 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
182 return PDBSymbol::create(*this, std::move(RawSymbol));
183}
184
185std::unique_ptr<IPDBEnumLineNumbers>
Zachary Turner43ec3af2016-02-18 18:47:29 +0000186DIASession::findLineNumbers(const PDBSymbolCompiland &Compiland,
187 const IPDBSourceFile &File) const {
188 const DIARawSymbol &RawCompiland =
189 static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
190 const DIASourceFile &RawFile = static_cast<const DIASourceFile &>(File);
191
192 CComPtr<IDiaEnumLineNumbers> LineNumbers;
193 if (S_OK !=
194 Session->findLines(RawCompiland.getDiaSymbol(), RawFile.getDiaFile(),
195 &LineNumbers))
196 return nullptr;
197
198 return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
199}
200
201std::unique_ptr<IPDBEnumLineNumbers>
Zachary Turner4b083542015-04-17 22:40:36 +0000202DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
203 CComPtr<IDiaEnumLineNumbers> LineNumbers;
204 if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers))
205 return nullptr;
206
207 return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
208}
209
Zachary Turner43ec3af2016-02-18 18:47:29 +0000210std::unique_ptr<IPDBEnumSourceFiles>
211DIASession::findSourceFiles(const PDBSymbolCompiland *Compiland,
212 llvm::StringRef Pattern,
213 PDB_NameSearchFlags Flags) const {
214 IDiaSymbol *DiaCompiland = nullptr;
215 CComBSTR Utf16Pattern;
216 if (!Pattern.empty())
217 Utf16Pattern = CComBSTR(Pattern.data());
218
219 if (Compiland)
220 DiaCompiland = static_cast<const DIARawSymbol &>(Compiland->getRawSymbol())
221 .getDiaSymbol();
222
223 Flags = static_cast<PDB_NameSearchFlags>(
224 Flags | PDB_NameSearchFlags::NS_FileNameExtMatch);
225 CComPtr<IDiaEnumSourceFiles> SourceFiles;
226 if (S_OK !=
227 Session->findFile(DiaCompiland, Utf16Pattern.m_str, Flags, &SourceFiles))
228 return nullptr;
229 return llvm::make_unique<DIAEnumSourceFiles>(*this, SourceFiles);
230}
231
232std::unique_ptr<IPDBSourceFile>
233DIASession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
234 llvm::StringRef Pattern,
235 PDB_NameSearchFlags Flags) const {
236 auto SourceFiles = findSourceFiles(Compiland, Pattern, Flags);
237 if (!SourceFiles || SourceFiles->getChildCount() == 0)
238 return nullptr;
239 return SourceFiles->getNext();
240}
241
242std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
243DIASession::findCompilandsForSourceFile(llvm::StringRef Pattern,
244 PDB_NameSearchFlags Flags) const {
245 auto File = findOneSourceFile(nullptr, Pattern, Flags);
246 if (!File)
247 return nullptr;
248 return File->getCompilands();
249}
250
251std::unique_ptr<PDBSymbolCompiland>
252DIASession::findOneCompilandForSourceFile(llvm::StringRef Pattern,
253 PDB_NameSearchFlags Flags) const {
254 auto Compilands = findCompilandsForSourceFile(Pattern, Flags);
255 if (!Compilands || Compilands->getChildCount() == 0)
256 return nullptr;
257 return Compilands->getNext();
258}
259
Zachary Turnera5549172015-02-10 22:43:25 +0000260std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
261 CComPtr<IDiaEnumSourceFiles> Files;
262 if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
263 return nullptr;
264
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000265 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
Zachary Turnera5549172015-02-10 22:43:25 +0000266}
267
268std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland(
269 const PDBSymbolCompiland &Compiland) const {
270 CComPtr<IDiaEnumSourceFiles> Files;
271
272 const DIARawSymbol &RawSymbol =
273 static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
274 if (S_OK !=
275 Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files))
276 return nullptr;
277
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000278 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
Zachary Turnera5549172015-02-10 22:43:25 +0000279}
280
Zachary Turnercffff262015-02-10 21:17:52 +0000281std::unique_ptr<IPDBSourceFile>
282DIASession::getSourceFileById(uint32_t FileId) const {
283 CComPtr<IDiaSourceFile> LocatedFile;
284 if (S_OK != Session->findFileById(FileId, &LocatedFile))
285 return nullptr;
286
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000287 return llvm::make_unique<DIASourceFile>(*this, LocatedFile);
Zachary Turnercffff262015-02-10 21:17:52 +0000288}
289
290std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
291 CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
292 if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
293 return nullptr;
294
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000295 return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator);
Zachary Turnercffff262015-02-10 21:17:52 +0000296}