1 //===- NativeSession.cpp - Native 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 
10 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
11 
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
14 #include "llvm/DebugInfo/PDB/GenericError.h"
15 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
16 #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
17 #include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h"
18 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
19 #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h"
20 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
21 #include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
22 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
23 #include "llvm/DebugInfo/PDB/Native/RawError.h"
24 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
25 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
26 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
27 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
28 #include "llvm/Support/Allocator.h"
29 #include "llvm/Support/BinaryByteStream.h"
30 #include "llvm/Support/Error.h"
31 #include "llvm/Support/ErrorOr.h"
32 #include "llvm/Support/MemoryBuffer.h"
33 
34 #include <algorithm>
35 #include <cassert>
36 #include <memory>
37 #include <utility>
38 
39 using namespace llvm;
40 using namespace llvm::msf;
41 using namespace llvm::pdb;
42 
43 namespace {
44 // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
45 // to instantiate a NativeBuiltinSymbol for that type.
46 static const struct BuiltinTypeEntry {
47   codeview::SimpleTypeKind Kind;
48   PDB_BuiltinType Type;
49   uint32_t Size;
50 } BuiltinTypes[] = {
51     {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
52     {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
53     {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
54     {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
55     {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
56     {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
57     {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
58     {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
59     {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}
60     // This table can be grown as necessary, but these are the only types we've
61     // needed so far.
62 };
63 } // namespace
64 
65 NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile,
66                              std::unique_ptr<BumpPtrAllocator> Allocator)
67     : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)) {}
68 
69 NativeSession::~NativeSession() = default;
70 
71 Error NativeSession::createFromPdb(StringRef Path,
72                                    std::unique_ptr<IPDBSession> &Session) {
73   ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
74       MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
75                                    /*RequiresNullTerminator=*/false);
76   if (!ErrorOrBuffer)
77     return make_error<GenericError>(generic_error_code::invalid_path);
78 
79   std::unique_ptr<MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
80   auto Stream = llvm::make_unique<MemoryBufferByteStream>(
81       std::move(Buffer), llvm::support::little);
82 
83   auto Allocator = llvm::make_unique<BumpPtrAllocator>();
84   auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), *Allocator);
85   if (auto EC = File->parseFileHeaders())
86     return EC;
87   if (auto EC = File->parseStreamData())
88     return EC;
89 
90   Session =
91       llvm::make_unique<NativeSession>(std::move(File), std::move(Allocator));
92 
93   return Error::success();
94 }
95 
96 Error NativeSession::createFromExe(StringRef Path,
97                                    std::unique_ptr<IPDBSession> &Session) {
98   return make_error<RawError>(raw_error_code::feature_unsupported);
99 }
100 
101 std::unique_ptr<PDBSymbolCompiland>
102 NativeSession::createCompilandSymbol(DbiModuleDescriptor MI) {
103   const auto Id = static_cast<SymIndexId>(SymbolCache.size());
104   SymbolCache.push_back(
105       llvm::make_unique<NativeCompilandSymbol>(*this, Id, MI));
106   return llvm::make_unique<PDBSymbolCompiland>(
107       *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone()));
108 }
109 
110 std::unique_ptr<PDBSymbolTypeEnum>
111 NativeSession::createEnumSymbol(codeview::TypeIndex Index) {
112   const auto Id = findSymbolByTypeIndex(Index);
113   return llvm::make_unique<PDBSymbolTypeEnum>(
114       *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone()));
115 }
116 
117 std::unique_ptr<IPDBEnumSymbols>
118 NativeSession::createTypeEnumerator(codeview::TypeLeafKind Kind) {
119   auto Tpi = Pdb->getPDBTpiStream();
120   if (!Tpi) {
121     consumeError(Tpi.takeError());
122     return nullptr;
123   }
124   auto &Types = Tpi->typeCollection();
125   return std::unique_ptr<IPDBEnumSymbols>(
126       new NativeEnumTypes(*this, Types, codeview::LF_ENUM));
127 }
128 
129 SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) {
130   // First see if it's already in our cache.
131   const auto Entry = TypeIndexToSymbolId.find(Index);
132   if (Entry != TypeIndexToSymbolId.end())
133     return Entry->second;
134 
135   // Symbols for built-in types are created on the fly.
136   if (Index.isSimple()) {
137     // FIXME:  We will eventually need to handle pointers to other simple types,
138     // which are still simple types in the world of CodeView TypeIndexes.
139     if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
140       return 0;
141     const auto Kind = Index.getSimpleKind();
142     const auto It =
143         std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes),
144                      [Kind](const BuiltinTypeEntry &Builtin) {
145                        return Builtin.Kind == Kind;
146                      });
147     if (It == std::end(BuiltinTypes))
148       return 0;
149     SymIndexId Id = SymbolCache.size();
150     SymbolCache.emplace_back(
151         llvm::make_unique<NativeBuiltinSymbol>(*this, Id, It->Type, It->Size));
152     TypeIndexToSymbolId[Index] = Id;
153     return Id;
154   }
155 
156   // We need to instantiate and cache the desired type symbol.
157   auto Tpi = Pdb->getPDBTpiStream();
158   if (!Tpi) {
159     consumeError(Tpi.takeError());
160     return 0;
161   }
162   auto &Types = Tpi->typeCollection();
163   const auto &I = Types.getType(Index);
164   const auto Id = static_cast<SymIndexId>(SymbolCache.size());
165   // TODO(amccarth):  Make this handle all types, not just LF_ENUMs.
166   assert(I.kind() == codeview::LF_ENUM);
167   SymbolCache.emplace_back(llvm::make_unique<NativeEnumSymbol>(*this, Id, I));
168   TypeIndexToSymbolId[Index] = Id;
169   return Id;
170 }
171 
172 uint64_t NativeSession::getLoadAddress() const { return 0; }
173 
174 void NativeSession::setLoadAddress(uint64_t Address) {}
175 
176 std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() {
177   const auto Id = static_cast<SymIndexId>(SymbolCache.size());
178   SymbolCache.push_back(llvm::make_unique<NativeExeSymbol>(*this, Id));
179   auto RawSymbol = SymbolCache[Id]->clone();
180   auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
181   std::unique_ptr<PDBSymbolExe> ExeSymbol(
182       static_cast<PDBSymbolExe *>(PdbSymbol.release()));
183   return ExeSymbol;
184 }
185 
186 std::unique_ptr<PDBSymbol>
187 NativeSession::getSymbolById(uint32_t SymbolId) const {
188   // If the caller has a SymbolId, it'd better be in our SymbolCache.
189   return SymbolId < SymbolCache.size()
190              ? PDBSymbol::create(*this, SymbolCache[SymbolId]->clone())
191              : nullptr;
192 }
193 
194 std::unique_ptr<PDBSymbol>
195 NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
196   return nullptr;
197 }
198 
199 std::unique_ptr<IPDBEnumLineNumbers>
200 NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland,
201                                const IPDBSourceFile &File) const {
202   return nullptr;
203 }
204 
205 std::unique_ptr<IPDBEnumLineNumbers>
206 NativeSession::findLineNumbersByAddress(uint64_t Address,
207                                         uint32_t Length) const {
208   return nullptr;
209 }
210 
211 std::unique_ptr<IPDBEnumSourceFiles>
212 NativeSession::findSourceFiles(const PDBSymbolCompiland *Compiland,
213                                StringRef Pattern,
214                                PDB_NameSearchFlags Flags) const {
215   return nullptr;
216 }
217 
218 std::unique_ptr<IPDBSourceFile>
219 NativeSession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
220                                  StringRef Pattern,
221                                  PDB_NameSearchFlags Flags) const {
222   return nullptr;
223 }
224 
225 std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
226 NativeSession::findCompilandsForSourceFile(StringRef Pattern,
227                                            PDB_NameSearchFlags Flags) const {
228   return nullptr;
229 }
230 
231 std::unique_ptr<PDBSymbolCompiland>
232 NativeSession::findOneCompilandForSourceFile(StringRef Pattern,
233                                              PDB_NameSearchFlags Flags) const {
234   return nullptr;
235 }
236 
237 std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getAllSourceFiles() const {
238   return nullptr;
239 }
240 
241 std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getSourceFilesForCompiland(
242     const PDBSymbolCompiland &Compiland) const {
243   return nullptr;
244 }
245 
246 std::unique_ptr<IPDBSourceFile>
247 NativeSession::getSourceFileById(uint32_t FileId) const {
248   return nullptr;
249 }
250 
251 std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const {
252   return nullptr;
253 }
254