16b6b8c4fSAdrian McCarthy //===- NativeSession.cpp - Native implementation of IPDBSession -*- C++ -*-===//
26b6b8c4fSAdrian McCarthy //
36b6b8c4fSAdrian McCarthy //                     The LLVM Compiler Infrastructure
46b6b8c4fSAdrian McCarthy //
56b6b8c4fSAdrian McCarthy // This file is distributed under the University of Illinois Open Source
66b6b8c4fSAdrian McCarthy // License. See LICENSE.TXT for details.
76b6b8c4fSAdrian McCarthy //
86b6b8c4fSAdrian McCarthy //===----------------------------------------------------------------------===//
96b6b8c4fSAdrian McCarthy 
106b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
116b6b8c4fSAdrian McCarthy 
126b6b8c4fSAdrian McCarthy #include "llvm/ADT/STLExtras.h"
138d090fc5SAdrian McCarthy #include "llvm/DebugInfo/CodeView/TypeIndex.h"
146b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/GenericError.h"
156b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
166b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
178d090fc5SAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h"
18bf0afc32SAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
19b41f03e7SAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h"
20b41f03e7SAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
214d93d66dSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
226b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
236b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/RawError.h"
24b41f03e7SAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
256b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
266b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
27b41f03e7SAdrian McCarthy #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
286b6b8c4fSAdrian McCarthy #include "llvm/Support/Allocator.h"
29d9dc2829SZachary Turner #include "llvm/Support/BinaryByteStream.h"
306b6b8c4fSAdrian McCarthy #include "llvm/Support/Error.h"
316b6b8c4fSAdrian McCarthy #include "llvm/Support/ErrorOr.h"
326b6b8c4fSAdrian McCarthy #include "llvm/Support/MemoryBuffer.h"
33bf0afc32SAdrian McCarthy 
346b6b8c4fSAdrian McCarthy #include <algorithm>
35b41f03e7SAdrian McCarthy #include <cassert>
366b6b8c4fSAdrian McCarthy #include <memory>
37bf0afc32SAdrian McCarthy #include <utility>
386b6b8c4fSAdrian McCarthy 
396b6b8c4fSAdrian McCarthy using namespace llvm;
406b6b8c4fSAdrian McCarthy using namespace llvm::msf;
416b6b8c4fSAdrian McCarthy using namespace llvm::pdb;
426b6b8c4fSAdrian McCarthy 
438d090fc5SAdrian McCarthy namespace {
448d090fc5SAdrian McCarthy // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
458d090fc5SAdrian McCarthy // to instantiate a NativeBuiltinSymbol for that type.
460962cb2eSReid Kleckner static const struct BuiltinTypeEntry {
478d090fc5SAdrian McCarthy   codeview::SimpleTypeKind Kind;
488d090fc5SAdrian McCarthy   PDB_BuiltinType Type;
498d090fc5SAdrian McCarthy   uint32_t Size;
508d090fc5SAdrian McCarthy } BuiltinTypes[] = {
518d090fc5SAdrian McCarthy     {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
528d090fc5SAdrian McCarthy     {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
538d090fc5SAdrian McCarthy     {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
548d090fc5SAdrian McCarthy     {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
558d090fc5SAdrian McCarthy     {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
568d090fc5SAdrian McCarthy     {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
578d090fc5SAdrian McCarthy     {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
588d090fc5SAdrian McCarthy     {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
598d090fc5SAdrian McCarthy     {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}
608d090fc5SAdrian McCarthy     // This table can be grown as necessary, but these are the only types we've
618d090fc5SAdrian McCarthy     // needed so far.
628d090fc5SAdrian McCarthy };
638d090fc5SAdrian McCarthy } // namespace
648d090fc5SAdrian McCarthy 
656b6b8c4fSAdrian McCarthy NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile,
666b6b8c4fSAdrian McCarthy                              std::unique_ptr<BumpPtrAllocator> Allocator)
676b6b8c4fSAdrian McCarthy     : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)) {}
686b6b8c4fSAdrian McCarthy 
696b6b8c4fSAdrian McCarthy NativeSession::~NativeSession() = default;
706b6b8c4fSAdrian McCarthy 
7175257bc2SPeter Collingbourne Error NativeSession::createFromPdb(std::unique_ptr<MemoryBuffer> Buffer,
726b6b8c4fSAdrian McCarthy                                    std::unique_ptr<IPDBSession> &Session) {
7375257bc2SPeter Collingbourne   StringRef Path = Buffer->getBufferIdentifier();
74695ed56bSZachary Turner   auto Stream = llvm::make_unique<MemoryBufferByteStream>(
75695ed56bSZachary Turner       std::move(Buffer), llvm::support::little);
766b6b8c4fSAdrian McCarthy 
776b6b8c4fSAdrian McCarthy   auto Allocator = llvm::make_unique<BumpPtrAllocator>();
787b327d05SZachary Turner   auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), *Allocator);
796b6b8c4fSAdrian McCarthy   if (auto EC = File->parseFileHeaders())
806b6b8c4fSAdrian McCarthy     return EC;
816b6b8c4fSAdrian McCarthy   if (auto EC = File->parseStreamData())
826b6b8c4fSAdrian McCarthy     return EC;
836b6b8c4fSAdrian McCarthy 
846b6b8c4fSAdrian McCarthy   Session =
856b6b8c4fSAdrian McCarthy       llvm::make_unique<NativeSession>(std::move(File), std::move(Allocator));
866b6b8c4fSAdrian McCarthy 
876b6b8c4fSAdrian McCarthy   return Error::success();
886b6b8c4fSAdrian McCarthy }
896b6b8c4fSAdrian McCarthy 
906b6b8c4fSAdrian McCarthy Error NativeSession::createFromExe(StringRef Path,
916b6b8c4fSAdrian McCarthy                                    std::unique_ptr<IPDBSession> &Session) {
926b6b8c4fSAdrian McCarthy   return make_error<RawError>(raw_error_code::feature_unsupported);
936b6b8c4fSAdrian McCarthy }
946b6b8c4fSAdrian McCarthy 
95bf0afc32SAdrian McCarthy std::unique_ptr<PDBSymbolCompiland>
96bf0afc32SAdrian McCarthy NativeSession::createCompilandSymbol(DbiModuleDescriptor MI) {
978d090fc5SAdrian McCarthy   const auto Id = static_cast<SymIndexId>(SymbolCache.size());
98bf0afc32SAdrian McCarthy   SymbolCache.push_back(
99bf0afc32SAdrian McCarthy       llvm::make_unique<NativeCompilandSymbol>(*this, Id, MI));
100bf0afc32SAdrian McCarthy   return llvm::make_unique<PDBSymbolCompiland>(
101bf0afc32SAdrian McCarthy       *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone()));
102bf0afc32SAdrian McCarthy }
103bf0afc32SAdrian McCarthy 
104b41f03e7SAdrian McCarthy std::unique_ptr<PDBSymbolTypeEnum>
105b41f03e7SAdrian McCarthy NativeSession::createEnumSymbol(codeview::TypeIndex Index) {
106b41f03e7SAdrian McCarthy   const auto Id = findSymbolByTypeIndex(Index);
107b41f03e7SAdrian McCarthy   return llvm::make_unique<PDBSymbolTypeEnum>(
108b41f03e7SAdrian McCarthy       *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone()));
109b41f03e7SAdrian McCarthy }
110b41f03e7SAdrian McCarthy 
111b41f03e7SAdrian McCarthy std::unique_ptr<IPDBEnumSymbols>
112b41f03e7SAdrian McCarthy NativeSession::createTypeEnumerator(codeview::TypeLeafKind Kind) {
113b41f03e7SAdrian McCarthy   auto Tpi = Pdb->getPDBTpiStream();
114b41f03e7SAdrian McCarthy   if (!Tpi) {
115b41f03e7SAdrian McCarthy     consumeError(Tpi.takeError());
116b41f03e7SAdrian McCarthy     return nullptr;
117b41f03e7SAdrian McCarthy   }
118b41f03e7SAdrian McCarthy   auto &Types = Tpi->typeCollection();
119b41f03e7SAdrian McCarthy   return std::unique_ptr<IPDBEnumSymbols>(
120b41f03e7SAdrian McCarthy       new NativeEnumTypes(*this, Types, codeview::LF_ENUM));
121b41f03e7SAdrian McCarthy }
122b41f03e7SAdrian McCarthy 
1238d090fc5SAdrian McCarthy SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) {
1248d090fc5SAdrian McCarthy   // First see if it's already in our cache.
1258d090fc5SAdrian McCarthy   const auto Entry = TypeIndexToSymbolId.find(Index);
1268d090fc5SAdrian McCarthy   if (Entry != TypeIndexToSymbolId.end())
1278d090fc5SAdrian McCarthy     return Entry->second;
1288d090fc5SAdrian McCarthy 
1298d090fc5SAdrian McCarthy   // Symbols for built-in types are created on the fly.
1308d090fc5SAdrian McCarthy   if (Index.isSimple()) {
1318d090fc5SAdrian McCarthy     // FIXME:  We will eventually need to handle pointers to other simple types,
1328d090fc5SAdrian McCarthy     // which are still simple types in the world of CodeView TypeIndexes.
1338d090fc5SAdrian McCarthy     if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
1348d090fc5SAdrian McCarthy       return 0;
1358d090fc5SAdrian McCarthy     const auto Kind = Index.getSimpleKind();
1360962cb2eSReid Kleckner     const auto It =
1370962cb2eSReid Kleckner         std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes),
1380962cb2eSReid Kleckner                      [Kind](const BuiltinTypeEntry &Builtin) {
1390962cb2eSReid Kleckner                        return Builtin.Kind == Kind;
1400962cb2eSReid Kleckner                      });
1418d090fc5SAdrian McCarthy     if (It == std::end(BuiltinTypes))
1428d090fc5SAdrian McCarthy       return 0;
1438d090fc5SAdrian McCarthy     SymIndexId Id = SymbolCache.size();
1448d090fc5SAdrian McCarthy     SymbolCache.emplace_back(
1450962cb2eSReid Kleckner         llvm::make_unique<NativeBuiltinSymbol>(*this, Id, It->Type, It->Size));
1468d090fc5SAdrian McCarthy     TypeIndexToSymbolId[Index] = Id;
1478d090fc5SAdrian McCarthy     return Id;
1488d090fc5SAdrian McCarthy   }
1498d090fc5SAdrian McCarthy 
150b41f03e7SAdrian McCarthy   // We need to instantiate and cache the desired type symbol.
151b41f03e7SAdrian McCarthy   auto Tpi = Pdb->getPDBTpiStream();
152b41f03e7SAdrian McCarthy   if (!Tpi) {
153b41f03e7SAdrian McCarthy     consumeError(Tpi.takeError());
1548d090fc5SAdrian McCarthy     return 0;
1558d090fc5SAdrian McCarthy   }
156b41f03e7SAdrian McCarthy   auto &Types = Tpi->typeCollection();
157b41f03e7SAdrian McCarthy   const auto &I = Types.getType(Index);
158b41f03e7SAdrian McCarthy   const auto Id = static_cast<SymIndexId>(SymbolCache.size());
159b41f03e7SAdrian McCarthy   // TODO(amccarth):  Make this handle all types, not just LF_ENUMs.
160b41f03e7SAdrian McCarthy   assert(I.kind() == codeview::LF_ENUM);
161b41f03e7SAdrian McCarthy   SymbolCache.emplace_back(llvm::make_unique<NativeEnumSymbol>(*this, Id, I));
162b41f03e7SAdrian McCarthy   TypeIndexToSymbolId[Index] = Id;
163b41f03e7SAdrian McCarthy   return Id;
164b41f03e7SAdrian McCarthy }
1658d090fc5SAdrian McCarthy 
1666b6b8c4fSAdrian McCarthy uint64_t NativeSession::getLoadAddress() const { return 0; }
1676b6b8c4fSAdrian McCarthy 
168*89a19ac3SAaron Smith bool NativeSession::setLoadAddress(uint64_t Address) { return false; }
1696b6b8c4fSAdrian McCarthy 
1706a4b080aSAdrian McCarthy std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() {
1718d090fc5SAdrian McCarthy   const auto Id = static_cast<SymIndexId>(SymbolCache.size());
172bf0afc32SAdrian McCarthy   SymbolCache.push_back(llvm::make_unique<NativeExeSymbol>(*this, Id));
173bf0afc32SAdrian McCarthy   auto RawSymbol = SymbolCache[Id]->clone();
174649b8e0cSAdrian McCarthy   auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
175649b8e0cSAdrian McCarthy   std::unique_ptr<PDBSymbolExe> ExeSymbol(
176649b8e0cSAdrian McCarthy       static_cast<PDBSymbolExe *>(PdbSymbol.release()));
177649b8e0cSAdrian McCarthy   return ExeSymbol;
1786b6b8c4fSAdrian McCarthy }
1796b6b8c4fSAdrian McCarthy 
1806b6b8c4fSAdrian McCarthy std::unique_ptr<PDBSymbol>
1816b6b8c4fSAdrian McCarthy NativeSession::getSymbolById(uint32_t SymbolId) const {
182bf0afc32SAdrian McCarthy   // If the caller has a SymbolId, it'd better be in our SymbolCache.
183bf0afc32SAdrian McCarthy   return SymbolId < SymbolCache.size()
184bf0afc32SAdrian McCarthy              ? PDBSymbol::create(*this, SymbolCache[SymbolId]->clone())
185bf0afc32SAdrian McCarthy              : nullptr;
1866b6b8c4fSAdrian McCarthy }
1876b6b8c4fSAdrian McCarthy 
1886b6b8c4fSAdrian McCarthy std::unique_ptr<PDBSymbol>
1896b6b8c4fSAdrian McCarthy NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
1906b6b8c4fSAdrian McCarthy   return nullptr;
1916b6b8c4fSAdrian McCarthy }
1926b6b8c4fSAdrian McCarthy 
1936b6b8c4fSAdrian McCarthy std::unique_ptr<IPDBEnumLineNumbers>
1946b6b8c4fSAdrian McCarthy NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland,
1956b6b8c4fSAdrian McCarthy                                const IPDBSourceFile &File) const {
1966b6b8c4fSAdrian McCarthy   return nullptr;
1976b6b8c4fSAdrian McCarthy }
1986b6b8c4fSAdrian McCarthy 
1996b6b8c4fSAdrian McCarthy std::unique_ptr<IPDBEnumLineNumbers>
2006b6b8c4fSAdrian McCarthy NativeSession::findLineNumbersByAddress(uint64_t Address,
2016b6b8c4fSAdrian McCarthy                                         uint32_t Length) const {
2026b6b8c4fSAdrian McCarthy   return nullptr;
2036b6b8c4fSAdrian McCarthy }
2046b6b8c4fSAdrian McCarthy 
2056b6b8c4fSAdrian McCarthy std::unique_ptr<IPDBEnumSourceFiles>
2066b6b8c4fSAdrian McCarthy NativeSession::findSourceFiles(const PDBSymbolCompiland *Compiland,
2076b6b8c4fSAdrian McCarthy                                StringRef Pattern,
2086b6b8c4fSAdrian McCarthy                                PDB_NameSearchFlags Flags) const {
2096b6b8c4fSAdrian McCarthy   return nullptr;
2106b6b8c4fSAdrian McCarthy }
2116b6b8c4fSAdrian McCarthy 
2126b6b8c4fSAdrian McCarthy std::unique_ptr<IPDBSourceFile>
2136b6b8c4fSAdrian McCarthy NativeSession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
2146b6b8c4fSAdrian McCarthy                                  StringRef Pattern,
2156b6b8c4fSAdrian McCarthy                                  PDB_NameSearchFlags Flags) const {
2166b6b8c4fSAdrian McCarthy   return nullptr;
2176b6b8c4fSAdrian McCarthy }
2186b6b8c4fSAdrian McCarthy 
2196b6b8c4fSAdrian McCarthy std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
2206b6b8c4fSAdrian McCarthy NativeSession::findCompilandsForSourceFile(StringRef Pattern,
2216b6b8c4fSAdrian McCarthy                                            PDB_NameSearchFlags Flags) const {
2226b6b8c4fSAdrian McCarthy   return nullptr;
2236b6b8c4fSAdrian McCarthy }
2246b6b8c4fSAdrian McCarthy 
2256b6b8c4fSAdrian McCarthy std::unique_ptr<PDBSymbolCompiland>
2266b6b8c4fSAdrian McCarthy NativeSession::findOneCompilandForSourceFile(StringRef Pattern,
2276b6b8c4fSAdrian McCarthy                                              PDB_NameSearchFlags Flags) const {
2286b6b8c4fSAdrian McCarthy   return nullptr;
2296b6b8c4fSAdrian McCarthy }
2306b6b8c4fSAdrian McCarthy 
2316b6b8c4fSAdrian McCarthy std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getAllSourceFiles() const {
2326b6b8c4fSAdrian McCarthy   return nullptr;
2336b6b8c4fSAdrian McCarthy }
2346b6b8c4fSAdrian McCarthy 
2356b6b8c4fSAdrian McCarthy std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getSourceFilesForCompiland(
2366b6b8c4fSAdrian McCarthy     const PDBSymbolCompiland &Compiland) const {
2376b6b8c4fSAdrian McCarthy   return nullptr;
2386b6b8c4fSAdrian McCarthy }
2396b6b8c4fSAdrian McCarthy 
2406b6b8c4fSAdrian McCarthy std::unique_ptr<IPDBSourceFile>
2416b6b8c4fSAdrian McCarthy NativeSession::getSourceFileById(uint32_t FileId) const {
2426b6b8c4fSAdrian McCarthy   return nullptr;
2436b6b8c4fSAdrian McCarthy }
2446b6b8c4fSAdrian McCarthy 
2456b6b8c4fSAdrian McCarthy std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const {
2466b6b8c4fSAdrian McCarthy   return nullptr;
2476b6b8c4fSAdrian McCarthy }
24889bca9e5SAaron Smith 
24989bca9e5SAaron Smith std::unique_ptr<IPDBEnumTables> NativeSession::getEnumTables() const {
25089bca9e5SAaron Smith   return nullptr;
25189bca9e5SAaron Smith }
252