Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
35293 views
//===- NativeSession.cpp - Native implementation of IPDBSession -*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DebugInfo/PDB/Native/NativeSession.h"910#include "llvm/ADT/SmallString.h"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"4041#include <algorithm>42#include <cassert>43#include <memory>44#include <utility>4546using namespace llvm;47using namespace llvm::msf;48using namespace llvm::pdb;4950namespace llvm {51namespace codeview {52union DebugInfo;53}54} // namespace llvm5556static DbiStream *getDbiStreamPtr(PDBFile &File) {57Expected<DbiStream &> DbiS = File.getPDBDbiStream();58if (DbiS)59return &DbiS.get();6061consumeError(DbiS.takeError());62return nullptr;63}6465NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile,66std::unique_ptr<BumpPtrAllocator> Allocator)67: Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)),68Cache(*this, getDbiStreamPtr(*Pdb)), AddrToModuleIndex(IMapAllocator) {}6970NativeSession::~NativeSession() = default;7172Error NativeSession::createFromPdb(std::unique_ptr<MemoryBuffer> Buffer,73std::unique_ptr<IPDBSession> &Session) {74StringRef Path = Buffer->getBufferIdentifier();75auto Stream = std::make_unique<MemoryBufferByteStream>(76std::move(Buffer), llvm::endianness::little);7778auto Allocator = std::make_unique<BumpPtrAllocator>();79auto File = std::make_unique<PDBFile>(Path, std::move(Stream), *Allocator);80if (auto EC = File->parseFileHeaders())81return EC;82if (auto EC = File->parseStreamData())83return EC;8485Session =86std::make_unique<NativeSession>(std::move(File), std::move(Allocator));8788return Error::success();89}9091static Expected<std::unique_ptr<PDBFile>>92loadPdbFile(StringRef PdbPath, std::unique_ptr<BumpPtrAllocator> &Allocator) {93ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =94MemoryBuffer::getFile(PdbPath, /*IsText=*/false,95/*RequiresNullTerminator=*/false);96if (!ErrorOrBuffer)97return make_error<RawError>(ErrorOrBuffer.getError());98std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);99100PdbPath = Buffer->getBufferIdentifier();101file_magic Magic;102auto EC = identify_magic(PdbPath, Magic);103if (EC || Magic != file_magic::pdb)104return make_error<RawError>(EC);105106auto Stream = std::make_unique<MemoryBufferByteStream>(107std::move(Buffer), llvm::endianness::little);108109auto File = std::make_unique<PDBFile>(PdbPath, std::move(Stream), *Allocator);110if (auto EC = File->parseFileHeaders())111return std::move(EC);112113if (auto EC = File->parseStreamData())114return std::move(EC);115116return std::move(File);117}118119Error NativeSession::createFromPdbPath(StringRef PdbPath,120std::unique_ptr<IPDBSession> &Session) {121auto Allocator = std::make_unique<BumpPtrAllocator>();122auto PdbFile = loadPdbFile(PdbPath, Allocator);123if (!PdbFile)124return PdbFile.takeError();125126Session = std::make_unique<NativeSession>(std::move(PdbFile.get()),127std::move(Allocator));128return Error::success();129}130131static Expected<std::string> getPdbPathFromExe(StringRef ExePath) {132Expected<object::OwningBinary<object::Binary>> BinaryFile =133object::createBinary(ExePath);134if (!BinaryFile)135return BinaryFile.takeError();136137const object::COFFObjectFile *ObjFile =138dyn_cast<object::COFFObjectFile>(BinaryFile->getBinary());139if (!ObjFile)140return make_error<RawError>(raw_error_code::invalid_format);141142StringRef PdbPath;143const llvm::codeview::DebugInfo *PdbInfo = nullptr;144if (Error E = ObjFile->getDebugPDBInfo(PdbInfo, PdbPath))145return std::move(E);146147return std::string(PdbPath);148}149150Error NativeSession::createFromExe(StringRef ExePath,151std::unique_ptr<IPDBSession> &Session) {152Expected<std::string> PdbPath = getPdbPathFromExe(ExePath);153if (!PdbPath)154return PdbPath.takeError();155156file_magic Magic;157auto EC = identify_magic(PdbPath.get(), Magic);158if (EC || Magic != file_magic::pdb)159return make_error<RawError>(EC);160161auto Allocator = std::make_unique<BumpPtrAllocator>();162auto File = loadPdbFile(PdbPath.get(), Allocator);163if (!File)164return File.takeError();165166Session = std::make_unique<NativeSession>(std::move(File.get()),167std::move(Allocator));168169return Error::success();170}171172Expected<std::string>173NativeSession::searchForPdb(const PdbSearchOptions &Opts) {174Expected<std::string> PathOrErr = getPdbPathFromExe(Opts.ExePath);175if (!PathOrErr)176return PathOrErr.takeError();177StringRef PathFromExe = PathOrErr.get();178sys::path::Style Style = PathFromExe.starts_with("/")179? sys::path::Style::posix180: sys::path::Style::windows;181StringRef PdbName = sys::path::filename(PathFromExe, Style);182183// Check if pdb exists in the executable directory.184SmallString<128> PdbPath = StringRef(Opts.ExePath);185sys::path::remove_filename(PdbPath);186sys::path::append(PdbPath, PdbName);187188auto Allocator = std::make_unique<BumpPtrAllocator>();189190if (auto File = loadPdbFile(PdbPath, Allocator))191return std::string(PdbPath);192else193consumeError(File.takeError());194195// Check path that was in the executable.196if (auto File = loadPdbFile(PathFromExe, Allocator))197return std::string(PathFromExe);198else199return File.takeError();200201return make_error<RawError>("PDB not found");202}203204uint64_t NativeSession::getLoadAddress() const { return LoadAddress; }205206bool NativeSession::setLoadAddress(uint64_t Address) {207LoadAddress = Address;208return true;209}210211std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() {212return PDBSymbol::createAs<PDBSymbolExe>(*this, getNativeGlobalScope());213}214215std::unique_ptr<PDBSymbol>216NativeSession::getSymbolById(SymIndexId SymbolId) const {217return Cache.getSymbolById(SymbolId);218}219220bool NativeSession::addressForVA(uint64_t VA, uint32_t &Section,221uint32_t &Offset) const {222uint32_t RVA = VA - getLoadAddress();223return addressForRVA(RVA, Section, Offset);224}225226bool NativeSession::addressForRVA(uint32_t RVA, uint32_t &Section,227uint32_t &Offset) const {228Section = 0;229Offset = 0;230231auto Dbi = Pdb->getPDBDbiStream();232if (!Dbi)233return false;234235if ((int32_t)RVA < 0)236return true;237238Offset = RVA;239for (; Section < Dbi->getSectionHeaders().size(); ++Section) {240auto &Sec = Dbi->getSectionHeaders()[Section];241if (RVA < Sec.VirtualAddress)242return true;243Offset = RVA - Sec.VirtualAddress;244}245return true;246}247248std::unique_ptr<PDBSymbol>249NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) {250uint32_t Section;251uint32_t Offset;252addressForVA(Address, Section, Offset);253return findSymbolBySectOffset(Section, Offset, Type);254}255256std::unique_ptr<PDBSymbol> NativeSession::findSymbolByRVA(uint32_t RVA,257PDB_SymType Type) {258uint32_t Section;259uint32_t Offset;260addressForRVA(RVA, Section, Offset);261return findSymbolBySectOffset(Section, Offset, Type);262}263264std::unique_ptr<PDBSymbol>265NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,266PDB_SymType Type) {267if (AddrToModuleIndex.empty())268parseSectionContribs();269270return Cache.findSymbolBySectOffset(Sect, Offset, Type);271}272273std::unique_ptr<IPDBEnumLineNumbers>274NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland,275const IPDBSourceFile &File) const {276return nullptr;277}278279std::unique_ptr<IPDBEnumLineNumbers>280NativeSession::findLineNumbersByAddress(uint64_t Address,281uint32_t Length) const {282return Cache.findLineNumbersByVA(Address, Length);283}284285std::unique_ptr<IPDBEnumLineNumbers>286NativeSession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const {287return Cache.findLineNumbersByVA(getLoadAddress() + RVA, Length);288}289290std::unique_ptr<IPDBEnumLineNumbers>291NativeSession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,292uint32_t Length) const {293uint64_t VA = getVAFromSectOffset(Section, Offset);294return Cache.findLineNumbersByVA(VA, Length);295}296297std::unique_ptr<IPDBEnumSourceFiles>298NativeSession::findSourceFiles(const PDBSymbolCompiland *Compiland,299StringRef Pattern,300PDB_NameSearchFlags Flags) const {301return nullptr;302}303304std::unique_ptr<IPDBSourceFile>305NativeSession::findOneSourceFile(const PDBSymbolCompiland *Compiland,306StringRef Pattern,307PDB_NameSearchFlags Flags) const {308return nullptr;309}310311std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>312NativeSession::findCompilandsForSourceFile(StringRef Pattern,313PDB_NameSearchFlags Flags) const {314return nullptr;315}316317std::unique_ptr<PDBSymbolCompiland>318NativeSession::findOneCompilandForSourceFile(StringRef Pattern,319PDB_NameSearchFlags Flags) const {320return nullptr;321}322323std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getAllSourceFiles() const {324return nullptr;325}326327std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getSourceFilesForCompiland(328const PDBSymbolCompiland &Compiland) const {329return nullptr;330}331332std::unique_ptr<IPDBSourceFile>333NativeSession::getSourceFileById(uint32_t FileId) const {334return Cache.getSourceFileById(FileId);335}336337std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const {338return nullptr;339}340341std::unique_ptr<IPDBEnumTables> NativeSession::getEnumTables() const {342return nullptr;343}344345std::unique_ptr<IPDBEnumInjectedSources>346NativeSession::getInjectedSources() const {347auto ISS = Pdb->getInjectedSourceStream();348if (!ISS) {349consumeError(ISS.takeError());350return nullptr;351}352auto Strings = Pdb->getStringTable();353if (!Strings) {354consumeError(Strings.takeError());355return nullptr;356}357return std::make_unique<NativeEnumInjectedSources>(*Pdb, *ISS, *Strings);358}359360std::unique_ptr<IPDBEnumSectionContribs>361NativeSession::getSectionContribs() const {362return nullptr;363}364365std::unique_ptr<IPDBEnumFrameData>366NativeSession::getFrameData() const {367return nullptr;368}369370void NativeSession::initializeExeSymbol() {371if (ExeSymbol == 0)372ExeSymbol = Cache.createSymbol<NativeExeSymbol>();373}374375NativeExeSymbol &NativeSession::getNativeGlobalScope() const {376const_cast<NativeSession &>(*this).initializeExeSymbol();377378return Cache.getNativeSymbolById<NativeExeSymbol>(ExeSymbol);379}380381uint32_t NativeSession::getRVAFromSectOffset(uint32_t Section,382uint32_t Offset) const {383if (Section <= 0)384return 0;385386auto Dbi = getDbiStreamPtr(*Pdb);387if (!Dbi)388return 0;389390uint32_t MaxSection = Dbi->getSectionHeaders().size();391if (Section > MaxSection + 1)392Section = MaxSection + 1;393auto &Sec = Dbi->getSectionHeaders()[Section - 1];394return Sec.VirtualAddress + Offset;395}396397uint64_t NativeSession::getVAFromSectOffset(uint32_t Section,398uint32_t Offset) const {399return LoadAddress + getRVAFromSectOffset(Section, Offset);400}401402bool NativeSession::moduleIndexForVA(uint64_t VA, uint16_t &ModuleIndex) const {403ModuleIndex = 0;404auto Iter = AddrToModuleIndex.find(VA);405if (Iter == AddrToModuleIndex.end())406return false;407ModuleIndex = Iter.value();408return true;409}410411bool NativeSession::moduleIndexForSectOffset(uint32_t Sect, uint32_t Offset,412uint16_t &ModuleIndex) const {413ModuleIndex = 0;414auto Iter = AddrToModuleIndex.find(getVAFromSectOffset(Sect, Offset));415if (Iter == AddrToModuleIndex.end())416return false;417ModuleIndex = Iter.value();418return true;419}420421void NativeSession::parseSectionContribs() {422auto Dbi = Pdb->getPDBDbiStream();423if (!Dbi)424return;425426class Visitor : public ISectionContribVisitor {427NativeSession &Session;428IMap &AddrMap;429430public:431Visitor(NativeSession &Session, IMap &AddrMap)432: Session(Session), AddrMap(AddrMap) {}433void visit(const SectionContrib &C) override {434if (C.Size == 0)435return;436437uint64_t VA = Session.getVAFromSectOffset(C.ISect, C.Off);438uint64_t End = VA + C.Size;439440// Ignore overlapping sections based on the assumption that a valid441// PDB file should not have overlaps.442if (!AddrMap.overlaps(VA, End))443AddrMap.insert(VA, End, C.Imod);444}445void visit(const SectionContrib2 &C) override { visit(C.Base); }446};447448Visitor V(*this, AddrToModuleIndex);449Dbi->visitSectionContributions(V);450}451452Expected<ModuleDebugStreamRef>453NativeSession::getModuleDebugStream(uint32_t Index) const {454auto *Dbi = getDbiStreamPtr(*Pdb);455assert(Dbi && "Dbi stream not present");456457DbiModuleDescriptor Modi = Dbi->modules().getModuleDescriptor(Index);458459uint16_t ModiStream = Modi.getModuleStreamIndex();460if (ModiStream == kInvalidStreamIndex)461return make_error<RawError>("Module stream not present");462463std::unique_ptr<msf::MappedBlockStream> ModStreamData =464Pdb->createIndexedStream(ModiStream);465466ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));467if (auto EC = ModS.reload())468return std::move(EC);469470return std::move(ModS);471}472473474