blob: 5e58bb4008f5fac3069fc2562476f2d8b1d73aa4 [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
21using namespace llvm;
22
23namespace {}
24
25DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
26
Zachary Turnerccf04152015-02-28 20:23:18 +000027PDB_ErrorCode DIASession::createFromPdb(StringRef Path,
28 std::unique_ptr<IPDBSession> &Session) {
29 CComPtr<IDiaDataSource> DiaDataSource;
30 CComPtr<IDiaSession> DiaSession;
Zachary Turnercffff262015-02-10 21:17:52 +000031
32 // We assume that CoInitializeEx has already been called by the executable.
Zachary Turnerccf04152015-02-28 20:23:18 +000033 HRESULT Result = ::CoCreateInstance(
34 CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource,
35 reinterpret_cast<LPVOID *>(&DiaDataSource));
Zachary Turnercffff262015-02-10 21:17:52 +000036 if (FAILED(Result))
Zachary Turnerccf04152015-02-28 20:23:18 +000037 return PDB_ErrorCode::NoPdbImpl;
Zachary Turnercffff262015-02-10 21:17:52 +000038
39 llvm::SmallVector<UTF16, 128> Path16;
40 if (!llvm::convertUTF8ToUTF16String(Path, Path16))
Zachary Turnerccf04152015-02-28 20:23:18 +000041 return PDB_ErrorCode::InvalidPath;
Zachary Turnercffff262015-02-10 21:17:52 +000042
43 const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
Zachary Turnerccf04152015-02-28 20:23:18 +000044 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 }
Zachary Turnercffff262015-02-10 21:17:52 +000056
Zachary Turnerccf04152015-02-28 20:23:18 +000057 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;
Zachary Turnercffff262015-02-10 21:17:52 +000066}
67
Zachary Turner4b083542015-04-17 22:40:36 +000068PDB_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
Zachary Turnercffff262015-02-10 21:17:52 +0000112uint64_t DIASession::getLoadAddress() const {
113 uint64_t LoadAddress;
114 bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
115 return (success) ? LoadAddress : 0;
116}
117
118void DIASession::setLoadAddress(uint64_t Address) {
119 Session->put_loadAddress(Address);
120}
121
122std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const {
123 CComPtr<IDiaSymbol> GlobalScope;
124 if (S_OK != Session->get_globalScope(&GlobalScope))
125 return nullptr;
126
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000127 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, GlobalScope);
Zachary Turnercffff262015-02-10 21:17:52 +0000128 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
134std::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
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000139 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, LocatedSymbol);
Zachary Turnercffff262015-02-10 21:17:52 +0000140 return PDBSymbol::create(*this, std::move(RawSymbol));
141}
142
Zachary Turner4b083542015-04-17 22:40:36 +0000143std::unique_ptr<PDBSymbol>
Zachary Turnere5cb2692015-05-01 20:24:26 +0000144DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
145 enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
146
Zachary Turner4b083542015-04-17 22:40:36 +0000147 CComPtr<IDiaSymbol> Symbol;
Zachary Turnere5cb2692015-05-01 20:24:26 +0000148 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 }
Zachary Turner4b083542015-04-17 22:40:36 +0000156 auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
157 return PDBSymbol::create(*this, std::move(RawSymbol));
158}
159
160std::unique_ptr<IPDBEnumLineNumbers>
Zachary Turner43ec3af2016-02-18 18:47:29 +0000161DIASession::findLineNumbers(const PDBSymbolCompiland &Compiland,
162 const IPDBSourceFile &File) const {
163 const DIARawSymbol &RawCompiland =
164 static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
165 const DIASourceFile &RawFile = static_cast<const DIASourceFile &>(File);
166
167 CComPtr<IDiaEnumLineNumbers> LineNumbers;
168 if (S_OK !=
169 Session->findLines(RawCompiland.getDiaSymbol(), RawFile.getDiaFile(),
170 &LineNumbers))
171 return nullptr;
172
173 return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
174}
175
176std::unique_ptr<IPDBEnumLineNumbers>
Zachary Turner4b083542015-04-17 22:40:36 +0000177DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
178 CComPtr<IDiaEnumLineNumbers> LineNumbers;
179 if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers))
180 return nullptr;
181
182 return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
183}
184
Zachary Turner43ec3af2016-02-18 18:47:29 +0000185std::unique_ptr<IPDBEnumSourceFiles>
186DIASession::findSourceFiles(const PDBSymbolCompiland *Compiland,
187 llvm::StringRef Pattern,
188 PDB_NameSearchFlags Flags) const {
189 IDiaSymbol *DiaCompiland = nullptr;
190 CComBSTR Utf16Pattern;
191 if (!Pattern.empty())
192 Utf16Pattern = CComBSTR(Pattern.data());
193
194 if (Compiland)
195 DiaCompiland = static_cast<const DIARawSymbol &>(Compiland->getRawSymbol())
196 .getDiaSymbol();
197
198 Flags = static_cast<PDB_NameSearchFlags>(
199 Flags | PDB_NameSearchFlags::NS_FileNameExtMatch);
200 CComPtr<IDiaEnumSourceFiles> SourceFiles;
201 if (S_OK !=
202 Session->findFile(DiaCompiland, Utf16Pattern.m_str, Flags, &SourceFiles))
203 return nullptr;
204 return llvm::make_unique<DIAEnumSourceFiles>(*this, SourceFiles);
205}
206
207std::unique_ptr<IPDBSourceFile>
208DIASession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
209 llvm::StringRef Pattern,
210 PDB_NameSearchFlags Flags) const {
211 auto SourceFiles = findSourceFiles(Compiland, Pattern, Flags);
212 if (!SourceFiles || SourceFiles->getChildCount() == 0)
213 return nullptr;
214 return SourceFiles->getNext();
215}
216
217std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
218DIASession::findCompilandsForSourceFile(llvm::StringRef Pattern,
219 PDB_NameSearchFlags Flags) const {
220 auto File = findOneSourceFile(nullptr, Pattern, Flags);
221 if (!File)
222 return nullptr;
223 return File->getCompilands();
224}
225
226std::unique_ptr<PDBSymbolCompiland>
227DIASession::findOneCompilandForSourceFile(llvm::StringRef Pattern,
228 PDB_NameSearchFlags Flags) const {
229 auto Compilands = findCompilandsForSourceFile(Pattern, Flags);
230 if (!Compilands || Compilands->getChildCount() == 0)
231 return nullptr;
232 return Compilands->getNext();
233}
234
Zachary Turnera5549172015-02-10 22:43:25 +0000235std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
236 CComPtr<IDiaEnumSourceFiles> Files;
237 if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
238 return nullptr;
239
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000240 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
Zachary Turnera5549172015-02-10 22:43:25 +0000241}
242
243std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland(
244 const PDBSymbolCompiland &Compiland) const {
245 CComPtr<IDiaEnumSourceFiles> Files;
246
247 const DIARawSymbol &RawSymbol =
248 static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
249 if (S_OK !=
250 Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files))
251 return nullptr;
252
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000253 return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
Zachary Turnera5549172015-02-10 22:43:25 +0000254}
255
Zachary Turnercffff262015-02-10 21:17:52 +0000256std::unique_ptr<IPDBSourceFile>
257DIASession::getSourceFileById(uint32_t FileId) const {
258 CComPtr<IDiaSourceFile> LocatedFile;
259 if (S_OK != Session->findFileById(FileId, &LocatedFile))
260 return nullptr;
261
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000262 return llvm::make_unique<DIASourceFile>(*this, LocatedFile);
Zachary Turnercffff262015-02-10 21:17:52 +0000263}
264
265std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
266 CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
267 if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
268 return nullptr;
269
Zachary Turnerbe6d1e42015-02-10 23:46:48 +0000270 return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator);
Zachary Turnercffff262015-02-10 21:17:52 +0000271}