LLVM  11.0.0git
NativeSession.cpp
Go to the documentation of this file.
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 
10 
11 #include "llvm/ADT/STLExtras.h"
29 #include "llvm/Object/COFF.h"
30 #include "llvm/Support/Allocator.h"
32 #include "llvm/Support/Error.h"
33 #include "llvm/Support/ErrorOr.h"
36 #include "llvm/Support/Path.h"
37 
38 #include <algorithm>
39 #include <cassert>
40 #include <memory>
41 #include <utility>
42 
43 using namespace llvm;
44 using namespace llvm::msf;
45 using namespace llvm::pdb;
46 using namespace llvm::codeview;
47 
50  if (DbiS)
51  return &DbiS.get();
52 
53  consumeError(DbiS.takeError());
54  return nullptr;
55 }
56 
57 NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile,
58  std::unique_ptr<BumpPtrAllocator> Allocator)
59  : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)),
60  Cache(*this, getDbiStreamPtr(*Pdb)) {}
61 
63 
64 Error NativeSession::createFromPdb(std::unique_ptr<MemoryBuffer> Buffer,
65  std::unique_ptr<IPDBSession> &Session) {
66  StringRef Path = Buffer->getBufferIdentifier();
67  auto Stream = std::make_unique<MemoryBufferByteStream>(
68  std::move(Buffer), llvm::support::little);
69 
70  auto Allocator = std::make_unique<BumpPtrAllocator>();
71  auto File = std::make_unique<PDBFile>(Path, std::move(Stream), *Allocator);
72  if (auto EC = File->parseFileHeaders())
73  return EC;
74  if (auto EC = File->parseStreamData())
75  return EC;
76 
77  Session =
78  std::make_unique<NativeSession>(std::move(File), std::move(Allocator));
79 
80  return Error::success();
81 }
82 
84 loadPdbFile(StringRef PdbPath, std::unique_ptr<BumpPtrAllocator> &Allocator) {
86  MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1,
87  /*RequiresNullTerminator=*/false);
88  if (!ErrorOrBuffer)
89  return make_error<RawError>(ErrorOrBuffer.getError());
90  std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
91 
92  PdbPath = Buffer->getBufferIdentifier();
94  auto EC = identify_magic(PdbPath, Magic);
95  if (EC || Magic != file_magic::pdb)
96  return make_error<RawError>(EC);
97 
98  auto Stream = std::make_unique<MemoryBufferByteStream>(std::move(Buffer),
100 
101  auto File = std::make_unique<PDBFile>(PdbPath, std::move(Stream), *Allocator);
102  if (auto EC = File->parseFileHeaders())
103  return std::move(EC);
104 
105  if (auto EC = File->parseStreamData())
106  return std::move(EC);
107 
108  return std::move(File);
109 }
110 
112  std::unique_ptr<IPDBSession> &Session) {
113  auto Allocator = std::make_unique<BumpPtrAllocator>();
114  auto PdbFile = loadPdbFile(PdbPath, Allocator);
115  if (!PdbFile)
116  return PdbFile.takeError();
117 
118  Session = std::make_unique<NativeSession>(std::move(PdbFile.get()),
119  std::move(Allocator));
120  return Error::success();
121 }
122 
125  object::createBinary(ExePath);
126  if (!BinaryFile)
127  return BinaryFile.takeError();
128 
129  const object::COFFObjectFile *ObjFile =
130  dyn_cast<object::COFFObjectFile>(BinaryFile->getBinary());
131  if (!ObjFile)
132  return make_error<RawError>(raw_error_code::invalid_format);
133 
134  StringRef PdbPath;
135  const llvm::codeview::DebugInfo *PdbInfo = nullptr;
136  if (auto EC = ObjFile->getDebugPDBInfo(PdbInfo, PdbPath))
137  return make_error<RawError>(EC);
138 
139  return std::string(PdbPath);
140 }
141 
143  std::unique_ptr<IPDBSession> &Session) {
144  Expected<std::string> PdbPath = getPdbPathFromExe(ExePath);
145  if (!PdbPath)
146  return PdbPath.takeError();
147 
149  auto EC = identify_magic(PdbPath.get(), Magic);
150  if (EC || Magic != file_magic::pdb)
151  return make_error<RawError>(EC);
152 
153  auto Allocator = std::make_unique<BumpPtrAllocator>();
154  auto File = loadPdbFile(PdbPath.get(), Allocator);
155  if (!File)
156  return File.takeError();
157 
158  Session = std::make_unique<NativeSession>(std::move(File.get()),
159  std::move(Allocator));
160 
161  return Error::success();
162 }
163 
165 NativeSession::searchForPdb(const PdbSearchOptions &Opts) {
166  Expected<std::string> PathOrErr = getPdbPathFromExe(Opts.ExePath);
167  if (!PathOrErr)
168  return PathOrErr.takeError();
169  StringRef PathFromExe = PathOrErr.get();
170  sys::path::Style Style = PathFromExe.startswith("/")
173  StringRef PdbName = sys::path::filename(PathFromExe, Style);
174 
175  // Check if pdb exists in the executable directory.
176  SmallString<128> PdbPath = StringRef(Opts.ExePath);
178  sys::path::append(PdbPath, PdbName);
179 
180  auto Allocator = std::make_unique<BumpPtrAllocator>();
181 
182  if (auto File = loadPdbFile(PdbPath, Allocator))
183  return std::string(PdbPath);
184  else
185  return File.takeError();
186 
187  return make_error<RawError>("PDB not found");
188 }
189 
190 uint64_t NativeSession::getLoadAddress() const { return LoadAddress; }
191 
192 bool NativeSession::setLoadAddress(uint64_t Address) {
193  LoadAddress = Address;
194  return true;
195 }
196 
197 std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() {
198  return PDBSymbol::createAs<PDBSymbolExe>(*this, getNativeGlobalScope());
199 }
200 
201 std::unique_ptr<PDBSymbol>
203  return Cache.getSymbolById(SymbolId);
204 }
205 
207  uint32_t &Offset) const {
208  uint32_t RVA = VA - getLoadAddress();
209  return addressForRVA(RVA, Section, Offset);
210 }
211 
213  uint32_t &Offset) const {
214  Section = 0;
215  Offset = 0;
216 
217  auto Dbi = Pdb->getPDBDbiStream();
218  if (!Dbi)
219  return false;
220 
221  if ((int32_t)RVA < 0)
222  return true;
223 
224  Offset = RVA;
225  for (; Section < Dbi->getSectionHeaders().size(); ++Section) {
226  auto &Sec = Dbi->getSectionHeaders()[Section];
227  if (RVA < Sec.VirtualAddress)
228  return true;
229  Offset = RVA - Sec.VirtualAddress;
230  }
231  return true;
232 }
233 
234 std::unique_ptr<PDBSymbol>
238  addressForVA(Address, Section, Offset);
239  return findSymbolBySectOffset(Section, Offset, Type);
240 }
241 
242 std::unique_ptr<PDBSymbol> NativeSession::findSymbolByRVA(uint32_t RVA,
243  PDB_SymType Type) {
246  addressForRVA(RVA, Section, Offset);
247  return findSymbolBySectOffset(Section, Offset, Type);
248 }
249 
250 std::unique_ptr<PDBSymbol>
252  PDB_SymType Type) {
253  return Cache.findSymbolBySectOffset(Sect, Offset, Type);
254 }
255 
256 std::unique_ptr<IPDBEnumLineNumbers>
258  const IPDBSourceFile &File) const {
259  return nullptr;
260 }
261 
262 std::unique_ptr<IPDBEnumLineNumbers>
264  uint32_t Length) const {
265  return nullptr;
266 }
267 
268 std::unique_ptr<IPDBEnumLineNumbers>
270  return nullptr;
271 }
272 
273 std::unique_ptr<IPDBEnumLineNumbers>
275  uint32_t Length) const {
276  return nullptr;
277 }
278 
279 std::unique_ptr<IPDBEnumSourceFiles>
282  PDB_NameSearchFlags Flags) const {
283  return nullptr;
284 }
285 
286 std::unique_ptr<IPDBSourceFile>
289  PDB_NameSearchFlags Flags) const {
290  return nullptr;
291 }
292 
293 std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
295  PDB_NameSearchFlags Flags) const {
296  return nullptr;
297 }
298 
299 std::unique_ptr<PDBSymbolCompiland>
301  PDB_NameSearchFlags Flags) const {
302  return nullptr;
303 }
304 
305 std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getAllSourceFiles() const {
306  return nullptr;
307 }
308 
309 std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getSourceFilesForCompiland(
310  const PDBSymbolCompiland &Compiland) const {
311  return nullptr;
312 }
313 
314 std::unique_ptr<IPDBSourceFile>
316  return nullptr;
317 }
318 
319 std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const {
320  return nullptr;
321 }
322 
323 std::unique_ptr<IPDBEnumTables> NativeSession::getEnumTables() const {
324  return nullptr;
325 }
326 
327 std::unique_ptr<IPDBEnumInjectedSources>
329  auto ISS = Pdb->getInjectedSourceStream();
330  if (!ISS) {
331  consumeError(ISS.takeError());
332  return nullptr;
333  }
334  auto Strings = Pdb->getStringTable();
335  if (!Strings) {
336  consumeError(Strings.takeError());
337  return nullptr;
338  }
339  return std::make_unique<NativeEnumInjectedSources>(*Pdb, *ISS, *Strings);
340 }
341 
342 std::unique_ptr<IPDBEnumSectionContribs>
344  return nullptr;
345 }
346 
347 std::unique_ptr<IPDBEnumFrameData>
349  return nullptr;
350 }
351 
352 void NativeSession::initializeExeSymbol() {
353  if (ExeSymbol == 0)
354  ExeSymbol = Cache.createSymbol<NativeExeSymbol>();
355 }
356 
358  const_cast<NativeSession &>(*this).initializeExeSymbol();
359 
360  return Cache.getNativeSymbolById<NativeExeSymbol>(ExeSymbol);
361 }
362 
364  uint32_t Offset) const {
365  if (Section <= 0)
366  return 0;
367 
368  auto Dbi = getDbiStreamPtr(*Pdb);
369  if (!Dbi)
370  return 0;
371 
372  uint32_t MaxSection = Dbi->getSectionHeaders().size();
373  if (Section > MaxSection + 1)
374  Section = MaxSection + 1;
375  auto &Sec = Dbi->getSectionHeaders()[Section - 1];
376  return Sec.VirtualAddress + Offset;
377 }
378 
380  uint32_t Offset) const {
381  return LoadAddress + getRVAFromSectOffset(Section, Offset);
382 }
std::unique_ptr< IPDBEnumSourceFiles > getAllSourceFiles() const override
static Error createFromExe(StringRef Path, std::unique_ptr< IPDBSession > &Session)
Represents either an error or a value T.
Definition: ErrorOr.h:56
std::unique_ptr< IPDBEnumLineNumbers > findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset, uint32_t Length) const override
void remove_filename(SmallVectorImpl< char > &path, Style style=Style::native)
Remove the last component from path unless it is the root dir.
Definition: Path.cpp:474
LLVM_NODISCARD std::enable_if_t< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
Definition: Casting.h:328
This class represents lattice values for constants.
Definition: AllocatorList.h:23
std::unique_ptr< IPDBEnumSectionContribs > getSectionContribs() const override
LLVM_NODISCARD bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:289
PDB_NameSearchFlags
Defines flags used for enumerating child symbols.
Definition: PDBTypes.h:101
std::unique_ptr< PDBSymbol > findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type)
Error takeError()
Take ownership of the stored error.
Definition: Error.h:557
This file defines the BumpPtrAllocator interface.
IPDBSourceFile defines an interface used to represent source files whose information are stored in th...
Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr)
Create a Binary from Source, autodetecting the file type.
Definition: Binary.cpp:46
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:455
std::unique_ptr< IPDBEnumSourceFiles > findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern, PDB_NameSearchFlags Flags) const override
Definition: BitVector.h:959
NativeExeSymbol & getNativeGlobalScope() const
file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
Definition: Magic.cpp:34
std::unique_ptr< PDBSymbol > getSymbolById(SymIndexId SymbolId) const
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
static DbiStream * getDbiStreamPtr(PDBFile &File)
std::unique_ptr< IPDBEnumFrameData > getFrameData() const override
std::unique_ptr< IPDBEnumTables > getEnumTables() const override
std::unique_ptr< IPDBEnumLineNumbers > findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const override
uint64_t getVAFromSectOffset(uint32_t Section, uint32_t Offset) const
PDB_SymType
These values correspond to the SymTagEnum enumeration, and are documented here: https://msdn.microsoft.com/en-us/library/bkedss5f.aspx.
Definition: PDBTypes.h:242
std::unique_ptr< PDBSymbol > findSymbolByAddress(uint64_t Address, PDB_SymType Type) override
std::unique_ptr< PDBSymbol > getSymbolById(SymIndexId SymbolId) const override
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
static Error createFromPdbPath(StringRef PdbPath, std::unique_ptr< IPDBSession > &Session)
Instrumentation for Order File
uint64_t getLoadAddress() const override
std::error_code getError() const
Definition: ErrorOr.h:153
std::error_code getDebugPDBInfo(const debug_directory *DebugDir, const codeview::DebugInfo *&Info, StringRef &PDBFileName) const
Get PDB information out of a codeview debug directory entry.
std::unique_ptr< IPDBEnumLineNumbers > findLineNumbers(const PDBSymbolCompiland &Compiland, const IPDBSourceFile &File) const override
static Expected< std::string > getPdbPathFromExe(StringRef ExePath)
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1006
Expected< DbiStream & > getPDBDbiStream()
Definition: PDBFile.cpp:289
static Expected< std::string > searchForPdb(const PdbSearchOptions &Opts)
static const char *const Magic
Definition: Archive.cpp:41
Basic Register Allocator
static ErrorSuccess success()
Create a success value.
Definition: Error.h:332
std::unique_ptr< IPDBEnumSourceFiles > getSourceFilesForCompiland(const PDBSymbolCompiland &Compiland) const override
SymIndexId createSymbol(Args &&... ConstructorArgs)
Definition: SymbolCache.h:105
reference get()
Returns a reference to the stored T value.
Definition: Error.h:537
NativeRawSymbol & getNativeSymbolById(SymIndexId SymbolId) const
std::unique_ptr< PDBSymbolExe > getGlobalScope() override
bool setLoadAddress(uint64_t Address) override
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:577
std::unique_ptr< IPDBEnumLineNumbers > findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override
std::unique_ptr< PDBSymbolCompiland > findOneCompilandForSourceFile(llvm::StringRef Pattern, PDB_NameSearchFlags Flags) const override
std::unique_ptr< IPDBSourceFile > getSourceFileById(uint32_t FileId) const override
std::unique_ptr< IPDBEnumChildren< PDBSymbolCompiland > > findCompilandsForSourceFile(llvm::StringRef Pattern, PDB_NameSearchFlags Flags) const override
Provides ErrorOr<T> smart pointer.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
std::unique_ptr< IPDBSourceFile > findOneSourceFile(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern, PDB_NameSearchFlags Flags) const override
uint32_t getRVAFromSectOffset(uint32_t Section, uint32_t Offset) const
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
static Expected< std::unique_ptr< PDBFile > > loadPdbFile(StringRef PdbPath, std::unique_ptr< BumpPtrAllocator > &Allocator)
static Error createFromPdb(std::unique_ptr< MemoryBuffer > MB, std::unique_ptr< IPDBSession > &Session)
bool addressForRVA(uint32_t RVA, uint32_t &Section, uint32_t &Offset) const override
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
std::unique_ptr< IPDBEnumDataStreams > getDebugStreams() const override
std::unique_ptr< PDBSymbol > findSymbolByRVA(uint32_t RVA, PDB_SymType Type) override
std::unique_ptr< PDBSymbol > findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type) override
bool addressForVA(uint64_t VA, uint32_t &Section, uint32_t &Offset) const override
Windows PDB debug info file.
Definition: Magic.h:51
std::unique_ptr< IPDBEnumInjectedSources > getInjectedSources() const override
file_magic - An "enum class" enumeration of file types based on magic (the first N bytes of the file)...
Definition: Magic.h:20