Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp
35293 views
//===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//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/DbiStream.h"9#include "llvm/ADT/StringRef.h"10#include "llvm/DebugInfo/MSF/MappedBlockStream.h"11#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"12#include "llvm/DebugInfo/PDB/Native/PDBFile.h"13#include "llvm/DebugInfo/PDB/Native/RawConstants.h"14#include "llvm/DebugInfo/PDB/Native/RawError.h"15#include "llvm/DebugInfo/PDB/Native/RawTypes.h"16#include "llvm/DebugInfo/PDB/PDBTypes.h"17#include "llvm/Object/COFF.h"18#include "llvm/Support/BinaryStreamArray.h"19#include "llvm/Support/BinaryStreamReader.h"20#include "llvm/Support/Error.h"21#include <cstddef>22#include <cstdint>2324using namespace llvm;25using namespace llvm::codeview;26using namespace llvm::msf;27using namespace llvm::pdb;28using namespace llvm::support;2930template <typename ContribType>31static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,32BinaryStreamReader &Reader) {33if (Reader.bytesRemaining() % sizeof(ContribType) != 0)34return make_error<RawError>(35raw_error_code::corrupt_file,36"Invalid number of bytes of section contributions");3738uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);39if (auto EC = Reader.readArray(Output, Count))40return EC;41return Error::success();42}4344DbiStream::DbiStream(std::unique_ptr<BinaryStream> Stream)45: Stream(std::move(Stream)), Header(nullptr) {}4647DbiStream::~DbiStream() = default;4849Error DbiStream::reload(PDBFile *Pdb) {50BinaryStreamReader Reader(*Stream);5152if (Stream->getLength() < sizeof(DbiStreamHeader))53return make_error<RawError>(raw_error_code::corrupt_file,54"DBI Stream does not contain a header.");55if (auto EC = Reader.readObject(Header))56return make_error<RawError>(raw_error_code::corrupt_file,57"DBI Stream does not contain a header.");5859if (Header->VersionSignature != -1)60return make_error<RawError>(raw_error_code::corrupt_file,61"Invalid DBI version signature.");6263// Require at least version 7, which should be present in all PDBs64// produced in the last decade and allows us to avoid having to65// special case all kinds of complicated arcane formats.66if (Header->VersionHeader < PdbDbiV70)67return make_error<RawError>(raw_error_code::feature_unsupported,68"Unsupported DBI version.");6970if (Stream->getLength() !=71sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +72Header->SecContrSubstreamSize + Header->SectionMapSize +73Header->FileInfoSize + Header->TypeServerSize +74Header->OptionalDbgHdrSize + Header->ECSubstreamSize)75return make_error<RawError>(raw_error_code::corrupt_file,76"DBI Length does not equal sum of substreams.");7778// Only certain substreams are guaranteed to be aligned. Validate79// them here.80if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)81return make_error<RawError>(raw_error_code::corrupt_file,82"DBI MODI substream not aligned.");83if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)84return make_error<RawError>(85raw_error_code::corrupt_file,86"DBI section contribution substream not aligned.");87if (Header->SectionMapSize % sizeof(uint32_t) != 0)88return make_error<RawError>(raw_error_code::corrupt_file,89"DBI section map substream not aligned.");90if (Header->FileInfoSize % sizeof(uint32_t) != 0)91return make_error<RawError>(raw_error_code::corrupt_file,92"DBI file info substream not aligned.");93if (Header->TypeServerSize % sizeof(uint32_t) != 0)94return make_error<RawError>(raw_error_code::corrupt_file,95"DBI type server substream not aligned.");9697if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize))98return EC;99100if (auto EC = Reader.readSubstream(SecContrSubstream,101Header->SecContrSubstreamSize))102return EC;103if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize))104return EC;105if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize))106return EC;107if (auto EC =108Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize))109return EC;110if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize))111return EC;112if (auto EC = Reader.readArray(113DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))114return EC;115116if (auto EC = Modules.initialize(ModiSubstream.StreamData,117FileInfoSubstream.StreamData))118return EC;119120if (auto EC = initializeSectionContributionData())121return EC;122if (auto EC = initializeSectionHeadersData(Pdb))123return EC;124if (auto EC = initializeSectionMapData())125return EC;126if (auto EC = initializeOldFpoRecords(Pdb))127return EC;128if (auto EC = initializeNewFpoRecords(Pdb))129return EC;130131if (Reader.bytesRemaining() > 0)132return make_error<RawError>(raw_error_code::corrupt_file,133"Found unexpected bytes in DBI Stream.");134135if (!ECSubstream.empty()) {136BinaryStreamReader ECReader(ECSubstream.StreamData);137if (auto EC = ECNames.reload(ECReader))138return EC;139}140141return Error::success();142}143144PdbRaw_DbiVer DbiStream::getDbiVersion() const {145uint32_t Value = Header->VersionHeader;146return static_cast<PdbRaw_DbiVer>(Value);147}148149uint32_t DbiStream::getAge() const { return Header->Age; }150151uint16_t DbiStream::getPublicSymbolStreamIndex() const {152return Header->PublicSymbolStreamIndex;153}154155uint16_t DbiStream::getGlobalSymbolStreamIndex() const {156return Header->GlobalSymbolStreamIndex;157}158159uint16_t DbiStream::getFlags() const { return Header->Flags; }160161bool DbiStream::isIncrementallyLinked() const {162return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;163}164165bool DbiStream::hasCTypes() const {166return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;167}168169bool DbiStream::isStripped() const {170return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;171}172173uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }174175uint16_t DbiStream::getBuildMajorVersion() const {176return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>177DbiBuildNo::BuildMajorShift;178}179180uint16_t DbiStream::getBuildMinorVersion() const {181return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>182DbiBuildNo::BuildMinorShift;183}184185uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }186187uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }188189uint32_t DbiStream::getSymRecordStreamIndex() const {190return Header->SymRecordStreamIndex;191}192193PDB_Machine DbiStream::getMachineType() const {194uint16_t Machine = Header->MachineType;195return static_cast<PDB_Machine>(Machine);196}197198FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() const {199return SectionHeaders;200}201202bool DbiStream::hasOldFpoRecords() const { return OldFpoStream != nullptr; }203204FixedStreamArray<object::FpoData> DbiStream::getOldFpoRecords() const {205return OldFpoRecords;206}207208bool DbiStream::hasNewFpoRecords() const { return NewFpoStream != nullptr; }209210const DebugFrameDataSubsectionRef &DbiStream::getNewFpoRecords() const {211return NewFpoRecords;212}213214const DbiModuleList &DbiStream::modules() const { return Modules; }215216FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {217return SectionMap;218}219220void DbiStream::visitSectionContributions(221ISectionContribVisitor &Visitor) const {222if (!SectionContribs.empty()) {223assert(SectionContribVersion == DbiSecContribVer60);224for (auto &SC : SectionContribs)225Visitor.visit(SC);226} else if (!SectionContribs2.empty()) {227assert(SectionContribVersion == DbiSecContribV2);228for (auto &SC : SectionContribs2)229Visitor.visit(SC);230}231}232233Expected<StringRef> DbiStream::getECName(uint32_t NI) const {234return ECNames.getStringForID(NI);235}236237Error DbiStream::initializeSectionContributionData() {238if (SecContrSubstream.empty())239return Error::success();240241BinaryStreamReader SCReader(SecContrSubstream.StreamData);242if (auto EC = SCReader.readEnum(SectionContribVersion))243return EC;244245if (SectionContribVersion == DbiSecContribVer60)246return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);247if (SectionContribVersion == DbiSecContribV2)248return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);249250return make_error<RawError>(raw_error_code::feature_unsupported,251"Unsupported DBI Section Contribution version");252}253254// Initializes this->SectionHeaders.255Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) {256Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =257createIndexedStreamForHeaderType(Pdb, DbgHeaderType::SectionHdr);258if (auto EC = ExpectedStream.takeError())259return EC;260261auto &SHS = *ExpectedStream;262if (!SHS)263return Error::success();264265size_t StreamLen = SHS->getLength();266if (StreamLen % sizeof(object::coff_section))267return make_error<RawError>(raw_error_code::corrupt_file,268"Corrupted section header stream.");269270size_t NumSections = StreamLen / sizeof(object::coff_section);271BinaryStreamReader Reader(*SHS);272if (auto EC = Reader.readArray(SectionHeaders, NumSections))273return make_error<RawError>(raw_error_code::corrupt_file,274"Could not read a bitmap.");275276SectionHeaderStream = std::move(SHS);277return Error::success();278}279280// Initializes this->Fpos.281Error DbiStream::initializeOldFpoRecords(PDBFile *Pdb) {282Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =283createIndexedStreamForHeaderType(Pdb, DbgHeaderType::FPO);284if (auto EC = ExpectedStream.takeError())285return EC;286287auto &FS = *ExpectedStream;288if (!FS)289return Error::success();290291size_t StreamLen = FS->getLength();292if (StreamLen % sizeof(object::FpoData))293return make_error<RawError>(raw_error_code::corrupt_file,294"Corrupted Old FPO stream.");295296size_t NumRecords = StreamLen / sizeof(object::FpoData);297BinaryStreamReader Reader(*FS);298if (auto EC = Reader.readArray(OldFpoRecords, NumRecords))299return make_error<RawError>(raw_error_code::corrupt_file,300"Corrupted Old FPO stream.");301OldFpoStream = std::move(FS);302return Error::success();303}304305Error DbiStream::initializeNewFpoRecords(PDBFile *Pdb) {306Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =307createIndexedStreamForHeaderType(Pdb, DbgHeaderType::NewFPO);308if (auto EC = ExpectedStream.takeError())309return EC;310311auto &FS = *ExpectedStream;312if (!FS)313return Error::success();314315if (auto EC = NewFpoRecords.initialize(*FS))316return EC;317318NewFpoStream = std::move(FS);319return Error::success();320}321322Expected<std::unique_ptr<msf::MappedBlockStream>>323DbiStream::createIndexedStreamForHeaderType(PDBFile *Pdb,324DbgHeaderType Type) const {325if (!Pdb)326return nullptr;327328if (DbgStreams.empty())329return nullptr;330331uint32_t StreamNum = getDebugStreamIndex(Type);332333// This means there is no such stream.334if (StreamNum == kInvalidStreamIndex)335return nullptr;336337return Pdb->safelyCreateIndexedStream(StreamNum);338}339340BinarySubstreamRef DbiStream::getSectionContributionData() const {341return SecContrSubstream;342}343344BinarySubstreamRef DbiStream::getSecMapSubstreamData() const {345return SecMapSubstream;346}347348BinarySubstreamRef DbiStream::getModiSubstreamData() const {349return ModiSubstream;350}351352BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const {353return FileInfoSubstream;354}355356BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const {357return TypeServerMapSubstream;358}359360BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; }361362Error DbiStream::initializeSectionMapData() {363if (SecMapSubstream.empty())364return Error::success();365366BinaryStreamReader SMReader(SecMapSubstream.StreamData);367const SecMapHeader *Header;368if (auto EC = SMReader.readObject(Header))369return EC;370if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))371return EC;372return Error::success();373}374375uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {376uint16_t T = static_cast<uint16_t>(Type);377if (T >= DbgStreams.size())378return kInvalidStreamIndex;379return DbgStreams[T];380}381382383