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