123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- //===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
- #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
- #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
- #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
- #include "llvm/DebugInfo/PDB/Native/RawError.h"
- #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
- #include "llvm/DebugInfo/PDB/PDBTypes.h"
- #include "llvm/Object/COFF.h"
- #include "llvm/Support/BinaryStreamArray.h"
- #include "llvm/Support/BinaryStreamReader.h"
- #include "llvm/Support/Error.h"
- #include <cstddef>
- #include <cstdint>
- using namespace llvm;
- using namespace llvm::codeview;
- using namespace llvm::msf;
- using namespace llvm::pdb;
- using namespace llvm::support;
- template <typename ContribType>
- static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
- BinaryStreamReader &Reader) {
- if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
- return make_error<RawError>(
- raw_error_code::corrupt_file,
- "Invalid number of bytes of section contributions");
- uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
- if (auto EC = Reader.readArray(Output, Count))
- return EC;
- return Error::success();
- }
- DbiStream::DbiStream(std::unique_ptr<BinaryStream> Stream)
- : Stream(std::move(Stream)), Header(nullptr) {}
- DbiStream::~DbiStream() = default;
- Error DbiStream::reload(PDBFile *Pdb) {
- BinaryStreamReader Reader(*Stream);
- if (Stream->getLength() < sizeof(DbiStreamHeader))
- return make_error<RawError>(raw_error_code::corrupt_file,
- "DBI Stream does not contain a header.");
- if (auto EC = Reader.readObject(Header))
- return make_error<RawError>(raw_error_code::corrupt_file,
- "DBI Stream does not contain a header.");
- if (Header->VersionSignature != -1)
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Invalid DBI version signature.");
- // Require at least version 7, which should be present in all PDBs
- // produced in the last decade and allows us to avoid having to
- // special case all kinds of complicated arcane formats.
- if (Header->VersionHeader < PdbDbiV70)
- return make_error<RawError>(raw_error_code::feature_unsupported,
- "Unsupported DBI version.");
- if (Stream->getLength() !=
- sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
- Header->SecContrSubstreamSize + Header->SectionMapSize +
- Header->FileInfoSize + Header->TypeServerSize +
- Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
- return make_error<RawError>(raw_error_code::corrupt_file,
- "DBI Length does not equal sum of substreams.");
- // Only certain substreams are guaranteed to be aligned. Validate
- // them here.
- if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
- return make_error<RawError>(raw_error_code::corrupt_file,
- "DBI MODI substream not aligned.");
- if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
- return make_error<RawError>(
- raw_error_code::corrupt_file,
- "DBI section contribution substream not aligned.");
- if (Header->SectionMapSize % sizeof(uint32_t) != 0)
- return make_error<RawError>(raw_error_code::corrupt_file,
- "DBI section map substream not aligned.");
- if (Header->FileInfoSize % sizeof(uint32_t) != 0)
- return make_error<RawError>(raw_error_code::corrupt_file,
- "DBI file info substream not aligned.");
- if (Header->TypeServerSize % sizeof(uint32_t) != 0)
- return make_error<RawError>(raw_error_code::corrupt_file,
- "DBI type server substream not aligned.");
- if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize))
- return EC;
- if (auto EC = Reader.readSubstream(SecContrSubstream,
- Header->SecContrSubstreamSize))
- return EC;
- if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize))
- return EC;
- if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize))
- return EC;
- if (auto EC =
- Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize))
- return EC;
- if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize))
- return EC;
- if (auto EC = Reader.readArray(
- DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))
- return EC;
- if (auto EC = Modules.initialize(ModiSubstream.StreamData,
- FileInfoSubstream.StreamData))
- return EC;
- if (auto EC = initializeSectionContributionData())
- return EC;
- if (auto EC = initializeSectionHeadersData(Pdb))
- return EC;
- if (auto EC = initializeSectionMapData())
- return EC;
- if (auto EC = initializeOldFpoRecords(Pdb))
- return EC;
- if (auto EC = initializeNewFpoRecords(Pdb))
- return EC;
- if (Reader.bytesRemaining() > 0)
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Found unexpected bytes in DBI Stream.");
- if (!ECSubstream.empty()) {
- BinaryStreamReader ECReader(ECSubstream.StreamData);
- if (auto EC = ECNames.reload(ECReader))
- return EC;
- }
- return Error::success();
- }
- PdbRaw_DbiVer DbiStream::getDbiVersion() const {
- uint32_t Value = Header->VersionHeader;
- return static_cast<PdbRaw_DbiVer>(Value);
- }
- uint32_t DbiStream::getAge() const { return Header->Age; }
- uint16_t DbiStream::getPublicSymbolStreamIndex() const {
- return Header->PublicSymbolStreamIndex;
- }
- uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
- return Header->GlobalSymbolStreamIndex;
- }
- uint16_t DbiStream::getFlags() const { return Header->Flags; }
- bool DbiStream::isIncrementallyLinked() const {
- return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
- }
- bool DbiStream::hasCTypes() const {
- return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
- }
- bool DbiStream::isStripped() const {
- return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
- }
- uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
- uint16_t DbiStream::getBuildMajorVersion() const {
- return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
- DbiBuildNo::BuildMajorShift;
- }
- uint16_t DbiStream::getBuildMinorVersion() const {
- return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
- DbiBuildNo::BuildMinorShift;
- }
- uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
- uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
- uint32_t DbiStream::getSymRecordStreamIndex() const {
- return Header->SymRecordStreamIndex;
- }
- PDB_Machine DbiStream::getMachineType() const {
- uint16_t Machine = Header->MachineType;
- return static_cast<PDB_Machine>(Machine);
- }
- FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() const {
- return SectionHeaders;
- }
- bool DbiStream::hasOldFpoRecords() const { return OldFpoStream != nullptr; }
- FixedStreamArray<object::FpoData> DbiStream::getOldFpoRecords() const {
- return OldFpoRecords;
- }
- bool DbiStream::hasNewFpoRecords() const { return NewFpoStream != nullptr; }
- const DebugFrameDataSubsectionRef &DbiStream::getNewFpoRecords() const {
- return NewFpoRecords;
- }
- const DbiModuleList &DbiStream::modules() const { return Modules; }
- FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
- return SectionMap;
- }
- void DbiStream::visitSectionContributions(
- ISectionContribVisitor &Visitor) const {
- if (!SectionContribs.empty()) {
- assert(SectionContribVersion == DbiSecContribVer60);
- for (auto &SC : SectionContribs)
- Visitor.visit(SC);
- } else if (!SectionContribs2.empty()) {
- assert(SectionContribVersion == DbiSecContribV2);
- for (auto &SC : SectionContribs2)
- Visitor.visit(SC);
- }
- }
- Expected<StringRef> DbiStream::getECName(uint32_t NI) const {
- return ECNames.getStringForID(NI);
- }
- Error DbiStream::initializeSectionContributionData() {
- if (SecContrSubstream.empty())
- return Error::success();
- BinaryStreamReader SCReader(SecContrSubstream.StreamData);
- if (auto EC = SCReader.readEnum(SectionContribVersion))
- return EC;
- if (SectionContribVersion == DbiSecContribVer60)
- return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
- if (SectionContribVersion == DbiSecContribV2)
- return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
- return make_error<RawError>(raw_error_code::feature_unsupported,
- "Unsupported DBI Section Contribution version");
- }
- // Initializes this->SectionHeaders.
- Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) {
- Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
- createIndexedStreamForHeaderType(Pdb, DbgHeaderType::SectionHdr);
- if (auto EC = ExpectedStream.takeError())
- return EC;
- auto &SHS = *ExpectedStream;
- if (!SHS)
- return Error::success();
- size_t StreamLen = SHS->getLength();
- if (StreamLen % sizeof(object::coff_section))
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Corrupted section header stream.");
- size_t NumSections = StreamLen / sizeof(object::coff_section);
- BinaryStreamReader Reader(*SHS);
- if (auto EC = Reader.readArray(SectionHeaders, NumSections))
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Could not read a bitmap.");
- SectionHeaderStream = std::move(SHS);
- return Error::success();
- }
- // Initializes this->Fpos.
- Error DbiStream::initializeOldFpoRecords(PDBFile *Pdb) {
- Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
- createIndexedStreamForHeaderType(Pdb, DbgHeaderType::FPO);
- if (auto EC = ExpectedStream.takeError())
- return EC;
- auto &FS = *ExpectedStream;
- if (!FS)
- return Error::success();
- size_t StreamLen = FS->getLength();
- if (StreamLen % sizeof(object::FpoData))
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Corrupted Old FPO stream.");
- size_t NumRecords = StreamLen / sizeof(object::FpoData);
- BinaryStreamReader Reader(*FS);
- if (auto EC = Reader.readArray(OldFpoRecords, NumRecords))
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Corrupted Old FPO stream.");
- OldFpoStream = std::move(FS);
- return Error::success();
- }
- Error DbiStream::initializeNewFpoRecords(PDBFile *Pdb) {
- Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
- createIndexedStreamForHeaderType(Pdb, DbgHeaderType::NewFPO);
- if (auto EC = ExpectedStream.takeError())
- return EC;
- auto &FS = *ExpectedStream;
- if (!FS)
- return Error::success();
- if (auto EC = NewFpoRecords.initialize(*FS))
- return EC;
- NewFpoStream = std::move(FS);
- return Error::success();
- }
- Expected<std::unique_ptr<msf::MappedBlockStream>>
- DbiStream::createIndexedStreamForHeaderType(PDBFile *Pdb,
- DbgHeaderType Type) const {
- if (!Pdb)
- return nullptr;
- if (DbgStreams.empty())
- return nullptr;
- uint32_t StreamNum = getDebugStreamIndex(Type);
- // This means there is no such stream.
- if (StreamNum == kInvalidStreamIndex)
- return nullptr;
- return Pdb->safelyCreateIndexedStream(StreamNum);
- }
- BinarySubstreamRef DbiStream::getSectionContributionData() const {
- return SecContrSubstream;
- }
- BinarySubstreamRef DbiStream::getSecMapSubstreamData() const {
- return SecMapSubstream;
- }
- BinarySubstreamRef DbiStream::getModiSubstreamData() const {
- return ModiSubstream;
- }
- BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const {
- return FileInfoSubstream;
- }
- BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const {
- return TypeServerMapSubstream;
- }
- BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; }
- Error DbiStream::initializeSectionMapData() {
- if (SecMapSubstream.empty())
- return Error::success();
- BinaryStreamReader SMReader(SecMapSubstream.StreamData);
- const SecMapHeader *Header;
- if (auto EC = SMReader.readObject(Header))
- return EC;
- if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
- return EC;
- return Error::success();
- }
- uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
- uint16_t T = static_cast<uint16_t>(Type);
- if (T >= DbgStreams.size())
- return kInvalidStreamIndex;
- return DbgStreams[T];
- }
|