blob: ef9390cda312700c5693683b99f1ab6cee171c26 [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"
Zachary Turner16901642017-04-24 17:47:24 +000024#include "llvm/Support/FormatVariadic.h"
Zachary Turner38380322016-10-19 16:42:20 +000025#include "llvm/Support/raw_ostream.h"
Zachary Turnercffff262015-02-10 21:17:52 +000026
27using namespace llvm;
Zachary Turnerec28fc32016-05-04 20:32:13 +000028using namespace llvm::pdb;
Zachary Turnercffff262015-02-10 21:17:52 +000029
Zachary Turner16901642017-04-24 17:47:24 +000030template <typename... Ts>
31static Error ErrorFromHResult(HRESULT Result, const char *Str, Ts &&... Args) {
32 SmallString<64> MessageStorage;
33 StringRef Context;
34 if (sizeof...(Args) > 0) {
35 MessageStorage = formatv(Str, std::forward<Ts>(Args)...).str();
36 Context = MessageStorage;
37 } else
38 Context = Str;
39
Zachary Turner819e77d2016-05-06 20:51:57 +000040 switch (Result) {
41 case E_PDB_NOT_FOUND:
Zachary Turner38380322016-10-19 16:42:20 +000042 return make_error<GenericError>(generic_error_code::invalid_path, Context);
Zachary Turner819e77d2016-05-06 20:51:57 +000043 case E_PDB_FORMAT:
Zachary Turner38380322016-10-19 16:42:20 +000044 return make_error<DIAError>(dia_error_code::invalid_file_format, Context);
Zachary Turner819e77d2016-05-06 20:51:57 +000045 case E_INVALIDARG:
Zachary Turner38380322016-10-19 16:42:20 +000046 return make_error<DIAError>(dia_error_code::invalid_parameter, Context);
Zachary Turner819e77d2016-05-06 20:51:57 +000047 case E_UNEXPECTED:
Zachary Turner38380322016-10-19 16:42:20 +000048 return make_error<DIAError>(dia_error_code::already_loaded, Context);
Zachary Turner819e77d2016-05-06 20:51:57 +000049 case E_PDB_INVALID_SIG:
50 case E_PDB_INVALID_AGE:
Zachary Turner38380322016-10-19 16:42:20 +000051 return make_error<DIAError>(dia_error_code::debug_info_mismatch, Context);
52 default: {
53 std::string S;
54 raw_string_ostream OS(S);
55 OS << "HRESULT: " << format_hex(static_cast<DWORD>(Result), 10, true)
56 << ": " << Context;
57 return make_error<DIAError>(dia_error_code::unspecified, OS.str());
58 }
Zachary Turner819e77d2016-05-06 20:51:57 +000059 }
60}
61
Reid Klecknerfb58be82016-10-12 21:51:14 +000062static Error LoadDIA(CComPtr<IDiaDataSource> &DiaDataSource) {
Nico Weber73853ab2016-04-01 22:21:51 +000063 if (SUCCEEDED(CoCreateInstance(CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER,
64 IID_IDiaDataSource,
65 reinterpret_cast<LPVOID *>(&DiaDataSource))))
Zachary Turner819e77d2016-05-06 20:51:57 +000066 return Error::success();
Nico Weber73853ab2016-04-01 22:21:51 +000067
Zachary Turner819e77d2016-05-06 20:51:57 +000068// If the CoCreateInstance call above failed, msdia*.dll is not registered.
69// Try loading the DLL corresponding to the #included DIA SDK.
Nico Weber73853ab2016-04-01 22:21:51 +000070#if !defined(_MSC_VER)
Zachary Turner819e77d2016-05-06 20:51:57 +000071 return llvm::make_error<GenericError>(
72 "DIA is only supported when using MSVC.");
Reid Klecknerfb58be82016-10-12 21:51:14 +000073#else
Nico Weber73853ab2016-04-01 22:21:51 +000074 const wchar_t *msdia_dll = nullptr;
Reid Klecknerfb58be82016-10-12 21:51:14 +000075#if _MSC_VER >= 1900 && _MSC_VER < 2000
Nico Weber73853ab2016-04-01 22:21:51 +000076 msdia_dll = L"msdia140.dll"; // VS2015
Reid Klecknerfb58be82016-10-12 21:51:14 +000077#elif _MSC_VER >= 1800
Nico Weber73853ab2016-04-01 22:21:51 +000078 msdia_dll = L"msdia120.dll"; // VS2013
79#else
80#error "Unknown Visual Studio version."
81#endif
Zachary Turner23ee87b2016-04-19 17:36:58 +000082
Zachary Turner819e77d2016-05-06 20:51:57 +000083 HRESULT HR;
84 if (FAILED(HR = NoRegCoCreate(msdia_dll, CLSID_DiaSource, IID_IDiaDataSource,
85 reinterpret_cast<LPVOID *>(&DiaDataSource))))
Zachary Turner38380322016-10-19 16:42:20 +000086 return ErrorFromHResult(HR, "Calling NoRegCoCreate");
Zachary Turner819e77d2016-05-06 20:51:57 +000087 return Error::success();
Reid Klecknerfb58be82016-10-12 21:51:14 +000088#endif
Nico Weber73853ab2016-04-01 22:21:51 +000089}
Zachary Turnercffff262015-02-10 21:17:52 +000090
91DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
92
Zachary Turner819e77d2016-05-06 20:51:57 +000093Error DIASession::createFromPdb(StringRef Path,
94 std::unique_ptr<IPDBSession> &Session) {
Zachary Turnerccf04152015-02-28 20:23:18 +000095 CComPtr<IDiaDataSource> DiaDataSource;
96 CComPtr<IDiaSession> DiaSession;
Zachary Turnercffff262015-02-10 21:17:52 +000097
98 // We assume that CoInitializeEx has already been called by the executable.
Zachary Turner819e77d2016-05-06 20:51:57 +000099 if (auto E = LoadDIA(DiaDataSource))
100 return E;
Zachary Turnercffff262015-02-10 21:17:52 +0000101
102 llvm::SmallVector<UTF16, 128> Path16;
103 if (!llvm::convertUTF8ToUTF16String(Path, Path16))
Zachary Turner819e77d2016-05-06 20:51:57 +0000104 return make_error<GenericError>(generic_error_code::invalid_path);
Zachary Turnercffff262015-02-10 21:17:52 +0000105
106 const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
Zachary Turner819e77d2016-05-06 20:51:57 +0000107 HRESULT HR;
Zachary Turner16901642017-04-24 17:47:24 +0000108 if (FAILED(HR = DiaDataSource->loadDataFromPdb(Path16Str))) {
109 return ErrorFromHResult(HR, "Calling loadDataFromPdb {0}", Path);
110 }
Zachary Turnercffff262015-02-10 21:17:52 +0000111
Zachary Turner819e77d2016-05-06 20:51:57 +0000112 if (FAILED(HR = DiaDataSource->openSession(&DiaSession)))
Zachary Turner38380322016-10-19 16:42:20 +0000113 return ErrorFromHResult(HR, "Calling openSession");
Zachary Turnerccf04152015-02-28 20:23:18 +0000114
115 Session.reset(new DIASession(DiaSession));
Zachary Turner819e77d2016-05-06 20:51:57 +0000116 return Error::success();
Zachary Turnercffff262015-02-10 21:17:52 +0000117}
118
Zachary Turner819e77d2016-05-06 20:51:57 +0000119Error DIASession::createFromExe(StringRef Path,
120 std::unique_ptr<IPDBSession> &Session) {
Zachary Turner4b083542015-04-17 22:40:36 +0000121 CComPtr<IDiaDataSource> DiaDataSource;
122 CComPtr<IDiaSession> DiaSession;
123
124 // We assume that CoInitializeEx has already been called by the executable.
Zachary Turner819e77d2016-05-06 20:51:57 +0000125 if (auto EC = LoadDIA(DiaDataSource))
126 return EC;
Zachary Turner4b083542015-04-17 22:40:36 +0000127
128 llvm::SmallVector<UTF16, 128> Path16;
129 if (!llvm::convertUTF8ToUTF16String(Path, Path16))
Zachary Turner819e77d2016-05-06 20:51:57 +0000130 return make_error<GenericError>(generic_error_code::invalid_path, Path);
Zachary Turner4b083542015-04-17 22:40:36 +0000131
132 const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
Zachary Turner819e77d2016-05-06 20:51:57 +0000133 HRESULT HR;
134 if (FAILED(HR = DiaDataSource->loadDataForExe(Path16Str, nullptr, nullptr)))
Zachary Turner38380322016-10-19 16:42:20 +0000135 return ErrorFromHResult(HR, "Calling loadDataForExe");
Zachary Turner4b083542015-04-17 22:40:36 +0000136
Zachary Turner819e77d2016-05-06 20:51:57 +0000137 if (FAILED(HR = DiaDataSource->openSession(&DiaSession)))
Zachary Turner38380322016-10-19 16:42:20 +0000138 return ErrorFromHResult(HR, "Calling openSession");
Zachary Turner4b083542015-04-17 22:40:36 +0000139
140 Session.reset(new DIASession(DiaSession));
Zachary Turner819e77d2016-05-06 20:51:57 +0000141 return Error::success();
Zachary Turner4b083542015-04-17 22:40:36 +0000142}
143
Zachary Turnercffff262015-02-10 21:17:52 +0000144uint64_t DIASession::getLoadAddress() const {
145 uint64_t LoadAddress;
146 bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
147 return (success) ? LoadAddress : 0;
148}
149
150void DIASession::setLoadAddress(uint64_t Address) {
151 Session->put_loadAddress(Address);
152}
153
Adrian McCarthy6a4b0802017-06-22 18:42:23 +0000154std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() {
Zachary Turnercffff262015-02-10 21:17:52 +0000155 CComPtr<IDiaSymbol> GlobalScope;
156 if (S_OK != Session->get_globalScope(&GlobalScope))
157 return nullptr;
158
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000159 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, GlobalScope);
Zachary Turnercffff262015-02-10 21:17:52 +0000160 auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
161 std::unique_ptr<PDBSymbolExe> ExeSymbol(
162 static_cast<PDBSymbolExe *>(PdbSymbol.release()));
163 return ExeSymbol;
164}
165
166std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const {
167 CComPtr<IDiaSymbol> LocatedSymbol;
168 if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol))
169 return nullptr;
170
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000171 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, LocatedSymbol);
Zachary Turnercffff262015-02-10 21:17:52 +0000172 return PDBSymbol::create(*this, std::move(RawSymbol));
173}
174
Zachary Turner4b083542015-04-17 22:40:36 +0000175std::unique_ptr<PDBSymbol>
Zachary Turnere5cb2692015-05-01 20:24:26 +0000176DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
177 enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
178
Zachary Turner4b083542015-04-17 22:40:36 +0000179 CComPtr<IDiaSymbol> Symbol;
Zachary Turnere5cb2692015-05-01 20:24:26 +0000180 if (S_OK != Session->findSymbolByVA(Address, EnumVal, &Symbol)) {
181 ULONGLONG LoadAddr = 0;
182 if (S_OK != Session->get_loadAddress(&LoadAddr))
183 return nullptr;
184 DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
185 if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
186 return nullptr;
187 }
Zachary Turner4b083542015-04-17 22:40:36 +0000188 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
189 return PDBSymbol::create(*this, std::move(RawSymbol));
190}
191
192std::unique_ptr<IPDBEnumLineNumbers>
Zachary Turner43ec3af2016-02-18 18:47:29 +0000193DIASession::findLineNumbers(const PDBSymbolCompiland &Compiland,
194 const IPDBSourceFile &File) const {
195 const DIARawSymbol &RawCompiland =
196 static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
197 const DIASourceFile &RawFile = static_cast<const DIASourceFile &>(File);
198
199 CComPtr<IDiaEnumLineNumbers> LineNumbers;
200 if (S_OK !=
201 Session->findLines(RawCompiland.getDiaSymbol(), RawFile.getDiaFile(),
202 &LineNumbers))
203 return nullptr;
204
205 return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
206}
207
208std::unique_ptr<IPDBEnumLineNumbers>
Zachary Turner4b083542015-04-17 22:40:36 +0000209DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
210 CComPtr<IDiaEnumLineNumbers> LineNumbers;
211 if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers))
212 return nullptr;
213
214 return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
215}
216
Zachary Turner43ec3af2016-02-18 18:47:29 +0000217std::unique_ptr<IPDBEnumSourceFiles>
218DIASession::findSourceFiles(const PDBSymbolCompiland *Compiland,
219 llvm::StringRef Pattern,
220 PDB_NameSearchFlags Flags) const {
221 IDiaSymbol *DiaCompiland = nullptr;
222 CComBSTR Utf16Pattern;
223 if (!Pattern.empty())
224 Utf16Pattern = CComBSTR(Pattern.data());
225
226 if (Compiland)
227 DiaCompiland = static_cast<const DIARawSymbol &>(Compiland->getRawSymbol())
228 .getDiaSymbol();
229
230 Flags = static_cast<PDB_NameSearchFlags>(
231 Flags | PDB_NameSearchFlags::NS_FileNameExtMatch);
232 CComPtr<IDiaEnumSourceFiles> SourceFiles;
233 if (S_OK !=
234 Session->findFile(DiaCompiland, Utf16Pattern.m_str, Flags, &SourceFiles))
235 return nullptr;
236 return llvm::make_unique<DIAEnumSourceFiles>(*this, SourceFiles);
237}
238
239std::unique_ptr<IPDBSourceFile>
240DIASession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
241 llvm::StringRef Pattern,
242 PDB_NameSearchFlags Flags) const {
243 auto SourceFiles = findSourceFiles(Compiland, Pattern, Flags);
244 if (!SourceFiles || SourceFiles->getChildCount() == 0)
245 return nullptr;
246 return SourceFiles->getNext();
247}
248
249std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
250DIASession::findCompilandsForSourceFile(llvm::StringRef Pattern,
251 PDB_NameSearchFlags Flags) const {
252 auto File = findOneSourceFile(nullptr, Pattern, Flags);
253 if (!File)
254 return nullptr;
255 return File->getCompilands();
256}
257
258std::unique_ptr<PDBSymbolCompiland>
259DIASession::findOneCompilandForSourceFile(llvm::StringRef Pattern,
260 PDB_NameSearchFlags Flags) const {
261 auto Compilands = findCompilandsForSourceFile(Pattern, Flags);
262 if (!Compilands || Compilands->getChildCount() == 0)
263 return nullptr;
264 return Compilands->getNext();
265}
266
Zachary Turnera5549172015-02-10 22:43:25 +0000267std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
268 CComPtr<IDiaEnumSourceFiles> Files;
269 if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
270 return nullptr;
271
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000272 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
Zachary Turnera5549172015-02-10 22:43:25 +0000273}
274
275std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland(
276 const PDBSymbolCompiland &Compiland) const {
277 CComPtr<IDiaEnumSourceFiles> Files;
278
279 const DIARawSymbol &RawSymbol =
280 static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
281 if (S_OK !=
282 Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files))
283 return nullptr;
284
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000285 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
Zachary Turnera5549172015-02-10 22:43:25 +0000286}
287
Zachary Turnercffff262015-02-10 21:17:52 +0000288std::unique_ptr<IPDBSourceFile>
289DIASession::getSourceFileById(uint32_t FileId) const {
290 CComPtr<IDiaSourceFile> LocatedFile;
291 if (S_OK != Session->findFileById(FileId, &LocatedFile))
292 return nullptr;
293
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000294 return llvm::make_unique<DIASourceFile>(*this, LocatedFile);
Zachary Turnercffff262015-02-10 21:17:52 +0000295}
296
297std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
298 CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
299 if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
300 return nullptr;
301
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000302 return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator);
Zachary Turnercffff262015-02-10 21:17:52 +0000303}