From cfca06d7963fa0909f90483b42a6d7d194d01e08 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 26 Jul 2020 19:36:28 +0000 Subject: Vendor import of llvm-project master 2e10b7a39b9, the last commit before the llvmorg-12-init tag, from which release/11.x was branched. --- llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp | 197 +++++++++++++++++++++--- 1 file changed, 179 insertions(+), 18 deletions(-) (limited to 'llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp') diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp index b45a5881dcb5..ac8449df44ff 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -12,6 +12,7 @@ #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" @@ -25,11 +26,14 @@ #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" +#include "llvm/Object/COFF.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/BinaryByteStream.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" #include #include @@ -75,14 +79,125 @@ Error NativeSession::createFromPdb(std::unique_ptr Buffer, return Error::success(); } -Error NativeSession::createFromExe(StringRef Path, +static Expected> +loadPdbFile(StringRef PdbPath, std::unique_ptr &Allocator) { + ErrorOr> ErrorOrBuffer = + MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1, + /*RequiresNullTerminator=*/false); + if (!ErrorOrBuffer) + return make_error(ErrorOrBuffer.getError()); + std::unique_ptr Buffer = std::move(*ErrorOrBuffer); + + PdbPath = Buffer->getBufferIdentifier(); + file_magic Magic; + auto EC = identify_magic(PdbPath, Magic); + if (EC || Magic != file_magic::pdb) + return make_error(EC); + + auto Stream = std::make_unique(std::move(Buffer), + llvm::support::little); + + auto File = std::make_unique(PdbPath, std::move(Stream), *Allocator); + if (auto EC = File->parseFileHeaders()) + return std::move(EC); + + if (auto EC = File->parseStreamData()) + return std::move(EC); + + return std::move(File); +} + +Error NativeSession::createFromPdbPath(StringRef PdbPath, + std::unique_ptr &Session) { + auto Allocator = std::make_unique(); + auto PdbFile = loadPdbFile(PdbPath, Allocator); + if (!PdbFile) + return PdbFile.takeError(); + + Session = std::make_unique(std::move(PdbFile.get()), + std::move(Allocator)); + return Error::success(); +} + +static Expected getPdbPathFromExe(StringRef ExePath) { + Expected> BinaryFile = + object::createBinary(ExePath); + if (!BinaryFile) + return BinaryFile.takeError(); + + const object::COFFObjectFile *ObjFile = + dyn_cast(BinaryFile->getBinary()); + if (!ObjFile) + return make_error(raw_error_code::invalid_format); + + StringRef PdbPath; + const llvm::codeview::DebugInfo *PdbInfo = nullptr; + if (Error E = ObjFile->getDebugPDBInfo(PdbInfo, PdbPath)) + return std::move(E); + + return std::string(PdbPath); +} + +Error NativeSession::createFromExe(StringRef ExePath, std::unique_ptr &Session) { - return make_error(raw_error_code::feature_unsupported); + Expected PdbPath = getPdbPathFromExe(ExePath); + if (!PdbPath) + return PdbPath.takeError(); + + file_magic Magic; + auto EC = identify_magic(PdbPath.get(), Magic); + if (EC || Magic != file_magic::pdb) + return make_error(EC); + + auto Allocator = std::make_unique(); + auto File = loadPdbFile(PdbPath.get(), Allocator); + if (!File) + return File.takeError(); + + Session = std::make_unique(std::move(File.get()), + std::move(Allocator)); + + return Error::success(); } -uint64_t NativeSession::getLoadAddress() const { return 0; } +Expected +NativeSession::searchForPdb(const PdbSearchOptions &Opts) { + Expected PathOrErr = getPdbPathFromExe(Opts.ExePath); + if (!PathOrErr) + return PathOrErr.takeError(); + StringRef PathFromExe = PathOrErr.get(); + sys::path::Style Style = PathFromExe.startswith("/") + ? sys::path::Style::posix + : sys::path::Style::windows; + StringRef PdbName = sys::path::filename(PathFromExe, Style); + + // Check if pdb exists in the executable directory. + SmallString<128> PdbPath = StringRef(Opts.ExePath); + sys::path::remove_filename(PdbPath); + sys::path::append(PdbPath, PdbName); -bool NativeSession::setLoadAddress(uint64_t Address) { return false; } + auto Allocator = std::make_unique(); + + if (auto File = loadPdbFile(PdbPath, Allocator)) + return std::string(PdbPath); + else + consumeError(File.takeError()); + + // Check path that was in the executable. + if (auto File = loadPdbFile(PathFromExe, Allocator)) + return std::string(PathFromExe); + else + return File.takeError(); + + return make_error("PDB not found"); +} + +uint64_t NativeSession::getLoadAddress() const { return LoadAddress; } + +bool NativeSession::setLoadAddress(uint64_t Address) { + LoadAddress = Address; + return true; +} std::unique_ptr NativeSession::getGlobalScope() { return PDBSymbol::createAs(*this, getNativeGlobalScope()); @@ -95,28 +210,52 @@ NativeSession::getSymbolById(SymIndexId SymbolId) const { bool NativeSession::addressForVA(uint64_t VA, uint32_t &Section, uint32_t &Offset) const { - return false; + uint32_t RVA = VA - getLoadAddress(); + return addressForRVA(RVA, Section, Offset); } -bool NativeSession::addressForRVA(uint32_t VA, uint32_t &Section, +bool NativeSession::addressForRVA(uint32_t RVA, uint32_t &Section, uint32_t &Offset) const { - return false; + Section = 0; + Offset = 0; + + auto Dbi = Pdb->getPDBDbiStream(); + if (!Dbi) + return false; + + if ((int32_t)RVA < 0) + return true; + + Offset = RVA; + for (; Section < Dbi->getSectionHeaders().size(); ++Section) { + auto &Sec = Dbi->getSectionHeaders()[Section]; + if (RVA < Sec.VirtualAddress) + return true; + Offset = RVA - Sec.VirtualAddress; + } + return true; } std::unique_ptr -NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const { - return nullptr; +NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) { + uint32_t Section; + uint32_t Offset; + addressForVA(Address, Section, Offset); + return findSymbolBySectOffset(Section, Offset, Type); } -std::unique_ptr -NativeSession::findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const { - return nullptr; +std::unique_ptr NativeSession::findSymbolByRVA(uint32_t RVA, + PDB_SymType Type) { + uint32_t Section; + uint32_t Offset; + addressForRVA(RVA, Section, Offset); + return findSymbolBySectOffset(Section, Offset, Type); } std::unique_ptr NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, - PDB_SymType Type) const { - return nullptr; + PDB_SymType Type) { + return Cache.findSymbolBySectOffset(Sect, Offset, Type); } std::unique_ptr @@ -128,18 +267,19 @@ NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland, std::unique_ptr NativeSession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const { - return nullptr; + return Cache.findLineNumbersByVA(Address, Length); } std::unique_ptr NativeSession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const { - return nullptr; + return findLineNumbersByAddress(getLoadAddress() + RVA, Length); } std::unique_ptr NativeSession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset, uint32_t Length) const { - return nullptr; + uint64_t VA = getVAFromSectOffset(Section, Offset); + return findLineNumbersByAddress(VA, Length); } std::unique_ptr @@ -179,7 +319,7 @@ std::unique_ptr NativeSession::getSourceFilesForCompiland( std::unique_ptr NativeSession::getSourceFileById(uint32_t FileId) const { - return nullptr; + return Cache.getSourceFileById(FileId); } std::unique_ptr NativeSession::getDebugStreams() const { @@ -225,3 +365,24 @@ NativeExeSymbol &NativeSession::getNativeGlobalScope() const { return Cache.getNativeSymbolById(ExeSymbol); } + +uint32_t NativeSession::getRVAFromSectOffset(uint32_t Section, + uint32_t Offset) const { + if (Section <= 0) + return 0; + + auto Dbi = getDbiStreamPtr(*Pdb); + if (!Dbi) + return 0; + + uint32_t MaxSection = Dbi->getSectionHeaders().size(); + if (Section > MaxSection + 1) + Section = MaxSection + 1; + auto &Sec = Dbi->getSectionHeaders()[Section - 1]; + return Sec.VirtualAddress + Offset; +} + +uint64_t NativeSession::getVAFromSectOffset(uint32_t Section, + uint32_t Offset) const { + return LoadAddress + getRVAFromSectOffset(Section, Offset); +} -- cgit v1.2.3