diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h --- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h @@ -109,6 +109,7 @@ SymbolCache Cache; SymIndexId ExeSymbol = 0; + uint64_t LoadAddress = 0; }; } // namespace pdb } // namespace llvm diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp --- a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -29,7 +29,10 @@ #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 "llvm/object/COFF.h" #include #include @@ -77,12 +80,62 @@ Error NativeSession::createFromExe(StringRef Path, std::unique_ptr &Session) { - return make_error(raw_error_code::feature_unsupported); + // Get PDB path. + Expected> BinaryFile = + object::createBinary(Path); + 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 (auto EC = ObjFile->getDebugPDBInfo(PdbInfo, PdbPath)) + return make_error(EC); + + // If PDB path doesn't exist, search in the current directory. + SmallString<128> TmpPath = Path; + if (!sys::fs::exists(PdbPath)) { + sys::path::remove_filename(TmpPath); + sys::path::append(TmpPath, sys::path::filename(PdbPath)); + PdbPath = TmpPath; + } + + file_magic Magic; + auto EC = identify_magic(PdbPath, Magic); + if (EC || Magic != file_magic::pdb) + return make_error(EC); + + ErrorOr> ErrorOrBuffer = + MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1, + /*RequiresNullTerminator=*/false); + if (!ErrorOrBuffer) + return make_error(ErrorOrBuffer.getError()); + std::unique_ptr Buffer = std::move(*ErrorOrBuffer); + + auto Stream = std::make_unique(std::move(Buffer), + llvm::support::little); + auto Allocator = std::make_unique(); + auto File = std::make_unique(PdbPath, std::move(Stream), *Allocator); + + if (auto EC = File->parseFileHeaders()) + return EC; + if (auto EC = File->parseStreamData()) + return EC; + + Session = + std::make_unique(std::move(File), std::move(Allocator)); + + return Error::success(); } -uint64_t NativeSession::getLoadAddress() const { return 0; } +uint64_t NativeSession::getLoadAddress() const { return LoadAddress; } -bool NativeSession::setLoadAddress(uint64_t Address) { return false; } +bool NativeSession::setLoadAddress(uint64_t Address) { + LoadAddress = Address; + return true; +} std::unique_ptr NativeSession::getGlobalScope() { return PDBSymbol::createAs(*this, getNativeGlobalScope()); @@ -95,11 +148,26 @@ 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 { + auto Dbi = Pdb->getPDBDbiStream(); + if (!Dbi) + return false; + + uint32_t Index = 1; + for (auto &Sec : Dbi->getSectionHeaders()) { + if (RVA >= Sec.VirtualAddress && + RVA < Sec.VirtualAddress + Sec.VirtualSize) { + Section = Index; + Offset = RVA - Sec.VirtualAddress; + return true; + } + ++Index; + } return false; }