brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.7 KiB · 1a22673 Raw
382 lines · cpp
1//===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/DebugInfo/PDB/Native/DbiStream.h"10#include "llvm/ADT/StringRef.h"11#include "llvm/DebugInfo/MSF/MappedBlockStream.h"12#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"13#include "llvm/DebugInfo/PDB/Native/PDBFile.h"14#include "llvm/DebugInfo/PDB/Native/RawConstants.h"15#include "llvm/DebugInfo/PDB/Native/RawError.h"16#include "llvm/DebugInfo/PDB/Native/RawTypes.h"17#include "llvm/DebugInfo/PDB/PDBTypes.h"18#include "llvm/Object/COFF.h"19#include "llvm/Support/BinaryStreamArray.h"20#include "llvm/Support/BinaryStreamReader.h"21#include "llvm/Support/Error.h"22#include <cstddef>23#include <cstdint>24 25using namespace llvm;26using namespace llvm::codeview;27using namespace llvm::msf;28using namespace llvm::pdb;29using namespace llvm::support;30 31template <typename ContribType>32static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,33                                 BinaryStreamReader &Reader) {34  if (Reader.bytesRemaining() % sizeof(ContribType) != 0)35    return make_error<RawError>(36        raw_error_code::corrupt_file,37        "Invalid number of bytes of section contributions");38 39  uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);40  if (auto EC = Reader.readArray(Output, Count))41    return EC;42  return Error::success();43}44 45DbiStream::DbiStream(std::unique_ptr<BinaryStream> Stream)46    : Stream(std::move(Stream)), Header(nullptr) {}47 48DbiStream::~DbiStream() = default;49 50Error DbiStream::reload(PDBFile *Pdb) {51  BinaryStreamReader Reader(*Stream);52 53  if (Stream->getLength() < sizeof(DbiStreamHeader))54    return make_error<RawError>(raw_error_code::corrupt_file,55                                "DBI Stream does not contain a header.");56  if (auto EC = Reader.readObject(Header))57    return make_error<RawError>(raw_error_code::corrupt_file,58                                "DBI Stream does not contain a header.");59 60  if (Header->VersionSignature != -1)61    return make_error<RawError>(raw_error_code::corrupt_file,62                                "Invalid DBI version signature.");63 64  // Require at least version 7, which should be present in all PDBs65  // produced in the last decade and allows us to avoid having to66  // special case all kinds of complicated arcane formats.67  if (Header->VersionHeader < PdbDbiV70)68    return make_error<RawError>(raw_error_code::feature_unsupported,69                                "Unsupported DBI version.");70 71  if (Stream->getLength() !=72      sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +73          Header->SecContrSubstreamSize + Header->SectionMapSize +74          Header->FileInfoSize + Header->TypeServerSize +75          Header->OptionalDbgHdrSize + Header->ECSubstreamSize)76    return make_error<RawError>(raw_error_code::corrupt_file,77                                "DBI Length does not equal sum of substreams.");78 79  // Only certain substreams are guaranteed to be aligned.  Validate80  // them here.81  if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)82    return make_error<RawError>(raw_error_code::corrupt_file,83                                "DBI MODI substream not aligned.");84  if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)85    return make_error<RawError>(86        raw_error_code::corrupt_file,87        "DBI section contribution substream not aligned.");88  if (Header->SectionMapSize % sizeof(uint32_t) != 0)89    return make_error<RawError>(raw_error_code::corrupt_file,90                                "DBI section map substream not aligned.");91  if (Header->FileInfoSize % sizeof(uint32_t) != 0)92    return make_error<RawError>(raw_error_code::corrupt_file,93                                "DBI file info substream not aligned.");94  if (Header->TypeServerSize % sizeof(uint32_t) != 0)95    return make_error<RawError>(raw_error_code::corrupt_file,96                                "DBI type server substream not aligned.");97 98  if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize))99    return EC;100 101  if (auto EC = Reader.readSubstream(SecContrSubstream,102                                     Header->SecContrSubstreamSize))103    return EC;104  if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize))105    return EC;106  if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize))107    return EC;108  if (auto EC =109          Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize))110    return EC;111  if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize))112    return EC;113  if (auto EC = Reader.readArray(114          DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))115    return EC;116 117  if (auto EC = Modules.initialize(ModiSubstream.StreamData,118                                   FileInfoSubstream.StreamData))119    return EC;120 121  if (auto EC = initializeSectionContributionData())122    return EC;123  if (auto EC = initializeSectionHeadersData(Pdb))124    return EC;125  if (auto EC = initializeSectionMapData())126    return EC;127  if (auto EC = initializeOldFpoRecords(Pdb))128    return EC;129  if (auto EC = initializeNewFpoRecords(Pdb))130     return EC;131 132  if (Reader.bytesRemaining() > 0)133    return make_error<RawError>(raw_error_code::corrupt_file,134                                "Found unexpected bytes in DBI Stream.");135 136  if (!ECSubstream.empty()) {137    BinaryStreamReader ECReader(ECSubstream.StreamData);138    if (auto EC = ECNames.reload(ECReader))139      return EC;140  }141 142  return Error::success();143}144 145PdbRaw_DbiVer DbiStream::getDbiVersion() const {146  uint32_t Value = Header->VersionHeader;147  return static_cast<PdbRaw_DbiVer>(Value);148}149 150uint32_t DbiStream::getAge() const { return Header->Age; }151 152uint16_t DbiStream::getPublicSymbolStreamIndex() const {153  return Header->PublicSymbolStreamIndex;154}155 156uint16_t DbiStream::getGlobalSymbolStreamIndex() const {157  return Header->GlobalSymbolStreamIndex;158}159 160uint16_t DbiStream::getFlags() const { return Header->Flags; }161 162bool DbiStream::isIncrementallyLinked() const {163  return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;164}165 166bool DbiStream::hasCTypes() const {167  return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;168}169 170bool DbiStream::isStripped() const {171  return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;172}173 174uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }175 176uint16_t DbiStream::getBuildMajorVersion() const {177  return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>178         DbiBuildNo::BuildMajorShift;179}180 181uint16_t DbiStream::getBuildMinorVersion() const {182  return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>183         DbiBuildNo::BuildMinorShift;184}185 186uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }187 188uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }189 190uint32_t DbiStream::getSymRecordStreamIndex() const {191  return Header->SymRecordStreamIndex;192}193 194PDB_Machine DbiStream::getMachineType() const {195  uint16_t Machine = Header->MachineType;196  return static_cast<PDB_Machine>(Machine);197}198 199FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() const {200  return SectionHeaders;201}202 203bool DbiStream::hasOldFpoRecords() const { return OldFpoStream != nullptr; }204 205FixedStreamArray<object::FpoData> DbiStream::getOldFpoRecords() const {206  return OldFpoRecords;207}208 209bool DbiStream::hasNewFpoRecords() const { return NewFpoStream != nullptr; }210 211const DebugFrameDataSubsectionRef &DbiStream::getNewFpoRecords() const {212  return NewFpoRecords;213}214 215const DbiModuleList &DbiStream::modules() const { return Modules; }216 217FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {218  return SectionMap;219}220 221void DbiStream::visitSectionContributions(222    ISectionContribVisitor &Visitor) const {223  if (!SectionContribs.empty()) {224    assert(SectionContribVersion == DbiSecContribVer60);225    for (auto &SC : SectionContribs)226      Visitor.visit(SC);227  } else if (!SectionContribs2.empty()) {228    assert(SectionContribVersion == DbiSecContribV2);229    for (auto &SC : SectionContribs2)230      Visitor.visit(SC);231  }232}233 234Expected<StringRef> DbiStream::getECName(uint32_t NI) const {235  return ECNames.getStringForID(NI);236}237 238Error DbiStream::initializeSectionContributionData() {239  if (SecContrSubstream.empty())240    return Error::success();241 242  BinaryStreamReader SCReader(SecContrSubstream.StreamData);243  if (auto EC = SCReader.readEnum(SectionContribVersion))244    return EC;245 246  if (SectionContribVersion == DbiSecContribVer60)247    return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);248  if (SectionContribVersion == DbiSecContribV2)249    return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);250 251  return make_error<RawError>(raw_error_code::feature_unsupported,252                              "Unsupported DBI Section Contribution version");253}254 255// Initializes this->SectionHeaders.256Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) {257  Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =258      createIndexedStreamForHeaderType(Pdb, DbgHeaderType::SectionHdr);259  if (auto EC = ExpectedStream.takeError())260    return EC;261 262  auto &SHS = *ExpectedStream;263  if (!SHS)264    return Error::success();265 266  size_t StreamLen = SHS->getLength();267  if (StreamLen % sizeof(object::coff_section))268    return make_error<RawError>(raw_error_code::corrupt_file,269                                "Corrupted section header stream.");270 271  size_t NumSections = StreamLen / sizeof(object::coff_section);272  BinaryStreamReader Reader(*SHS);273  if (auto EC = Reader.readArray(SectionHeaders, NumSections))274    return make_error<RawError>(raw_error_code::corrupt_file,275                                "Could not read a bitmap.");276 277  SectionHeaderStream = std::move(SHS);278  return Error::success();279}280 281// Initializes this->Fpos.282Error DbiStream::initializeOldFpoRecords(PDBFile *Pdb) {283  Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =284      createIndexedStreamForHeaderType(Pdb, DbgHeaderType::FPO);285  if (auto EC = ExpectedStream.takeError())286    return EC;287 288  auto &FS = *ExpectedStream;289  if (!FS)290    return Error::success();291 292  size_t StreamLen = FS->getLength();293  if (StreamLen % sizeof(object::FpoData))294    return make_error<RawError>(raw_error_code::corrupt_file,295                                "Corrupted Old FPO stream.");296 297  size_t NumRecords = StreamLen / sizeof(object::FpoData);298  BinaryStreamReader Reader(*FS);299  if (auto EC = Reader.readArray(OldFpoRecords, NumRecords))300    return make_error<RawError>(raw_error_code::corrupt_file,301                                "Corrupted Old FPO stream.");302  OldFpoStream = std::move(FS);303  return Error::success();304}305 306Error DbiStream::initializeNewFpoRecords(PDBFile *Pdb) {307  Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =308      createIndexedStreamForHeaderType(Pdb, DbgHeaderType::NewFPO);309  if (auto EC = ExpectedStream.takeError())310    return EC;311 312  auto &FS = *ExpectedStream;313  if (!FS)314    return Error::success();315 316  if (auto EC = NewFpoRecords.initialize(*FS))317    return EC;318 319  NewFpoStream = std::move(FS);320  return Error::success();321}322 323Expected<std::unique_ptr<msf::MappedBlockStream>>324DbiStream::createIndexedStreamForHeaderType(PDBFile *Pdb,325                                            DbgHeaderType Type) const {326  if (!Pdb)327    return nullptr;328 329  if (DbgStreams.empty())330    return nullptr;331 332  uint32_t StreamNum = getDebugStreamIndex(Type);333 334  // This means there is no such stream.335  if (StreamNum == kInvalidStreamIndex)336    return nullptr;337 338  return Pdb->safelyCreateIndexedStream(StreamNum);339}340 341BinarySubstreamRef DbiStream::getSectionContributionData() const {342  return SecContrSubstream;343}344 345BinarySubstreamRef DbiStream::getSecMapSubstreamData() const {346  return SecMapSubstream;347}348 349BinarySubstreamRef DbiStream::getModiSubstreamData() const {350  return ModiSubstream;351}352 353BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const {354  return FileInfoSubstream;355}356 357BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const {358  return TypeServerMapSubstream;359}360 361BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; }362 363Error DbiStream::initializeSectionMapData() {364  if (SecMapSubstream.empty())365    return Error::success();366 367  BinaryStreamReader SMReader(SecMapSubstream.StreamData);368  const SecMapHeader *Header;369  if (auto EC = SMReader.readObject(Header))370    return EC;371  if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))372    return EC;373  return Error::success();374}375 376uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {377  uint16_t T = static_cast<uint16_t>(Type);378  if (T >= DbgStreams.size())379    return kInvalidStreamIndex;380  return DbgStreams[T];381}382