blob: 7077bda4a534795c9492bef4c021efaac1700d56 [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//===----------------------------------------------------------------------===//
Zachary Turner819e77d2016-05-06 20:51:57 +00009#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
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 Turner819e77d2016-05-06 20:51:57 +000014#include "llvm/DebugInfo/PDB/DIA/DIAError.h"
Zachary Turnercffff262015-02-10 21:17:52 +000015#include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
Zachary Turnercffff262015-02-10 21:17:52 +000016#include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
Zachary Turner819e77d2016-05-06 20:51:57 +000017#include "llvm/DebugInfo/PDB/DIA/DIASupport.h"
18#include "llvm/DebugInfo/PDB/GenericError.h"
19#include "llvm/DebugInfo/PDB/PDB.h"
Chandler Carruth71f308a2015-02-13 09:09:03 +000020#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
21#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
Zachary Turnercffff262015-02-10 21:17:52 +000022#include "llvm/Support/ConvertUTF.h"
Zachary Turner38380322016-10-19 16:42:20 +000023#include "llvm/Support/Format.h"
24#include "llvm/Support/raw_ostream.h"
Zachary Turnercffff262015-02-10 21:17:52 +000025
26using namespace llvm;
Zachary Turnerec28fc32016-05-04 20:32:13 +000027using namespace llvm::pdb;
Zachary Turnercffff262015-02-10 21:17:52 +000028
Zachary Turner38380322016-10-19 16:42:20 +000029static Error ErrorFromHResult(HRESULT Result, StringRef Context) {
Zachary Turner819e77d2016-05-06 20:51:57 +000030 switch (Result) {
31 case E_PDB_NOT_FOUND:
Zachary Turner38380322016-10-19 16:42:20 +000032 return make_error<GenericError>(generic_error_code::invalid_path, Context);
Zachary Turner819e77d2016-05-06 20:51:57 +000033 case E_PDB_FORMAT:
Zachary Turner38380322016-10-19 16:42:20 +000034 return make_error<DIAError>(dia_error_code::invalid_file_format, Context);
Zachary Turner819e77d2016-05-06 20:51:57 +000035 case E_INVALIDARG:
Zachary Turner38380322016-10-19 16:42:20 +000036 return make_error<DIAError>(dia_error_code::invalid_parameter, Context);
Zachary Turner819e77d2016-05-06 20:51:57 +000037 case E_UNEXPECTED:
Zachary Turner38380322016-10-19 16:42:20 +000038 return make_error<DIAError>(dia_error_code::already_loaded, Context);
Zachary Turner819e77d2016-05-06 20:51:57 +000039 case E_PDB_INVALID_SIG:
40 case E_PDB_INVALID_AGE:
Zachary Turner38380322016-10-19 16:42:20 +000041 return make_error<DIAError>(dia_error_code::debug_info_mismatch, Context);
42 default: {
43 std::string S;
44 raw_string_ostream OS(S);
45 OS << "HRESULT: " << format_hex(static_cast<DWORD>(Result), 10, true)
46 << ": " << Context;
47 return make_error<DIAError>(dia_error_code::unspecified, OS.str());
48 }
Zachary Turner819e77d2016-05-06 20:51:57 +000049 }
50}
51
Reid Klecknerfb58be82016-10-12 21:51:14 +000052static Error LoadDIA(CComPtr<IDiaDataSource> &DiaDataSource) {
Nico Weber73853ab2016-04-01 22:21:51 +000053 if (SUCCEEDED(CoCreateInstance(CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER,
54 IID_IDiaDataSource,
55 reinterpret_cast<LPVOID *>(&DiaDataSource))))
Zachary Turner819e77d2016-05-06 20:51:57 +000056 return Error::success();
Nico Weber73853ab2016-04-01 22:21:51 +000057
Zachary Turner819e77d2016-05-06 20:51:57 +000058// If the CoCreateInstance call above failed, msdia*.dll is not registered.
59// Try loading the DLL corresponding to the #included DIA SDK.
Nico Weber73853ab2016-04-01 22:21:51 +000060#if !defined(_MSC_VER)
Zachary Turner819e77d2016-05-06 20:51:57 +000061 return llvm::make_error<GenericError>(
62 "DIA is only supported when using MSVC.");
Reid Klecknerfb58be82016-10-12 21:51:14 +000063#else
Nico Weber73853ab2016-04-01 22:21:51 +000064 const wchar_t *msdia_dll = nullptr;
Reid Klecknerfb58be82016-10-12 21:51:14 +000065#if _MSC_VER >= 1900 && _MSC_VER < 2000
Nico Weber73853ab2016-04-01 22:21:51 +000066 msdia_dll = L"msdia140.dll"; // VS2015
Reid Klecknerfb58be82016-10-12 21:51:14 +000067#elif _MSC_VER >= 1800
Nico Weber73853ab2016-04-01 22:21:51 +000068 msdia_dll = L"msdia120.dll"; // VS2013
69#else
70#error "Unknown Visual Studio version."
71#endif
Zachary Turner23ee87b2016-04-19 17:36:58 +000072
Zachary Turner819e77d2016-05-06 20:51:57 +000073 HRESULT HR;
74 if (FAILED(HR = NoRegCoCreate(msdia_dll, CLSID_DiaSource, IID_IDiaDataSource,
75 reinterpret_cast<LPVOID *>(&DiaDataSource))))
Zachary Turner38380322016-10-19 16:42:20 +000076 return ErrorFromHResult(HR, "Calling NoRegCoCreate");
Zachary Turner819e77d2016-05-06 20:51:57 +000077 return Error::success();
Reid Klecknerfb58be82016-10-12 21:51:14 +000078#endif
Nico Weber73853ab2016-04-01 22:21:51 +000079}
Zachary Turnercffff262015-02-10 21:17:52 +000080
81DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
82
Zachary Turner819e77d2016-05-06 20:51:57 +000083Error DIASession::createFromPdb(StringRef Path,
84 std::unique_ptr<IPDBSession> &Session) {
Zachary Turnerccf04152015-02-28 20:23:18 +000085 CComPtr<IDiaDataSource> DiaDataSource;
86 CComPtr<IDiaSession> DiaSession;
Zachary Turnercffff262015-02-10 21:17:52 +000087
88 // We assume that CoInitializeEx has already been called by the executable.
Zachary Turner819e77d2016-05-06 20:51:57 +000089 if (auto E = LoadDIA(DiaDataSource))
90 return E;
Zachary Turnercffff262015-02-10 21:17:52 +000091
92 llvm::SmallVector<UTF16, 128> Path16;
93 if (!llvm::convertUTF8ToUTF16String(Path, Path16))
Zachary Turner819e77d2016-05-06 20:51:57 +000094 return make_error<GenericError>(generic_error_code::invalid_path);
Zachary Turnercffff262015-02-10 21:17:52 +000095
96 const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
Zachary Turner819e77d2016-05-06 20:51:57 +000097 HRESULT HR;
98 if (FAILED(HR = DiaDataSource->loadDataFromPdb(Path16Str)))
Zachary Turner38380322016-10-19 16:42:20 +000099 return ErrorFromHResult(HR, "Calling loadDataFromPdb");
Zachary Turnercffff262015-02-10 21:17:52 +0000100
Zachary Turner819e77d2016-05-06 20:51:57 +0000101 if (FAILED(HR = DiaDataSource->openSession(&DiaSession)))
Zachary Turner38380322016-10-19 16:42:20 +0000102 return ErrorFromHResult(HR, "Calling openSession");
Zachary Turnerccf04152015-02-28 20:23:18 +0000103
104 Session.reset(new DIASession(DiaSession));
Zachary Turner819e77d2016-05-06 20:51:57 +0000105 return Error::success();
Zachary Turnercffff262015-02-10 21:17:52 +0000106}
107
Zachary Turner819e77d2016-05-06 20:51:57 +0000108Error DIASession::createFromExe(StringRef Path,
109 std::unique_ptr<IPDBSession> &Session) {
Zachary Turner4b083542015-04-17 22:40:36 +0000110 CComPtr<IDiaDataSource> DiaDataSource;
111 CComPtr<IDiaSession> DiaSession;
112
113 // We assume that CoInitializeEx has already been called by the executable.
Zachary Turner819e77d2016-05-06 20:51:57 +0000114 if (auto EC = LoadDIA(DiaDataSource))
115 return EC;
Zachary Turner4b083542015-04-17 22:40:36 +0000116
117 llvm::SmallVector<UTF16, 128> Path16;
118 if (!llvm::convertUTF8ToUTF16String(Path, Path16))
Zachary Turner819e77d2016-05-06 20:51:57 +0000119 return make_error<GenericError>(generic_error_code::invalid_path, Path);
Zachary Turner4b083542015-04-17 22:40:36 +0000120
121 const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
Zachary Turner819e77d2016-05-06 20:51:57 +0000122 HRESULT HR;
123 if (FAILED(HR = DiaDataSource->loadDataForExe(Path16Str, nullptr, nullptr)))
Zachary Turner38380322016-10-19 16:42:20 +0000124 return ErrorFromHResult(HR, "Calling loadDataForExe");
Zachary Turner4b083542015-04-17 22:40:36 +0000125
Zachary Turner819e77d2016-05-06 20:51:57 +0000126 if (FAILED(HR = DiaDataSource->openSession(&DiaSession)))
Zachary Turner38380322016-10-19 16:42:20 +0000127 return ErrorFromHResult(HR, "Calling openSession");
Zachary Turner4b083542015-04-17 22:40:36 +0000128
129 Session.reset(new DIASession(DiaSession));
Zachary Turner819e77d2016-05-06 20:51:57 +0000130 return Error::success();
Zachary Turner4b083542015-04-17 22:40:36 +0000131}
132
Zachary Turnercffff262015-02-10 21:17:52 +0000133uint64_t DIASession::getLoadAddress() const {
134 uint64_t LoadAddress;
135 bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
136 return (success) ? LoadAddress : 0;
137}
138
139void DIASession::setLoadAddress(uint64_t Address) {
140 Session->put_loadAddress(Address);
141}
142
Adrian McCarthy649b8e02017-02-24 00:10:47 +0000143std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() {
Zachary Turnercffff262015-02-10 21:17:52 +0000144 CComPtr<IDiaSymbol> GlobalScope;
145 if (S_OK != Session->get_globalScope(&GlobalScope))
146 return nullptr;
147
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000148 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, GlobalScope);
Zachary Turnercffff262015-02-10 21:17:52 +0000149 auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
150 std::unique_ptr<PDBSymbolExe> ExeSymbol(
151 static_cast<PDBSymbolExe *>(PdbSymbol.release()));
152 return ExeSymbol;
153}
154
155std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const {
156 CComPtr<IDiaSymbol> LocatedSymbol;
157 if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol))
158 return nullptr;
159
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000160 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, LocatedSymbol);
Zachary Turnercffff262015-02-10 21:17:52 +0000161 return PDBSymbol::create(*this, std::move(RawSymbol));
162}
163
Zachary Turner4b083542015-04-17 22:40:36 +0000164std::unique_ptr<PDBSymbol>
Zachary Turnere5cb2692015-05-01 20:24:26 +0000165DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
166 enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
167
Zachary Turner4b083542015-04-17 22:40:36 +0000168 CComPtr<IDiaSymbol> Symbol;
Zachary Turnere5cb2692015-05-01 20:24:26 +0000169 if (S_OK != Session->findSymbolByVA(Address, EnumVal, &Symbol)) {
170 ULONGLONG LoadAddr = 0;
171 if (S_OK != Session->get_loadAddress(&LoadAddr))
172 return nullptr;
173 DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
174 if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
175 return nullptr;
176 }
Zachary Turner4b083542015-04-17 22:40:36 +0000177 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
178 return PDBSymbol::create(*this, std::move(RawSymbol));
179}
180
181std::unique_ptr<IPDBEnumLineNumbers>
Zachary Turner43ec3af2016-02-18 18:47:29 +0000182DIASession::findLineNumbers(const PDBSymbolCompiland &Compiland,
183 const IPDBSourceFile &File) const {
184 const DIARawSymbol &RawCompiland =
185 static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
186 const DIASourceFile &RawFile = static_cast<const DIASourceFile &>(File);
187
188 CComPtr<IDiaEnumLineNumbers> LineNumbers;
189 if (S_OK !=
190 Session->findLines(RawCompiland.getDiaSymbol(), RawFile.getDiaFile(),
191 &LineNumbers))
192 return nullptr;
193
194 return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
195}
196
197std::unique_ptr<IPDBEnumLineNumbers>
Zachary Turner4b083542015-04-17 22:40:36 +0000198DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
199 CComPtr<IDiaEnumLineNumbers> LineNumbers;
200 if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers))
201 return nullptr;
202
203 return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
204}
205
Zachary Turner43ec3af2016-02-18 18:47:29 +0000206std::unique_ptr<IPDBEnumSourceFiles>
207DIASession::findSourceFiles(const PDBSymbolCompiland *Compiland,
208 llvm::StringRef Pattern,
209 PDB_NameSearchFlags Flags) const {
210 IDiaSymbol *DiaCompiland = nullptr;
211 CComBSTR Utf16Pattern;
212 if (!Pattern.empty())
213 Utf16Pattern = CComBSTR(Pattern.data());
214
215 if (Compiland)
216 DiaCompiland = static_cast<const DIARawSymbol &>(Compiland->getRawSymbol())
217 .getDiaSymbol();
218
219 Flags = static_cast<PDB_NameSearchFlags>(
220 Flags | PDB_NameSearchFlags::NS_FileNameExtMatch);
221 CComPtr<IDiaEnumSourceFiles> SourceFiles;
222 if (S_OK !=
223 Session->findFile(DiaCompiland, Utf16Pattern.m_str, Flags, &SourceFiles))
224 return nullptr;
225 return llvm::make_unique<DIAEnumSourceFiles>(*this, SourceFiles);
226}
227
228std::unique_ptr<IPDBSourceFile>
229DIASession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
230 llvm::StringRef Pattern,
231 PDB_NameSearchFlags Flags) const {
232 auto SourceFiles = findSourceFiles(Compiland, Pattern, Flags);
233 if (!SourceFiles || SourceFiles->getChildCount() == 0)
234 return nullptr;
235 return SourceFiles->getNext();
236}
237
238std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
239DIASession::findCompilandsForSourceFile(llvm::StringRef Pattern,
240 PDB_NameSearchFlags Flags) const {
241 auto File = findOneSourceFile(nullptr, Pattern, Flags);
242 if (!File)
243 return nullptr;
244 return File->getCompilands();
245}
246
247std::unique_ptr<PDBSymbolCompiland>
248DIASession::findOneCompilandForSourceFile(llvm::StringRef Pattern,
249 PDB_NameSearchFlags Flags) const {
250 auto Compilands = findCompilandsForSourceFile(Pattern, Flags);
251 if (!Compilands || Compilands->getChildCount() == 0)
252 return nullptr;
253 return Compilands->getNext();
254}
255
Zachary Turnera5549172015-02-10 22:43:25 +0000256std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
257 CComPtr<IDiaEnumSourceFiles> Files;
258 if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
259 return nullptr;
260
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000261 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
Zachary Turnera5549172015-02-10 22:43:25 +0000262}
263
264std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland(
265 const PDBSymbolCompiland &Compiland) const {
266 CComPtr<IDiaEnumSourceFiles> Files;
267
268 const DIARawSymbol &RawSymbol =
269 static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
270 if (S_OK !=
271 Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files))
272 return nullptr;
273
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000274 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
Zachary Turnera5549172015-02-10 22:43:25 +0000275}
276
Zachary Turnercffff262015-02-10 21:17:52 +0000277std::unique_ptr<IPDBSourceFile>
278DIASession::getSourceFileById(uint32_t FileId) const {
279 CComPtr<IDiaSourceFile> LocatedFile;
280 if (S_OK != Session->findFileById(FileId, &LocatedFile))
281 return nullptr;
282
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000283 return llvm::make_unique<DIASourceFile>(*this, LocatedFile);
Zachary Turnercffff262015-02-10 21:17:52 +0000284}
285
286std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
287 CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
288 if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
289 return nullptr;
290
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000291 return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator);
Zachary Turnercffff262015-02-10 21:17:52 +0000292}