xref: /freebsd-src/contrib/llvm-project/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp (revision e25152834cdf3b353892835a4f3b157e066a8ed4)
10b57cec5SDimitry Andric //===- DIASession.cpp - DIA implementation of IPDBSession -------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/DIA/DIASession.h"
90b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
100b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
110b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h"
120b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h"
130b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
140b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h"
150b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
160b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/DIA/DIAEnumTables.h"
170b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/DIA/DIAError.h"
180b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
190b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
200b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/DIA/DIASupport.h"
210b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/GenericError.h"
220b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDB.h"
230b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
240b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
250b57cec5SDimitry Andric #include "llvm/Support/ConvertUTF.h"
260b57cec5SDimitry Andric #include "llvm/Support/Format.h"
270b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h"
280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric using namespace llvm;
310b57cec5SDimitry Andric using namespace llvm::pdb;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric template <typename... Ts>
ErrorFromHResult(HRESULT Result,const char * Str,Ts &&...Args)340b57cec5SDimitry Andric static Error ErrorFromHResult(HRESULT Result, const char *Str, Ts &&... Args) {
350b57cec5SDimitry Andric   SmallString<64> MessageStorage;
360b57cec5SDimitry Andric   StringRef Context;
370b57cec5SDimitry Andric   if (sizeof...(Args) > 0) {
380b57cec5SDimitry Andric     MessageStorage = formatv(Str, std::forward<Ts>(Args)...).str();
390b57cec5SDimitry Andric     Context = MessageStorage;
400b57cec5SDimitry Andric   } else
410b57cec5SDimitry Andric     Context = Str;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   switch (Result) {
440b57cec5SDimitry Andric   case E_PDB_NOT_FOUND:
450b57cec5SDimitry Andric     return errorCodeToError(std::error_code(ENOENT, std::generic_category()));
460b57cec5SDimitry Andric   case E_PDB_FORMAT:
470b57cec5SDimitry Andric     return make_error<DIAError>(dia_error_code::invalid_file_format, Context);
480b57cec5SDimitry Andric   case E_INVALIDARG:
490b57cec5SDimitry Andric     return make_error<DIAError>(dia_error_code::invalid_parameter, Context);
500b57cec5SDimitry Andric   case E_UNEXPECTED:
510b57cec5SDimitry Andric     return make_error<DIAError>(dia_error_code::already_loaded, Context);
520b57cec5SDimitry Andric   case E_PDB_INVALID_SIG:
530b57cec5SDimitry Andric   case E_PDB_INVALID_AGE:
540b57cec5SDimitry Andric     return make_error<DIAError>(dia_error_code::debug_info_mismatch, Context);
550b57cec5SDimitry Andric   default: {
560b57cec5SDimitry Andric     std::string S;
570b57cec5SDimitry Andric     raw_string_ostream OS(S);
580b57cec5SDimitry Andric     OS << "HRESULT: " << format_hex(static_cast<DWORD>(Result), 10, true)
590b57cec5SDimitry Andric        << ": " << Context;
600b57cec5SDimitry Andric     return make_error<DIAError>(dia_error_code::unspecified, OS.str());
610b57cec5SDimitry Andric   }
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
LoadDIA(CComPtr<IDiaDataSource> & DiaDataSource)650b57cec5SDimitry Andric static Error LoadDIA(CComPtr<IDiaDataSource> &DiaDataSource) {
660b57cec5SDimitry Andric   if (SUCCEEDED(CoCreateInstance(CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER,
670b57cec5SDimitry Andric                                  IID_IDiaDataSource,
680b57cec5SDimitry Andric                                  reinterpret_cast<LPVOID *>(&DiaDataSource))))
690b57cec5SDimitry Andric     return Error::success();
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric // If the CoCreateInstance call above failed, msdia*.dll is not registered.
720b57cec5SDimitry Andric // Try loading the DLL corresponding to the #included DIA SDK.
730b57cec5SDimitry Andric #if !defined(_MSC_VER)
740b57cec5SDimitry Andric   return llvm::make_error<PDBError>(pdb_error_code::dia_failed_loading);
750b57cec5SDimitry Andric #else
768bcb0991SDimitry Andric   const wchar_t *msdia_dll = L"msdia140.dll";
770b57cec5SDimitry Andric   HRESULT HR;
780b57cec5SDimitry Andric   if (FAILED(HR = NoRegCoCreate(msdia_dll, CLSID_DiaSource, IID_IDiaDataSource,
790b57cec5SDimitry Andric                                 reinterpret_cast<LPVOID *>(&DiaDataSource))))
800b57cec5SDimitry Andric     return ErrorFromHResult(HR, "Calling NoRegCoCreate");
810b57cec5SDimitry Andric   return Error::success();
820b57cec5SDimitry Andric #endif
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
DIASession(CComPtr<IDiaSession> DiaSession)850b57cec5SDimitry Andric DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
860b57cec5SDimitry Andric 
createFromPdb(StringRef Path,std::unique_ptr<IPDBSession> & Session)870b57cec5SDimitry Andric Error DIASession::createFromPdb(StringRef Path,
880b57cec5SDimitry Andric                                 std::unique_ptr<IPDBSession> &Session) {
890b57cec5SDimitry Andric   CComPtr<IDiaDataSource> DiaDataSource;
900b57cec5SDimitry Andric   CComPtr<IDiaSession> DiaSession;
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   // We assume that CoInitializeEx has already been called by the executable.
930b57cec5SDimitry Andric   if (auto E = LoadDIA(DiaDataSource))
940b57cec5SDimitry Andric     return E;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   llvm::SmallVector<UTF16, 128> Path16;
970b57cec5SDimitry Andric   if (!llvm::convertUTF8ToUTF16String(Path, Path16))
980b57cec5SDimitry Andric     return make_error<PDBError>(pdb_error_code::invalid_utf8_path, Path);
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
1010b57cec5SDimitry Andric   HRESULT HR;
1020b57cec5SDimitry Andric   if (FAILED(HR = DiaDataSource->loadDataFromPdb(Path16Str))) {
1030b57cec5SDimitry Andric     return ErrorFromHResult(HR, "Calling loadDataFromPdb {0}", Path);
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   if (FAILED(HR = DiaDataSource->openSession(&DiaSession)))
1070b57cec5SDimitry Andric     return ErrorFromHResult(HR, "Calling openSession");
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   Session.reset(new DIASession(DiaSession));
1100b57cec5SDimitry Andric   return Error::success();
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric 
createFromExe(StringRef Path,std::unique_ptr<IPDBSession> & Session)1130b57cec5SDimitry Andric Error DIASession::createFromExe(StringRef Path,
1140b57cec5SDimitry Andric                                 std::unique_ptr<IPDBSession> &Session) {
1150b57cec5SDimitry Andric   CComPtr<IDiaDataSource> DiaDataSource;
1160b57cec5SDimitry Andric   CComPtr<IDiaSession> DiaSession;
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   // We assume that CoInitializeEx has already been called by the executable.
1190b57cec5SDimitry Andric   if (auto EC = LoadDIA(DiaDataSource))
1200b57cec5SDimitry Andric     return EC;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   llvm::SmallVector<UTF16, 128> Path16;
1230b57cec5SDimitry Andric   if (!llvm::convertUTF8ToUTF16String(Path, Path16))
1240b57cec5SDimitry Andric     return make_error<PDBError>(pdb_error_code::invalid_utf8_path, Path);
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
1270b57cec5SDimitry Andric   HRESULT HR;
1280b57cec5SDimitry Andric   if (FAILED(HR = DiaDataSource->loadDataForExe(Path16Str, nullptr, nullptr)))
1290b57cec5SDimitry Andric     return ErrorFromHResult(HR, "Calling loadDataForExe");
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   if (FAILED(HR = DiaDataSource->openSession(&DiaSession)))
1320b57cec5SDimitry Andric     return ErrorFromHResult(HR, "Calling openSession");
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   Session.reset(new DIASession(DiaSession));
1350b57cec5SDimitry Andric   return Error::success();
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
getLoadAddress() const1380b57cec5SDimitry Andric uint64_t DIASession::getLoadAddress() const {
1390b57cec5SDimitry Andric   uint64_t LoadAddress;
1400b57cec5SDimitry Andric   bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
1410b57cec5SDimitry Andric   return (success) ? LoadAddress : 0;
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
setLoadAddress(uint64_t Address)1440b57cec5SDimitry Andric bool DIASession::setLoadAddress(uint64_t Address) {
1450b57cec5SDimitry Andric   return (S_OK == Session->put_loadAddress(Address));
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
getGlobalScope()1480b57cec5SDimitry Andric std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() {
1490b57cec5SDimitry Andric   CComPtr<IDiaSymbol> GlobalScope;
1500b57cec5SDimitry Andric   if (S_OK != Session->get_globalScope(&GlobalScope))
1510b57cec5SDimitry Andric     return nullptr;
1520b57cec5SDimitry Andric 
1538bcb0991SDimitry Andric   auto RawSymbol = std::make_unique<DIARawSymbol>(*this, GlobalScope);
1540b57cec5SDimitry Andric   auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
1550b57cec5SDimitry Andric   std::unique_ptr<PDBSymbolExe> ExeSymbol(
1560b57cec5SDimitry Andric       static_cast<PDBSymbolExe *>(PdbSymbol.release()));
1570b57cec5SDimitry Andric   return ExeSymbol;
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric 
addressForVA(uint64_t VA,uint32_t & Section,uint32_t & Offset) const1600b57cec5SDimitry Andric bool DIASession::addressForVA(uint64_t VA, uint32_t &Section,
1610b57cec5SDimitry Andric                               uint32_t &Offset) const {
1620b57cec5SDimitry Andric   DWORD ArgSection, ArgOffset = 0;
1630b57cec5SDimitry Andric   if (S_OK == Session->addressForVA(VA, &ArgSection, &ArgOffset)) {
1640b57cec5SDimitry Andric     Section = static_cast<uint32_t>(ArgSection);
1650b57cec5SDimitry Andric     Offset = static_cast<uint32_t>(ArgOffset);
1660b57cec5SDimitry Andric     return true;
1670b57cec5SDimitry Andric   }
1680b57cec5SDimitry Andric   return false;
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
addressForRVA(uint32_t RVA,uint32_t & Section,uint32_t & Offset) const1710b57cec5SDimitry Andric bool DIASession::addressForRVA(uint32_t RVA, uint32_t &Section,
1720b57cec5SDimitry Andric                                uint32_t &Offset) const {
1730b57cec5SDimitry Andric   DWORD ArgSection, ArgOffset = 0;
1740b57cec5SDimitry Andric   if (S_OK == Session->addressForRVA(RVA, &ArgSection, &ArgOffset)) {
1750b57cec5SDimitry Andric     Section = static_cast<uint32_t>(ArgSection);
1760b57cec5SDimitry Andric     Offset = static_cast<uint32_t>(ArgOffset);
1770b57cec5SDimitry Andric     return true;
1780b57cec5SDimitry Andric   }
1790b57cec5SDimitry Andric   return false;
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric std::unique_ptr<PDBSymbol>
getSymbolById(SymIndexId SymbolId) const1830b57cec5SDimitry Andric DIASession::getSymbolById(SymIndexId SymbolId) const {
1840b57cec5SDimitry Andric   CComPtr<IDiaSymbol> LocatedSymbol;
1850b57cec5SDimitry Andric   if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol))
1860b57cec5SDimitry Andric     return nullptr;
1870b57cec5SDimitry Andric 
1888bcb0991SDimitry Andric   auto RawSymbol = std::make_unique<DIARawSymbol>(*this, LocatedSymbol);
1890b57cec5SDimitry Andric   return PDBSymbol::create(*this, std::move(RawSymbol));
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric 
findSymbolByAddress(uint64_t Address,PDB_SymType Type)192*5ffd83dbSDimitry Andric std::unique_ptr<PDBSymbol> DIASession::findSymbolByAddress(uint64_t Address,
193*5ffd83dbSDimitry Andric                                                            PDB_SymType Type) {
1940b57cec5SDimitry Andric   enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric   CComPtr<IDiaSymbol> Symbol;
1970b57cec5SDimitry Andric   if (S_OK != Session->findSymbolByVA(Address, EnumVal, &Symbol)) {
1980b57cec5SDimitry Andric     ULONGLONG LoadAddr = 0;
1990b57cec5SDimitry Andric     if (S_OK != Session->get_loadAddress(&LoadAddr))
2000b57cec5SDimitry Andric       return nullptr;
2010b57cec5SDimitry Andric     DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
2020b57cec5SDimitry Andric     if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
2030b57cec5SDimitry Andric       return nullptr;
2040b57cec5SDimitry Andric   }
2058bcb0991SDimitry Andric   auto RawSymbol = std::make_unique<DIARawSymbol>(*this, Symbol);
2060b57cec5SDimitry Andric   return PDBSymbol::create(*this, std::move(RawSymbol));
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric 
findSymbolByRVA(uint32_t RVA,PDB_SymType Type)2090b57cec5SDimitry Andric std::unique_ptr<PDBSymbol> DIASession::findSymbolByRVA(uint32_t RVA,
210*5ffd83dbSDimitry Andric                                                        PDB_SymType Type) {
2110b57cec5SDimitry Andric   enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   CComPtr<IDiaSymbol> Symbol;
2140b57cec5SDimitry Andric   if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
2150b57cec5SDimitry Andric     return nullptr;
2160b57cec5SDimitry Andric 
2178bcb0991SDimitry Andric   auto RawSymbol = std::make_unique<DIARawSymbol>(*this, Symbol);
2180b57cec5SDimitry Andric   return PDBSymbol::create(*this, std::move(RawSymbol));
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric std::unique_ptr<PDBSymbol>
findSymbolBySectOffset(uint32_t Sect,uint32_t Offset,PDB_SymType Type)2220b57cec5SDimitry Andric DIASession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
223*5ffd83dbSDimitry Andric                                    PDB_SymType Type) {
2240b57cec5SDimitry Andric   enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   CComPtr<IDiaSymbol> Symbol;
2270b57cec5SDimitry Andric   if (S_OK != Session->findSymbolByAddr(Sect, Offset, EnumVal, &Symbol))
2280b57cec5SDimitry Andric     return nullptr;
2290b57cec5SDimitry Andric 
2308bcb0991SDimitry Andric   auto RawSymbol = std::make_unique<DIARawSymbol>(*this, Symbol);
2310b57cec5SDimitry Andric   return PDBSymbol::create(*this, std::move(RawSymbol));
2320b57cec5SDimitry Andric }
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbers(const PDBSymbolCompiland & Compiland,const IPDBSourceFile & File) const2350b57cec5SDimitry Andric DIASession::findLineNumbers(const PDBSymbolCompiland &Compiland,
2360b57cec5SDimitry Andric                             const IPDBSourceFile &File) const {
2370b57cec5SDimitry Andric   const DIARawSymbol &RawCompiland =
2380b57cec5SDimitry Andric       static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
2390b57cec5SDimitry Andric   const DIASourceFile &RawFile = static_cast<const DIASourceFile &>(File);
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   CComPtr<IDiaEnumLineNumbers> LineNumbers;
2420b57cec5SDimitry Andric   if (S_OK != Session->findLines(RawCompiland.getDiaSymbol(),
2430b57cec5SDimitry Andric                                  RawFile.getDiaFile(), &LineNumbers))
2440b57cec5SDimitry Andric     return nullptr;
2450b57cec5SDimitry Andric 
2468bcb0991SDimitry Andric   return std::make_unique<DIAEnumLineNumbers>(LineNumbers);
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbersByAddress(uint64_t Address,uint32_t Length) const2500b57cec5SDimitry Andric DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
2510b57cec5SDimitry Andric   CComPtr<IDiaEnumLineNumbers> LineNumbers;
2520b57cec5SDimitry Andric   if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers)) {
2530b57cec5SDimitry Andric     ULONGLONG LoadAddr = 0;
2540b57cec5SDimitry Andric     if (S_OK != Session->get_loadAddress(&LoadAddr))
2550b57cec5SDimitry Andric       return nullptr;
2560b57cec5SDimitry Andric     DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
2570b57cec5SDimitry Andric     if (S_OK != Session->findLinesByRVA(RVA, Length, &LineNumbers))
2580b57cec5SDimitry Andric       return nullptr;
2590b57cec5SDimitry Andric   }
2608bcb0991SDimitry Andric   return std::make_unique<DIAEnumLineNumbers>(LineNumbers);
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbersByRVA(uint32_t RVA,uint32_t Length) const2640b57cec5SDimitry Andric DIASession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const {
2650b57cec5SDimitry Andric   CComPtr<IDiaEnumLineNumbers> LineNumbers;
2660b57cec5SDimitry Andric   if (S_OK != Session->findLinesByRVA(RVA, Length, &LineNumbers))
2670b57cec5SDimitry Andric     return nullptr;
2680b57cec5SDimitry Andric 
2698bcb0991SDimitry Andric   return std::make_unique<DIAEnumLineNumbers>(LineNumbers);
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbersBySectOffset(uint32_t Section,uint32_t Offset,uint32_t Length) const2730b57cec5SDimitry Andric DIASession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
2740b57cec5SDimitry Andric                                         uint32_t Length) const {
2750b57cec5SDimitry Andric   CComPtr<IDiaEnumLineNumbers> LineNumbers;
2760b57cec5SDimitry Andric   if (S_OK != Session->findLinesByAddr(Section, Offset, Length, &LineNumbers))
2770b57cec5SDimitry Andric     return nullptr;
2780b57cec5SDimitry Andric 
2798bcb0991SDimitry Andric   return std::make_unique<DIAEnumLineNumbers>(LineNumbers);
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric std::unique_ptr<IPDBEnumSourceFiles>
findSourceFiles(const PDBSymbolCompiland * Compiland,llvm::StringRef Pattern,PDB_NameSearchFlags Flags) const2830b57cec5SDimitry Andric DIASession::findSourceFiles(const PDBSymbolCompiland *Compiland,
2840b57cec5SDimitry Andric                             llvm::StringRef Pattern,
2850b57cec5SDimitry Andric                             PDB_NameSearchFlags Flags) const {
2860b57cec5SDimitry Andric   IDiaSymbol *DiaCompiland = nullptr;
2870b57cec5SDimitry Andric   CComBSTR Utf16Pattern;
2880b57cec5SDimitry Andric   if (!Pattern.empty())
2890b57cec5SDimitry Andric     Utf16Pattern = CComBSTR(Pattern.data());
2900b57cec5SDimitry Andric 
2910b57cec5SDimitry Andric   if (Compiland)
2920b57cec5SDimitry Andric     DiaCompiland = static_cast<const DIARawSymbol &>(Compiland->getRawSymbol())
2930b57cec5SDimitry Andric                        .getDiaSymbol();
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   Flags = static_cast<PDB_NameSearchFlags>(
2960b57cec5SDimitry Andric       Flags | PDB_NameSearchFlags::NS_FileNameExtMatch);
2970b57cec5SDimitry Andric   CComPtr<IDiaEnumSourceFiles> SourceFiles;
2980b57cec5SDimitry Andric   if (S_OK !=
2990b57cec5SDimitry Andric       Session->findFile(DiaCompiland, Utf16Pattern.m_str, Flags, &SourceFiles))
3000b57cec5SDimitry Andric     return nullptr;
3018bcb0991SDimitry Andric   return std::make_unique<DIAEnumSourceFiles>(*this, SourceFiles);
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric std::unique_ptr<IPDBSourceFile>
findOneSourceFile(const PDBSymbolCompiland * Compiland,llvm::StringRef Pattern,PDB_NameSearchFlags Flags) const3050b57cec5SDimitry Andric DIASession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
3060b57cec5SDimitry Andric                               llvm::StringRef Pattern,
3070b57cec5SDimitry Andric                               PDB_NameSearchFlags Flags) const {
3080b57cec5SDimitry Andric   auto SourceFiles = findSourceFiles(Compiland, Pattern, Flags);
3090b57cec5SDimitry Andric   if (!SourceFiles || SourceFiles->getChildCount() == 0)
3100b57cec5SDimitry Andric     return nullptr;
3110b57cec5SDimitry Andric   return SourceFiles->getNext();
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
findCompilandsForSourceFile(llvm::StringRef Pattern,PDB_NameSearchFlags Flags) const3150b57cec5SDimitry Andric DIASession::findCompilandsForSourceFile(llvm::StringRef Pattern,
3160b57cec5SDimitry Andric                                         PDB_NameSearchFlags Flags) const {
3170b57cec5SDimitry Andric   auto File = findOneSourceFile(nullptr, Pattern, Flags);
3180b57cec5SDimitry Andric   if (!File)
3190b57cec5SDimitry Andric     return nullptr;
3200b57cec5SDimitry Andric   return File->getCompilands();
3210b57cec5SDimitry Andric }
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric std::unique_ptr<PDBSymbolCompiland>
findOneCompilandForSourceFile(llvm::StringRef Pattern,PDB_NameSearchFlags Flags) const3240b57cec5SDimitry Andric DIASession::findOneCompilandForSourceFile(llvm::StringRef Pattern,
3250b57cec5SDimitry Andric                                           PDB_NameSearchFlags Flags) const {
3260b57cec5SDimitry Andric   auto Compilands = findCompilandsForSourceFile(Pattern, Flags);
3270b57cec5SDimitry Andric   if (!Compilands || Compilands->getChildCount() == 0)
3280b57cec5SDimitry Andric     return nullptr;
3290b57cec5SDimitry Andric   return Compilands->getNext();
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric 
getAllSourceFiles() const3320b57cec5SDimitry Andric std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
3330b57cec5SDimitry Andric   CComPtr<IDiaEnumSourceFiles> Files;
3340b57cec5SDimitry Andric   if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
3350b57cec5SDimitry Andric     return nullptr;
3360b57cec5SDimitry Andric 
3378bcb0991SDimitry Andric   return std::make_unique<DIAEnumSourceFiles>(*this, Files);
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric 
getSourceFilesForCompiland(const PDBSymbolCompiland & Compiland) const3400b57cec5SDimitry Andric std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland(
3410b57cec5SDimitry Andric     const PDBSymbolCompiland &Compiland) const {
3420b57cec5SDimitry Andric   CComPtr<IDiaEnumSourceFiles> Files;
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   const DIARawSymbol &RawSymbol =
3450b57cec5SDimitry Andric       static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
3460b57cec5SDimitry Andric   if (S_OK !=
3470b57cec5SDimitry Andric       Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files))
3480b57cec5SDimitry Andric     return nullptr;
3490b57cec5SDimitry Andric 
3508bcb0991SDimitry Andric   return std::make_unique<DIAEnumSourceFiles>(*this, Files);
3510b57cec5SDimitry Andric }
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric std::unique_ptr<IPDBSourceFile>
getSourceFileById(uint32_t FileId) const3540b57cec5SDimitry Andric DIASession::getSourceFileById(uint32_t FileId) const {
3550b57cec5SDimitry Andric   CComPtr<IDiaSourceFile> LocatedFile;
3560b57cec5SDimitry Andric   if (S_OK != Session->findFileById(FileId, &LocatedFile))
3570b57cec5SDimitry Andric     return nullptr;
3580b57cec5SDimitry Andric 
3598bcb0991SDimitry Andric   return std::make_unique<DIASourceFile>(*this, LocatedFile);
3600b57cec5SDimitry Andric }
3610b57cec5SDimitry Andric 
getDebugStreams() const3620b57cec5SDimitry Andric std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
3630b57cec5SDimitry Andric   CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
3640b57cec5SDimitry Andric   if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
3650b57cec5SDimitry Andric     return nullptr;
3660b57cec5SDimitry Andric 
3678bcb0991SDimitry Andric   return std::make_unique<DIAEnumDebugStreams>(DiaEnumerator);
3680b57cec5SDimitry Andric }
3690b57cec5SDimitry Andric 
getEnumTables() const3700b57cec5SDimitry Andric std::unique_ptr<IPDBEnumTables> DIASession::getEnumTables() const {
3710b57cec5SDimitry Andric   CComPtr<IDiaEnumTables> DiaEnumerator;
3720b57cec5SDimitry Andric   if (S_OK != Session->getEnumTables(&DiaEnumerator))
3730b57cec5SDimitry Andric     return nullptr;
3740b57cec5SDimitry Andric 
3758bcb0991SDimitry Andric   return std::make_unique<DIAEnumTables>(DiaEnumerator);
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric 
getTableEnumerator(IDiaSession & Session)3780b57cec5SDimitry Andric template <class T> static CComPtr<T> getTableEnumerator(IDiaSession &Session) {
3790b57cec5SDimitry Andric   CComPtr<T> Enumerator;
3800b57cec5SDimitry Andric   CComPtr<IDiaEnumTables> ET;
3810b57cec5SDimitry Andric   CComPtr<IDiaTable> Table;
3820b57cec5SDimitry Andric   ULONG Count = 0;
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   if (Session.getEnumTables(&ET) != S_OK)
3850b57cec5SDimitry Andric     return nullptr;
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   while (ET->Next(1, &Table, &Count) == S_OK && Count == 1) {
3880b57cec5SDimitry Andric     // There is only one table that matches the given iid
3890b57cec5SDimitry Andric     if (S_OK == Table->QueryInterface(__uuidof(T), (void **)&Enumerator))
3900b57cec5SDimitry Andric       break;
3910b57cec5SDimitry Andric     Table.Release();
3920b57cec5SDimitry Andric   }
3930b57cec5SDimitry Andric   return Enumerator;
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric std::unique_ptr<IPDBEnumInjectedSources>
getInjectedSources() const3960b57cec5SDimitry Andric DIASession::getInjectedSources() const {
3970b57cec5SDimitry Andric   CComPtr<IDiaEnumInjectedSources> Files =
3980b57cec5SDimitry Andric       getTableEnumerator<IDiaEnumInjectedSources>(*Session);
3990b57cec5SDimitry Andric   if (!Files)
4000b57cec5SDimitry Andric     return nullptr;
4010b57cec5SDimitry Andric 
4028bcb0991SDimitry Andric   return std::make_unique<DIAEnumInjectedSources>(Files);
4030b57cec5SDimitry Andric }
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric std::unique_ptr<IPDBEnumSectionContribs>
getSectionContribs() const4060b57cec5SDimitry Andric DIASession::getSectionContribs() const {
4070b57cec5SDimitry Andric   CComPtr<IDiaEnumSectionContribs> Sections =
4080b57cec5SDimitry Andric       getTableEnumerator<IDiaEnumSectionContribs>(*Session);
4090b57cec5SDimitry Andric   if (!Sections)
4100b57cec5SDimitry Andric     return nullptr;
4110b57cec5SDimitry Andric 
4128bcb0991SDimitry Andric   return std::make_unique<DIAEnumSectionContribs>(*this, Sections);
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric std::unique_ptr<IPDBEnumFrameData>
getFrameData() const4160b57cec5SDimitry Andric DIASession::getFrameData() const {
4170b57cec5SDimitry Andric   CComPtr<IDiaEnumFrameData> FD =
4180b57cec5SDimitry Andric       getTableEnumerator<IDiaEnumFrameData>(*Session);
4190b57cec5SDimitry Andric   if (!FD)
4200b57cec5SDimitry Andric     return nullptr;
4210b57cec5SDimitry Andric 
4228bcb0991SDimitry Andric   return std::make_unique<DIAEnumFrameData>(FD);
4230b57cec5SDimitry Andric }
424