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 
68 NativeSession::~NativeSession() = default;
69 
70 Error NativeSession::createFromPdb(std::unique_ptr<MemoryBuffer> Buffer,
71                                    std::unique_ptr<IPDBSession> &Session) {
72   StringRef Path = Buffer->getBufferIdentifier();
73   auto Stream = llvm::make_unique<MemoryBufferByteStream>(
74       std::move(Buffer), llvm::support::little);
75 
76   auto Allocator = llvm::make_unique<BumpPtrAllocator>();
77   auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), *Allocator);
78   if (auto EC = File->parseFileHeaders())
79     return EC;
80   if (auto EC = File->parseStreamData())
81     return EC;
82 
83   Session =
84       llvm::make_unique<NativeSession>(std::move(File), std::move(Allocator));
85 
86   return Error::success();
87 }
88 
89 Error NativeSession::createFromExe(StringRef Path,
90                                    std::unique_ptr<IPDBSession> &Session) {
91   return make_error<RawError>(raw_error_code::feature_unsupported);
92 }
93 
94 std::unique_ptr<PDBSymbolCompiland>
95 NativeSession::createCompilandSymbol(DbiModuleDescriptor MI) {
96   const auto Id = static_cast<SymIndexId>(SymbolCache.size());
97   SymbolCache.push_back(
98       llvm::make_unique<NativeCompilandSymbol>(*this, Id, MI));
99   return llvm::make_unique<PDBSymbolCompiland>(
100       *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone()));
101 }
102 
103 std::unique_ptr<PDBSymbolTypeEnum>
104 NativeSession::createEnumSymbol(codeview::TypeIndex Index) {
105   const auto Id = findSymbolByTypeIndex(Index);
106   return llvm::make_unique<PDBSymbolTypeEnum>(
107       *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone()));
108 }
109 
110 std::unique_ptr<IPDBEnumSymbols>
111 NativeSession::createTypeEnumerator(codeview::TypeLeafKind Kind) {
112   auto Tpi = Pdb->getPDBTpiStream();
113   if (!Tpi) {
114     consumeError(Tpi.takeError());
115     return nullptr;
116   }
117   auto &Types = Tpi->typeCollection();
118   return std::unique_ptr<IPDBEnumSymbols>(
119       new NativeEnumTypes(*this, Types, codeview::LF_ENUM));
120 }
121 
122 SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) {
123   // First see if it's already in our cache.
124   const auto Entry = TypeIndexToSymbolId.find(Index);
125   if (Entry != TypeIndexToSymbolId.end())
126     return Entry->second;
127 
128   // Symbols for built-in types are created on the fly.
129   if (Index.isSimple()) {
130     // FIXME:  We will eventually need to handle pointers to other simple types,
131     // which are still simple types in the world of CodeView TypeIndexes.
132     if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
133       return 0;
134     const auto Kind = Index.getSimpleKind();
135     const auto It =
136         std::find_if(std::begin(BuiltinTypes), std::end(BuiltinTypes),
137                      [Kind](const BuiltinTypeEntry &Builtin) {
138                        return Builtin.Kind == Kind;
139                      });
140     if (It == std::end(BuiltinTypes))
141       return 0;
142     SymIndexId Id = SymbolCache.size();
143     SymbolCache.emplace_back(
144         llvm::make_unique<NativeBuiltinSymbol>(*this, Id, It->Type, It->Size));
145     TypeIndexToSymbolId[Index] = Id;
146     return Id;
147   }
148 
149   // We need to instantiate and cache the desired type symbol.
150   auto Tpi = Pdb->getPDBTpiStream();
151   if (!Tpi) {
152     consumeError(Tpi.takeError());
153     return 0;
154   }
155   auto &Types = Tpi->typeCollection();
156   const auto &I = Types.getType(Index);
157   const auto Id = static_cast<SymIndexId>(SymbolCache.size());
158   // TODO(amccarth):  Make this handle all types, not just LF_ENUMs.
159   assert(I.kind() == codeview::LF_ENUM);
160   SymbolCache.emplace_back(llvm::make_unique<NativeEnumSymbol>(*this, Id, I));
161   TypeIndexToSymbolId[Index] = Id;
162   return Id;
163 }
164 
165 uint64_t NativeSession::getLoadAddress() const { return 0; }
166 
167 bool NativeSession::setLoadAddress(uint64_t Address) { return false; }
168 
169 std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() {
170   const auto Id = static_cast<SymIndexId>(SymbolCache.size());
171   SymbolCache.push_back(llvm::make_unique<NativeExeSymbol>(*this, Id));
172   auto RawSymbol = SymbolCache[Id]->clone();
173   auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
174   std::unique_ptr<PDBSymbolExe> ExeSymbol(
175       static_cast<PDBSymbolExe *>(PdbSymbol.release()));
176   return ExeSymbol;
177 }
178 
179 std::unique_ptr<PDBSymbol>
180 NativeSession::getSymbolById(uint32_t SymbolId) const {
181   // If the caller has a SymbolId, it'd better be in our SymbolCache.
182   return SymbolId < SymbolCache.size()
183              ? PDBSymbol::create(*this, SymbolCache[SymbolId]->clone())
184              : nullptr;
185 }
186 
187 bool NativeSession::addressForVA(uint64_t VA, uint32_t &Section,
188                                  uint32_t &Offset) const {
189   return false;
190 }
191 
192 bool NativeSession::addressForRVA(uint32_t VA, uint32_t &Section,
193                                   uint32_t &Offset) const {
194   return false;
195 }
196 
197 std::unique_ptr<PDBSymbol>
198 NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
199   return nullptr;
200 }
201 
202 std::unique_ptr<PDBSymbol>
203 NativeSession::findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const {
204   return nullptr;
205 }
206 
207 std::unique_ptr<PDBSymbol>
208 NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
209                                       PDB_SymType Type) const {
210   return nullptr;
211 }
212 
213 std::unique_ptr<IPDBEnumLineNumbers>
214 NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland,
215                                const IPDBSourceFile &File) const {
216   return nullptr;
217 }
218 
219 std::unique_ptr<IPDBEnumLineNumbers>
220 NativeSession::findLineNumbersByAddress(uint64_t Address,
221                                         uint32_t Length) const {
222   return nullptr;
223 }
224 
225 std::unique_ptr<IPDBEnumLineNumbers>
226 NativeSession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const {
227   return nullptr;
228 }
229 
230 std::unique_ptr<IPDBEnumLineNumbers>
231 NativeSession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
232                                            uint32_t Length) const {
233   return nullptr;
234 }
235 
236 std::unique_ptr<IPDBEnumSourceFiles>
237 NativeSession::findSourceFiles(const PDBSymbolCompiland *Compiland,
238                                StringRef Pattern,
239                                PDB_NameSearchFlags Flags) const {
240   return nullptr;
241 }
242 
243 std::unique_ptr<IPDBSourceFile>
244 NativeSession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
245                                  StringRef Pattern,
246                                  PDB_NameSearchFlags Flags) const {
247   return nullptr;
248 }
249 
250 std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
251 NativeSession::findCompilandsForSourceFile(StringRef Pattern,
252                                            PDB_NameSearchFlags Flags) const {
253   return nullptr;
254 }
255 
256 std::unique_ptr<PDBSymbolCompiland>
257 NativeSession::findOneCompilandForSourceFile(StringRef Pattern,
258                                              PDB_NameSearchFlags Flags) const {
259   return nullptr;
260 }
261 
262 std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getAllSourceFiles() const {
263   return nullptr;
264 }
265 
266 std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getSourceFilesForCompiland(
267     const PDBSymbolCompiland &Compiland) const {
268   return nullptr;
269 }
270 
271 std::unique_ptr<IPDBSourceFile>
272 NativeSession::getSourceFileById(uint32_t FileId) const {
273   return nullptr;
274 }
275 
276 std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const {
277   return nullptr;
278 }
279 
280 std::unique_ptr<IPDBEnumTables> NativeSession::getEnumTables() const {
281   return nullptr;
282 }
283 
284 std::unique_ptr<IPDBEnumInjectedSources>
285 NativeSession::getInjectedSources() const {
286   return nullptr;
287 }
288 
289 std::unique_ptr<IPDBEnumSectionContribs>
290 NativeSession::getSectionContribs() const {
291   return nullptr;
292 }
293