1 //===- NativeSession.cpp - Native implementation of IPDBSession -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
10 
11 #include "llvm/BinaryFormat/Magic.h"
12 #include "llvm/DebugInfo/MSF/MSFCommon.h"
13 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
14 #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
15 #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
16 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
17 #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
18 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
19 #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
20 #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
21 #include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h"
22 #include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"
23 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
24 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
25 #include "llvm/DebugInfo/PDB/Native/RawError.h"
26 #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
27 #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
28 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
29 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
30 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
31 #include "llvm/Object/Binary.h"
32 #include "llvm/Object/COFF.h"
33 #include "llvm/Support/Allocator.h"
34 #include "llvm/Support/BinaryByteStream.h"
35 #include "llvm/Support/BinaryStreamArray.h"
36 #include "llvm/Support/Error.h"
37 #include "llvm/Support/ErrorOr.h"
38 #include "llvm/Support/MemoryBuffer.h"
39 #include "llvm/Support/Path.h"
40 
41 #include <algorithm>
42 #include <cassert>
43 #include <memory>
44 #include <utility>
45 
46 using namespace llvm;
47 using namespace llvm::msf;
48 using namespace llvm::pdb;
49 
50 namespace llvm {
51 namespace codeview {
52 union DebugInfo;
53 }
54 } // namespace llvm
55 
56 static DbiStream *getDbiStreamPtr(PDBFile &File) {
57   Expected<DbiStream &> DbiS = File.getPDBDbiStream();
58   if (DbiS)
59     return &DbiS.get();
60 
61   consumeError(DbiS.takeError());
62   return nullptr;
63 }
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       Cache(*this, getDbiStreamPtr(*Pdb)), AddrToModuleIndex(IMapAllocator) {}
69 
70 NativeSession::~NativeSession() = default;
71 
72 Error NativeSession::createFromPdb(std::unique_ptr<MemoryBuffer> Buffer,
73                                    std::unique_ptr<IPDBSession> &Session) {
74   StringRef Path = Buffer->getBufferIdentifier();
75   auto Stream = std::make_unique<MemoryBufferByteStream>(
76       std::move(Buffer), llvm::support::little);
77 
78   auto Allocator = std::make_unique<BumpPtrAllocator>();
79   auto File = std::make_unique<PDBFile>(Path, std::move(Stream), *Allocator);
80   if (auto EC = File->parseFileHeaders())
81     return EC;
82   if (auto EC = File->parseStreamData())
83     return EC;
84 
85   Session =
86       std::make_unique<NativeSession>(std::move(File), std::move(Allocator));
87 
88   return Error::success();
89 }
90 
91 static Expected<std::unique_ptr<PDBFile>>
92 loadPdbFile(StringRef PdbPath, std::unique_ptr<BumpPtrAllocator> &Allocator) {
93   ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
94       MemoryBuffer::getFile(PdbPath, /*IsText=*/false,
95                             /*RequiresNullTerminator=*/false);
96   if (!ErrorOrBuffer)
97     return make_error<RawError>(ErrorOrBuffer.getError());
98   std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
99 
100   PdbPath = Buffer->getBufferIdentifier();
101   file_magic Magic;
102   auto EC = identify_magic(PdbPath, Magic);
103   if (EC || Magic != file_magic::pdb)
104     return make_error<RawError>(EC);
105 
106   auto Stream = std::make_unique<MemoryBufferByteStream>(std::move(Buffer),
107                                                          llvm::support::little);
108 
109   auto File = std::make_unique<PDBFile>(PdbPath, std::move(Stream), *Allocator);
110   if (auto EC = File->parseFileHeaders())
111     return std::move(EC);
112 
113   if (auto EC = File->parseStreamData())
114     return std::move(EC);
115 
116   return std::move(File);
117 }
118 
119 Error NativeSession::createFromPdbPath(StringRef PdbPath,
120                                        std::unique_ptr<IPDBSession> &Session) {
121   auto Allocator = std::make_unique<BumpPtrAllocator>();
122   auto PdbFile = loadPdbFile(PdbPath, Allocator);
123   if (!PdbFile)
124     return PdbFile.takeError();
125 
126   Session = std::make_unique<NativeSession>(std::move(PdbFile.get()),
127                                             std::move(Allocator));
128   return Error::success();
129 }
130 
131 static Expected<std::string> getPdbPathFromExe(StringRef ExePath) {
132   Expected<object::OwningBinary<object::Binary>> BinaryFile =
133       object::createBinary(ExePath);
134   if (!BinaryFile)
135     return BinaryFile.takeError();
136 
137   const object::COFFObjectFile *ObjFile =
138       dyn_cast<object::COFFObjectFile>(BinaryFile->getBinary());
139   if (!ObjFile)
140     return make_error<RawError>(raw_error_code::invalid_format);
141 
142   StringRef PdbPath;
143   const llvm::codeview::DebugInfo *PdbInfo = nullptr;
144   if (Error E = ObjFile->getDebugPDBInfo(PdbInfo, PdbPath))
145     return std::move(E);
146 
147   return std::string(PdbPath);
148 }
149 
150 Error NativeSession::createFromExe(StringRef ExePath,
151                                    std::unique_ptr<IPDBSession> &Session) {
152   Expected<std::string> PdbPath = getPdbPathFromExe(ExePath);
153   if (!PdbPath)
154     return PdbPath.takeError();
155 
156   file_magic Magic;
157   auto EC = identify_magic(PdbPath.get(), Magic);
158   if (EC || Magic != file_magic::pdb)
159     return make_error<RawError>(EC);
160 
161   auto Allocator = std::make_unique<BumpPtrAllocator>();
162   auto File = loadPdbFile(PdbPath.get(), Allocator);
163   if (!File)
164     return File.takeError();
165 
166   Session = std::make_unique<NativeSession>(std::move(File.get()),
167                                             std::move(Allocator));
168 
169   return Error::success();
170 }
171 
172 Expected<std::string>
173 NativeSession::searchForPdb(const PdbSearchOptions &Opts) {
174   Expected<std::string> PathOrErr = getPdbPathFromExe(Opts.ExePath);
175   if (!PathOrErr)
176     return PathOrErr.takeError();
177   StringRef PathFromExe = PathOrErr.get();
178   sys::path::Style Style = PathFromExe.startswith("/")
179                                ? sys::path::Style::posix
180                                : sys::path::Style::windows;
181   StringRef PdbName = sys::path::filename(PathFromExe, Style);
182 
183   // Check if pdb exists in the executable directory.
184   SmallString<128> PdbPath = StringRef(Opts.ExePath);
185   sys::path::remove_filename(PdbPath);
186   sys::path::append(PdbPath, PdbName);
187 
188   auto Allocator = std::make_unique<BumpPtrAllocator>();
189 
190   if (auto File = loadPdbFile(PdbPath, Allocator))
191     return std::string(PdbPath);
192   else
193     consumeError(File.takeError());
194 
195   // Check path that was in the executable.
196   if (auto File = loadPdbFile(PathFromExe, Allocator))
197     return std::string(PathFromExe);
198   else
199     return File.takeError();
200 
201   return make_error<RawError>("PDB not found");
202 }
203 
204 uint64_t NativeSession::getLoadAddress() const { return LoadAddress; }
205 
206 bool NativeSession::setLoadAddress(uint64_t Address) {
207   LoadAddress = Address;
208   return true;
209 }
210 
211 std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() {
212   return PDBSymbol::createAs<PDBSymbolExe>(*this, getNativeGlobalScope());
213 }
214 
215 std::unique_ptr<PDBSymbol>
216 NativeSession::getSymbolById(SymIndexId SymbolId) const {
217   return Cache.getSymbolById(SymbolId);
218 }
219 
220 bool NativeSession::addressForVA(uint64_t VA, uint32_t &Section,
221                                  uint32_t &Offset) const {
222   uint32_t RVA = VA - getLoadAddress();
223   return addressForRVA(RVA, Section, Offset);
224 }
225 
226 bool NativeSession::addressForRVA(uint32_t RVA, uint32_t &Section,
227                                   uint32_t &Offset) const {
228   Section = 0;
229   Offset = 0;
230 
231   auto Dbi = Pdb->getPDBDbiStream();
232   if (!Dbi)
233     return false;
234 
235   if ((int32_t)RVA < 0)
236     return true;
237 
238   Offset = RVA;
239   for (; Section < Dbi->getSectionHeaders().size(); ++Section) {
240     auto &Sec = Dbi->getSectionHeaders()[Section];
241     if (RVA < Sec.VirtualAddress)
242       return true;
243     Offset = RVA - Sec.VirtualAddress;
244   }
245   return true;
246 }
247 
248 std::unique_ptr<PDBSymbol>
249 NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) {
250   uint32_t Section;
251   uint32_t Offset;
252   addressForVA(Address, Section, Offset);
253   return findSymbolBySectOffset(Section, Offset, Type);
254 }
255 
256 std::unique_ptr<PDBSymbol> NativeSession::findSymbolByRVA(uint32_t RVA,
257                                                           PDB_SymType Type) {
258   uint32_t Section;
259   uint32_t Offset;
260   addressForRVA(RVA, Section, Offset);
261   return findSymbolBySectOffset(Section, Offset, Type);
262 }
263 
264 std::unique_ptr<PDBSymbol>
265 NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
266                                       PDB_SymType Type) {
267   if (AddrToModuleIndex.empty())
268     parseSectionContribs();
269 
270   return Cache.findSymbolBySectOffset(Sect, Offset, Type);
271 }
272 
273 std::unique_ptr<IPDBEnumLineNumbers>
274 NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland,
275                                const IPDBSourceFile &File) const {
276   return nullptr;
277 }
278 
279 std::unique_ptr<IPDBEnumLineNumbers>
280 NativeSession::findLineNumbersByAddress(uint64_t Address,
281                                         uint32_t Length) const {
282   return Cache.findLineNumbersByVA(Address, Length);
283 }
284 
285 std::unique_ptr<IPDBEnumLineNumbers>
286 NativeSession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const {
287   return Cache.findLineNumbersByVA(getLoadAddress() + RVA, Length);
288 }
289 
290 std::unique_ptr<IPDBEnumLineNumbers>
291 NativeSession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
292                                            uint32_t Length) const {
293   uint64_t VA = getVAFromSectOffset(Section, Offset);
294   return Cache.findLineNumbersByVA(VA, Length);
295 }
296 
297 std::unique_ptr<IPDBEnumSourceFiles>
298 NativeSession::findSourceFiles(const PDBSymbolCompiland *Compiland,
299                                StringRef Pattern,
300                                PDB_NameSearchFlags Flags) const {
301   return nullptr;
302 }
303 
304 std::unique_ptr<IPDBSourceFile>
305 NativeSession::findOneSourceFile(const PDBSymbolCompiland *Compiland,
306                                  StringRef Pattern,
307                                  PDB_NameSearchFlags Flags) const {
308   return nullptr;
309 }
310 
311 std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
312 NativeSession::findCompilandsForSourceFile(StringRef Pattern,
313                                            PDB_NameSearchFlags Flags) const {
314   return nullptr;
315 }
316 
317 std::unique_ptr<PDBSymbolCompiland>
318 NativeSession::findOneCompilandForSourceFile(StringRef Pattern,
319                                              PDB_NameSearchFlags Flags) const {
320   return nullptr;
321 }
322 
323 std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getAllSourceFiles() const {
324   return nullptr;
325 }
326 
327 std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getSourceFilesForCompiland(
328     const PDBSymbolCompiland &Compiland) const {
329   return nullptr;
330 }
331 
332 std::unique_ptr<IPDBSourceFile>
333 NativeSession::getSourceFileById(uint32_t FileId) const {
334   return Cache.getSourceFileById(FileId);
335 }
336 
337 std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const {
338   return nullptr;
339 }
340 
341 std::unique_ptr<IPDBEnumTables> NativeSession::getEnumTables() const {
342   return nullptr;
343 }
344 
345 std::unique_ptr<IPDBEnumInjectedSources>
346 NativeSession::getInjectedSources() const {
347   auto ISS = Pdb->getInjectedSourceStream();
348   if (!ISS) {
349     consumeError(ISS.takeError());
350     return nullptr;
351   }
352   auto Strings = Pdb->getStringTable();
353   if (!Strings) {
354     consumeError(Strings.takeError());
355     return nullptr;
356   }
357   return std::make_unique<NativeEnumInjectedSources>(*Pdb, *ISS, *Strings);
358 }
359 
360 std::unique_ptr<IPDBEnumSectionContribs>
361 NativeSession::getSectionContribs() const {
362   return nullptr;
363 }
364 
365 std::unique_ptr<IPDBEnumFrameData>
366 NativeSession::getFrameData() const {
367   return nullptr;
368 }
369 
370 void NativeSession::initializeExeSymbol() {
371   if (ExeSymbol == 0)
372     ExeSymbol = Cache.createSymbol<NativeExeSymbol>();
373 }
374 
375 NativeExeSymbol &NativeSession::getNativeGlobalScope() const {
376   const_cast<NativeSession &>(*this).initializeExeSymbol();
377 
378   return Cache.getNativeSymbolById<NativeExeSymbol>(ExeSymbol);
379 }
380 
381 uint32_t NativeSession::getRVAFromSectOffset(uint32_t Section,
382                                              uint32_t Offset) const {
383   if (Section <= 0)
384     return 0;
385 
386   auto Dbi = getDbiStreamPtr(*Pdb);
387   if (!Dbi)
388     return 0;
389 
390   uint32_t MaxSection = Dbi->getSectionHeaders().size();
391   if (Section > MaxSection + 1)
392     Section = MaxSection + 1;
393   auto &Sec = Dbi->getSectionHeaders()[Section - 1];
394   return Sec.VirtualAddress + Offset;
395 }
396 
397 uint64_t NativeSession::getVAFromSectOffset(uint32_t Section,
398                                             uint32_t Offset) const {
399   return LoadAddress + getRVAFromSectOffset(Section, Offset);
400 }
401 
402 bool NativeSession::moduleIndexForVA(uint64_t VA, uint16_t &ModuleIndex) const {
403   ModuleIndex = 0;
404   auto Iter = AddrToModuleIndex.find(VA);
405   if (Iter == AddrToModuleIndex.end())
406     return false;
407   ModuleIndex = Iter.value();
408   return true;
409 }
410 
411 bool NativeSession::moduleIndexForSectOffset(uint32_t Sect, uint32_t Offset,
412                                              uint16_t &ModuleIndex) const {
413   ModuleIndex = 0;
414   auto Iter = AddrToModuleIndex.find(getVAFromSectOffset(Sect, Offset));
415   if (Iter == AddrToModuleIndex.end())
416     return false;
417   ModuleIndex = Iter.value();
418   return true;
419 }
420 
421 void NativeSession::parseSectionContribs() {
422   auto Dbi = Pdb->getPDBDbiStream();
423   if (!Dbi)
424     return;
425 
426   class Visitor : public ISectionContribVisitor {
427     NativeSession &Session;
428     IMap &AddrMap;
429 
430   public:
431     Visitor(NativeSession &Session, IMap &AddrMap)
432         : Session(Session), AddrMap(AddrMap) {}
433     void visit(const SectionContrib &C) override {
434       if (C.Size == 0)
435         return;
436 
437       uint64_t VA = Session.getVAFromSectOffset(C.ISect, C.Off);
438       uint64_t End = VA + C.Size;
439 
440       // Ignore overlapping sections based on the assumption that a valid
441       // PDB file should not have overlaps.
442       if (!AddrMap.overlaps(VA, End))
443         AddrMap.insert(VA, End, C.Imod);
444     }
445     void visit(const SectionContrib2 &C) override { visit(C.Base); }
446   };
447 
448   Visitor V(*this, AddrToModuleIndex);
449   Dbi->visitSectionContributions(V);
450 }
451 
452 Expected<ModuleDebugStreamRef>
453 NativeSession::getModuleDebugStream(uint32_t Index) const {
454   auto *Dbi = getDbiStreamPtr(*Pdb);
455   assert(Dbi && "Dbi stream not present");
456 
457   DbiModuleDescriptor Modi = Dbi->modules().getModuleDescriptor(Index);
458 
459   uint16_t ModiStream = Modi.getModuleStreamIndex();
460   if (ModiStream == kInvalidStreamIndex)
461     return make_error<RawError>("Module stream not present");
462 
463   std::unique_ptr<msf::MappedBlockStream> ModStreamData =
464       Pdb->createIndexedStream(ModiStream);
465 
466   ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
467   if (auto EC = ModS.reload())
468     return std::move(EC);
469 
470   return std::move(ModS);
471 }
472