DIASession.cpp revision 360784
1174604Sscottl//===- DIASession.cpp - DIA implementation of IPDBSession -------*- C++ -*-===//
2174604Sscottl//
3174604Sscottl// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4174604Sscottl// See https://llvm.org/LICENSE.txt for license information.
5174604Sscottl// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6174604Sscottl//
7174604Sscottl//===----------------------------------------------------------------------===//
8174604Sscottl#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
9174604Sscottl#include "llvm/ADT/STLExtras.h"
10174604Sscottl#include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
11174604Sscottl#include "llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h"
12174604Sscottl#include "llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h"
13174604Sscottl#include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
14174604Sscottl#include "llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h"
15174604Sscottl#include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
16174604Sscottl#include "llvm/DebugInfo/PDB/DIA/DIAEnumTables.h"
17174604Sscottl#include "llvm/DebugInfo/PDB/DIA/DIAError.h"
18174604Sscottl#include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
19174604Sscottl#include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
20174604Sscottl#include "llvm/DebugInfo/PDB/DIA/DIASupport.h"
21174604Sscottl#include "llvm/DebugInfo/PDB/GenericError.h"
22174604Sscottl#include "llvm/DebugInfo/PDB/PDB.h"
23174604Sscottl#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
24174604Sscottl#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
25174604Sscottl#include "llvm/Support/ConvertUTF.h"
26174604Sscottl#include "llvm/Support/Format.h"
27174604Sscottl#include "llvm/Support/FormatVariadic.h"
28174604Sscottl#include "llvm/Support/raw_ostream.h"
29174604Sscottl
30174604Sscottlusing namespace llvm;
31174604Sscottlusing namespace llvm::pdb;
32174604Sscottl
33174604Sscottltemplate <typename... Ts>
34174604Sscottlstatic Error ErrorFromHResult(HRESULT Result, const char *Str, Ts &&... Args) {
35174604Sscottl  SmallString<64> MessageStorage;
36174604Sscottl  StringRef Context;
37174604Sscottl  if (sizeof...(Args) > 0) {
38174604Sscottl    MessageStorage = formatv(Str, std::forward<Ts>(Args)...).str();
39174604Sscottl    Context = MessageStorage;
40174604Sscottl  } else
41174604Sscottl    Context = Str;
42174604Sscottl
43174604Sscottl  switch (Result) {
44174604Sscottl  case E_PDB_NOT_FOUND:
45174604Sscottl    return errorCodeToError(std::error_code(ENOENT, std::generic_category()));
46174604Sscottl  case E_PDB_FORMAT:
47174604Sscottl    return make_error<DIAError>(dia_error_code::invalid_file_format, Context);
48174604Sscottl  case E_INVALIDARG:
49174604Sscottl    return make_error<DIAError>(dia_error_code::invalid_parameter, Context);
50174604Sscottl  case E_UNEXPECTED:
51174604Sscottl    return make_error<DIAError>(dia_error_code::already_loaded, Context);
52174604Sscottl  case E_PDB_INVALID_SIG:
53174604Sscottl  case E_PDB_INVALID_AGE:
54174604Sscottl    return make_error<DIAError>(dia_error_code::debug_info_mismatch, Context);
55174604Sscottl  default: {
56174604Sscottl    std::string S;
57174604Sscottl    raw_string_ostream OS(S);
58174604Sscottl    OS << "HRESULT: " << format_hex(static_cast<DWORD>(Result), 10, true)
59174604Sscottl       << ": " << Context;
60174604Sscottl    return make_error<DIAError>(dia_error_code::unspecified, OS.str());
61174604Sscottl  }
62174604Sscottl  }
63174604Sscottl}
64174604Sscottl
65174604Sscottlstatic Error LoadDIA(CComPtr<IDiaDataSource> &DiaDataSource) {
66174604Sscottl  if (SUCCEEDED(CoCreateInstance(CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER,
67174604Sscottl                                 IID_IDiaDataSource,
68174604Sscottl                                 reinterpret_cast<LPVOID *>(&DiaDataSource))))
69174604Sscottl    return Error::success();
70174604Sscottl
71174604Sscottl// If the CoCreateInstance call above failed, msdia*.dll is not registered.
72174604Sscottl// Try loading the DLL corresponding to the #included DIA SDK.
73174604Sscottl#if !defined(_MSC_VER)
74174604Sscottl  return llvm::make_error<PDBError>(pdb_error_code::dia_failed_loading);
75174604Sscottl#else
76174604Sscottl  const wchar_t *msdia_dll = L"msdia140.dll";
77174604Sscottl  HRESULT HR;
78174604Sscottl  if (FAILED(HR = NoRegCoCreate(msdia_dll, CLSID_DiaSource, IID_IDiaDataSource,
79174604Sscottl                                reinterpret_cast<LPVOID *>(&DiaDataSource))))
80174604Sscottl    return ErrorFromHResult(HR, "Calling NoRegCoCreate");
81174604Sscottl  return Error::success();
82174604Sscottl#endif
83174604Sscottl}
84174604Sscottl
85174604SscottlDIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
86174604Sscottl
87174604SscottlError DIASession::createFromPdb(StringRef Path,
88174604Sscottl                                std::unique_ptr<IPDBSession> &Session) {
89174604Sscottl  CComPtr<IDiaDataSource> DiaDataSource;
90174604Sscottl  CComPtr<IDiaSession> DiaSession;
91174604Sscottl
92174604Sscottl  // We assume that CoInitializeEx has already been called by the executable.
93174604Sscottl  if (auto E = LoadDIA(DiaDataSource))
94174604Sscottl    return E;
95174604Sscottl
96174604Sscottl  llvm::SmallVector<UTF16, 128> Path16;
97174604Sscottl  if (!llvm::convertUTF8ToUTF16String(Path, Path16))
98174604Sscottl    return make_error<PDBError>(pdb_error_code::invalid_utf8_path, Path);
99174604Sscottl
100174604Sscottl  const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
101174604Sscottl  HRESULT HR;
102176018Sscottl  if (FAILED(HR = DiaDataSource->loadDataFromPdb(Path16Str))) {
103176018Sscottl    return ErrorFromHResult(HR, "Calling loadDataFromPdb {0}", Path);
104174604Sscottl  }
105176018Sscottl
106174604Sscottl  if (FAILED(HR = DiaDataSource->openSession(&DiaSession)))
107174604Sscottl    return ErrorFromHResult(HR, "Calling openSession");
108174604Sscottl
109174604Sscottl  Session.reset(new DIASession(DiaSession));
110174604Sscottl  return Error::success();
111174604Sscottl}
112174604Sscottl
113174604SscottlError DIASession::createFromExe(StringRef Path,
114174604Sscottl                                std::unique_ptr<IPDBSession> &Session) {
115174604Sscottl  CComPtr<IDiaDataSource> DiaDataSource;
116174604Sscottl  CComPtr<IDiaSession> DiaSession;
117174604Sscottl
118174604Sscottl  // We assume that CoInitializeEx has already been called by the executable.
119174604Sscottl  if (auto EC = LoadDIA(DiaDataSource))
120174604Sscottl    return EC;
121174604Sscottl
122174604Sscottl  llvm::SmallVector<UTF16, 128> Path16;
123174604Sscottl  if (!llvm::convertUTF8ToUTF16String(Path, Path16))
124174604Sscottl    return make_error<PDBError>(pdb_error_code::invalid_utf8_path, Path);
125174604Sscottl
126174604Sscottl  const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
127174604Sscottl  HRESULT HR;
128174604Sscottl  if (FAILED(HR = DiaDataSource->loadDataForExe(Path16Str, nullptr, nullptr)))
129174604Sscottl    return ErrorFromHResult(HR, "Calling loadDataForExe");
130174604Sscottl
131174604Sscottl  if (FAILED(HR = DiaDataSource->openSession(&DiaSession)))
132174604Sscottl    return ErrorFromHResult(HR, "Calling openSession");
133174604Sscottl
134174604Sscottl  Session.reset(new DIASession(DiaSession));
135174604Sscottl  return Error::success();
136174604Sscottl}
137174604Sscottl
138174604Sscottluint64_t DIASession::getLoadAddress() const {
139174604Sscottl  uint64_t LoadAddress;
140174604Sscottl  bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
141174604Sscottl  return (success) ? LoadAddress : 0;
142174604Sscottl}
143174604Sscottl
144174604Sscottlbool DIASession::setLoadAddress(uint64_t Address) {
145174604Sscottl  return (S_OK == Session->put_loadAddress(Address));
146174604Sscottl}
147174604Sscottl
148174604Sscottlstd::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() {
149174604Sscottl  CComPtr<IDiaSymbol> GlobalScope;
150174604Sscottl  if (S_OK != Session->get_globalScope(&GlobalScope))
151174604Sscottl    return nullptr;
152174604Sscottl
153174604Sscottl  auto RawSymbol = std::make_unique<DIARawSymbol>(*this, GlobalScope);
154174604Sscottl  auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
155174604Sscottl  std::unique_ptr<PDBSymbolExe> ExeSymbol(
156174604Sscottl      static_cast<PDBSymbolExe *>(PdbSymbol.release()));
157174604Sscottl  return ExeSymbol;
158174604Sscottl}
159174604Sscottl
160174604Sscottlbool DIASession::addressForVA(uint64_t VA, uint32_t &Section,
161174604Sscottl                              uint32_t &Offset) const {
162174604Sscottl  DWORD ArgSection, ArgOffset = 0;
163174604Sscottl  if (S_OK == Session->addressForVA(VA, &ArgSection, &ArgOffset)) {
164174604Sscottl    Section = static_cast<uint32_t>(ArgSection);
165174604Sscottl    Offset = static_cast<uint32_t>(ArgOffset);
166174604Sscottl    return true;
167174604Sscottl  }
168176018Sscottl  return false;
169174604Sscottl}
170176018Sscottl
171174604Sscottlbool DIASession::addressForRVA(uint32_t RVA, uint32_t &Section,
172174604Sscottl                               uint32_t &Offset) const {
173174604Sscottl  DWORD ArgSection, ArgOffset = 0;
174174604Sscottl  if (S_OK == Session->addressForRVA(RVA, &ArgSection, &ArgOffset)) {
175174604Sscottl    Section = static_cast<uint32_t>(ArgSection);
176174604Sscottl    Offset = static_cast<uint32_t>(ArgOffset);
177174604Sscottl    return true;
178174604Sscottl  }
179174604Sscottl  return false;
180174604Sscottl}
181174604Sscottl
182174604Sscottlstd::unique_ptr<PDBSymbol>
183174604SscottlDIASession::getSymbolById(SymIndexId SymbolId) const {
184174604Sscottl  CComPtr<IDiaSymbol> LocatedSymbol;
185174604Sscottl  if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol))
186174604Sscottl    return nullptr;
187174604Sscottl
188174604Sscottl  auto RawSymbol = std::make_unique<DIARawSymbol>(*this, LocatedSymbol);
189174604Sscottl  return PDBSymbol::create(*this, std::move(RawSymbol));
190174604Sscottl}
191174604Sscottl
192174604Sscottlstd::unique_ptr<PDBSymbol>
193174604SscottlDIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
194174604Sscottl  enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
195174604Sscottl
196174604Sscottl  CComPtr<IDiaSymbol> Symbol;
197174604Sscottl  if (S_OK != Session->findSymbolByVA(Address, EnumVal, &Symbol)) {
198174604Sscottl    ULONGLONG LoadAddr = 0;
199174604Sscottl    if (S_OK != Session->get_loadAddress(&LoadAddr))
200174604Sscottl      return nullptr;
201174604Sscottl    DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
202174604Sscottl    if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
203174604Sscottl      return nullptr;
204174604Sscottl  }
205174604Sscottl  auto RawSymbol = std::make_unique<DIARawSymbol>(*this, Symbol);
206174604Sscottl  return PDBSymbol::create(*this, std::move(RawSymbol));
207174604Sscottl}
208174604Sscottl
209174604Sscottlstd::unique_ptr<PDBSymbol> DIASession::findSymbolByRVA(uint32_t RVA,
210174604Sscottl                                                       PDB_SymType Type) const {
211174604Sscottl  enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
212174604Sscottl
213174604Sscottl  CComPtr<IDiaSymbol> Symbol;
214174604Sscottl  if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
215174604Sscottl    return nullptr;
216174604Sscottl
217174604Sscottl  auto RawSymbol = std::make_unique<DIARawSymbol>(*this, Symbol);
218174604Sscottl  return PDBSymbol::create(*this, std::move(RawSymbol));
219174604Sscottl}
220174604Sscottl
221174604Sscottlstd::unique_ptr<PDBSymbol>
222174604SscottlDIASession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
223174604Sscottl                                   PDB_SymType Type) const {
224174604Sscottl  enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
225174604Sscottl
226174604Sscottl  CComPtr<IDiaSymbol> Symbol;
227174604Sscottl  if (S_OK != Session->findSymbolByAddr(Sect, Offset, EnumVal, &Symbol))
228174604Sscottl    return nullptr;
229174604Sscottl
230174604Sscottl  auto RawSymbol = std::make_unique<DIARawSymbol>(*this, Symbol);
231174604Sscottl  return PDBSymbol::create(*this, std::move(RawSymbol));
232174604Sscottl}
233174604Sscottl
234174604Sscottlstd::unique_ptr<IPDBEnumLineNumbers>
235174604SscottlDIASession::findLineNumbers(const PDBSymbolCompiland &Compiland,
236174604Sscottl                            const IPDBSourceFile &File) const {
237174604Sscottl  const DIARawSymbol &RawCompiland =
238174604Sscottl      static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
239174604Sscottl  const DIASourceFile &RawFile = static_cast<const DIASourceFile &>(File);
240174604Sscottl
241174604Sscottl  CComPtr<IDiaEnumLineNumbers> LineNumbers;
242174604Sscottl  if (S_OK != Session->findLines(RawCompiland.getDiaSymbol(),
243174604Sscottl                                 RawFile.getDiaFile(), &LineNumbers))
244174604Sscottl    return nullptr;
245174604Sscottl
246174604Sscottl  return std::make_unique<DIAEnumLineNumbers>(LineNumbers);
247174604Sscottl}
248174604Sscottl
249174604Sscottlstd::unique_ptr<IPDBEnumLineNumbers>
250174604SscottlDIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
251174604Sscottl  CComPtr<IDiaEnumLineNumbers> LineNumbers;
252174604Sscottl  if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers)) {
253174604Sscottl    ULONGLONG LoadAddr = 0;
254174604Sscottl    if (S_OK != Session->get_loadAddress(&LoadAddr))
255174604Sscottl      return nullptr;
256174604Sscottl    DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
257174604Sscottl    if (S_OK != Session->findLinesByRVA(RVA, Length, &LineNumbers))
258174604Sscottl      return nullptr;
259174604Sscottl  }
260174604Sscottl  return std::make_unique<DIAEnumLineNumbers>(LineNumbers);
261174604Sscottl}
262174604Sscottl
263174604Sscottlstd::unique_ptr<IPDBEnumLineNumbers>
264174604SscottlDIASession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const {
265174604Sscottl  CComPtr<IDiaEnumLineNumbers> LineNumbers;
266174604Sscottl  if (S_OK != Session->findLinesByRVA(RVA, Length, &LineNumbers))
267174604Sscottl    return nullptr;
268174604Sscottl
269174604Sscottl  return std::make_unique<DIAEnumLineNumbers>(LineNumbers);
270174604Sscottl}
271174604Sscottl
272174604Sscottlstd::unique_ptr<IPDBEnumLineNumbers>
273174604SscottlDIASession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
274174604Sscottl                                        uint32_t Length) const {
275174604Sscottl  CComPtr<IDiaEnumLineNumbers> LineNumbers;
276174604Sscottl  if (S_OK != Session->findLinesByAddr(Section, Offset, Length, &LineNumbers))
277174604Sscottl    return nullptr;
278174604Sscottl
279174604Sscottl  return std::make_unique<DIAEnumLineNumbers>(LineNumbers);
280174604Sscottl}
281174604Sscottl
282174604Sscottlstd::unique_ptr<IPDBEnumSourceFiles>
283176018SscottlDIASession::findSourceFiles(const PDBSymbolCompiland *Compiland,
284174604Sscottl                            llvm::StringRef Pattern,
285174604Sscottl                            PDB_NameSearchFlags Flags) const {
286174604Sscottl  IDiaSymbol *DiaCompiland = nullptr;
287174604Sscottl  CComBSTR Utf16Pattern;
288174604Sscottl  if (!Pattern.empty())
289174604Sscottl    Utf16Pattern = CComBSTR(Pattern.data());
290174604Sscottl
291174604Sscottl  if (Compiland)
292174604Sscottl    DiaCompiland = static_cast<const DIARawSymbol &>(Compiland->getRawSymbol())
293174604Sscottl                       .getDiaSymbol();
294174604Sscottl
295174604Sscottl  Flags = static_cast<PDB_NameSearchFlags>(
296174604Sscottl      Flags | PDB_NameSearchFlags::NS_FileNameExtMatch);
297174604Sscottl  CComPtr<IDiaEnumSourceFiles> SourceFiles;
298174604Sscottl  if (S_OK !=
299174604Sscottl      Session->findFile(DiaCompiland, Utf16Pattern.m_str, Flags, &SourceFiles))
300174604Sscottl    return nullptr;
301174604Sscottl  return std::make_unique<DIAEnumSourceFiles>(*this, SourceFiles);
302174604Sscottl}
303174604Sscottl
304174604Sscottlstd::unique_ptr<IPDBSourceFile>
305174604SscottlDIASession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
306174604Sscottl                              llvm::StringRef Pattern,
307174604Sscottl                              PDB_NameSearchFlags Flags) const {
308174604Sscottl  auto SourceFiles = findSourceFiles(Compiland, Pattern, Flags);
309174604Sscottl  if (!SourceFiles || SourceFiles->getChildCount() == 0)
310174604Sscottl    return nullptr;
311174604Sscottl  return SourceFiles->getNext();
312174604Sscottl}
313174604Sscottl
314174604Sscottlstd::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
315176018SscottlDIASession::findCompilandsForSourceFile(llvm::StringRef Pattern,
316176018Sscottl                                        PDB_NameSearchFlags Flags) const {
317176018Sscottl  auto File = findOneSourceFile(nullptr, Pattern, Flags);
318176018Sscottl  if (!File)
319176018Sscottl    return nullptr;
320176018Sscottl  return File->getCompilands();
321176018Sscottl}
322176018Sscottl
323176018Sscottlstd::unique_ptr<PDBSymbolCompiland>
324174604SscottlDIASession::findOneCompilandForSourceFile(llvm::StringRef Pattern,
325174604Sscottl                                          PDB_NameSearchFlags Flags) const {
326174604Sscottl  auto Compilands = findCompilandsForSourceFile(Pattern, Flags);
327174604Sscottl  if (!Compilands || Compilands->getChildCount() == 0)
328174604Sscottl    return nullptr;
329174604Sscottl  return Compilands->getNext();
330174604Sscottl}
331174604Sscottl
332174604Sscottlstd::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
333174604Sscottl  CComPtr<IDiaEnumSourceFiles> Files;
334174604Sscottl  if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
335174604Sscottl    return nullptr;
336174604Sscottl
337174604Sscottl  return std::make_unique<DIAEnumSourceFiles>(*this, Files);
338174604Sscottl}
339174604Sscottl
340174604Sscottlstd::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland(
341174604Sscottl    const PDBSymbolCompiland &Compiland) const {
342174604Sscottl  CComPtr<IDiaEnumSourceFiles> Files;
343174604Sscottl
344174604Sscottl  const DIARawSymbol &RawSymbol =
345174604Sscottl      static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
346174604Sscottl  if (S_OK !=
347174604Sscottl      Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files))
348174604Sscottl    return nullptr;
349174604Sscottl
350174604Sscottl  return std::make_unique<DIAEnumSourceFiles>(*this, Files);
351174604Sscottl}
352174604Sscottl
353176018Sscottlstd::unique_ptr<IPDBSourceFile>
354176018SscottlDIASession::getSourceFileById(uint32_t FileId) const {
355174604Sscottl  CComPtr<IDiaSourceFile> LocatedFile;
356174604Sscottl  if (S_OK != Session->findFileById(FileId, &LocatedFile))
357174604Sscottl    return nullptr;
358174604Sscottl
359174604Sscottl  return std::make_unique<DIASourceFile>(*this, LocatedFile);
360174604Sscottl}
361174604Sscottl
362174604Sscottlstd::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
363174604Sscottl  CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
364176018Sscottl  if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
365176018Sscottl    return nullptr;
366174604Sscottl
367174604Sscottl  return std::make_unique<DIAEnumDebugStreams>(DiaEnumerator);
368174604Sscottl}
369174604Sscottl
370174604Sscottlstd::unique_ptr<IPDBEnumTables> DIASession::getEnumTables() const {
371174604Sscottl  CComPtr<IDiaEnumTables> DiaEnumerator;
372174604Sscottl  if (S_OK != Session->getEnumTables(&DiaEnumerator))
373174604Sscottl    return nullptr;
374174604Sscottl
375174604Sscottl  return std::make_unique<DIAEnumTables>(DiaEnumerator);
376174604Sscottl}
377174604Sscottl
378174604Sscottltemplate <class T> static CComPtr<T> getTableEnumerator(IDiaSession &Session) {
379174604Sscottl  CComPtr<T> Enumerator;
380174604Sscottl  CComPtr<IDiaEnumTables> ET;
381174604Sscottl  CComPtr<IDiaTable> Table;
382174604Sscottl  ULONG Count = 0;
383174604Sscottl
384174604Sscottl  if (Session.getEnumTables(&ET) != S_OK)
385174604Sscottl    return nullptr;
386174604Sscottl
387174604Sscottl  while (ET->Next(1, &Table, &Count) == S_OK && Count == 1) {
388174604Sscottl    // There is only one table that matches the given iid
389174604Sscottl    if (S_OK == Table->QueryInterface(__uuidof(T), (void **)&Enumerator))
390174604Sscottl      break;
391174604Sscottl    Table.Release();
392174604Sscottl  }
393174604Sscottl  return Enumerator;
394174604Sscottl}
395174604Sscottlstd::unique_ptr<IPDBEnumInjectedSources>
396174604SscottlDIASession::getInjectedSources() const {
397174604Sscottl  CComPtr<IDiaEnumInjectedSources> Files =
398174604Sscottl      getTableEnumerator<IDiaEnumInjectedSources>(*Session);
399174604Sscottl  if (!Files)
400174604Sscottl    return nullptr;
401174604Sscottl
402174604Sscottl  return std::make_unique<DIAEnumInjectedSources>(Files);
403174604Sscottl}
404174604Sscottl
405174604Sscottlstd::unique_ptr<IPDBEnumSectionContribs>
406174604SscottlDIASession::getSectionContribs() const {
407174604Sscottl  CComPtr<IDiaEnumSectionContribs> Sections =
408174604Sscottl      getTableEnumerator<IDiaEnumSectionContribs>(*Session);
409174604Sscottl  if (!Sections)
410174604Sscottl    return nullptr;
411174604Sscottl
412174604Sscottl  return std::make_unique<DIAEnumSectionContribs>(*this, Sections);
413174604Sscottl}
414174604Sscottl
415174604Sscottlstd::unique_ptr<IPDBEnumFrameData>
416174604SscottlDIASession::getFrameData() const {
417174604Sscottl  CComPtr<IDiaEnumFrameData> FD =
418174604Sscottl      getTableEnumerator<IDiaEnumFrameData>(*Session);
419174604Sscottl  if (!FD)
420174604Sscottl    return nullptr;
421174604Sscottl
422174604Sscottl  return std::make_unique<DIAEnumFrameData>(FD);
423174604Sscottl}
424174604Sscottl