LCOV - code coverage report
Current view: top level - lib/DebugInfo/PDB/Raw - DbiStream.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 171 230 74.3 %
Date: 2017-01-24 23:09:07 Functions: 31 32 96.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/ADT/StringRef.h"
      11             : #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
      12             : #include "llvm/DebugInfo/MSF/StreamArray.h"
      13             : #include "llvm/DebugInfo/MSF/StreamReader.h"
      14             : #include "llvm/DebugInfo/PDB/PDBTypes.h"
      15             : #include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
      16             : #include "llvm/DebugInfo/PDB/Raw/ISectionContribVisitor.h"
      17             : #include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
      18             : #include "llvm/DebugInfo/PDB/Raw/ModInfo.h"
      19             : #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
      20             : #include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
      21             : #include "llvm/DebugInfo/PDB/Raw/RawError.h"
      22             : #include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
      23             : #include "llvm/Object/COFF.h"
      24             : #include "llvm/Support/Error.h"
      25             : #include <algorithm>
      26             : #include <cstddef>
      27             : #include <cstdint>
      28             : 
      29             : using namespace llvm;
      30             : using namespace llvm::codeview;
      31             : using namespace llvm::msf;
      32             : using namespace llvm::pdb;
      33             : using namespace llvm::support;
      34             : 
      35             : template <typename ContribType>
      36           9 : static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
      37             :                                  StreamReader &Reader) {
      38           9 :   if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
      39             :     return make_error<RawError>(
      40             :         raw_error_code::corrupt_file,
      41           0 :         "Invalid number of bytes of section contributions");
      42             : 
      43           9 :   uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
      44          27 :   if (auto EC = Reader.readArray(Output, Count))
      45           0 :     return EC;
      46          27 :   return Error::success();
      47             : }
      48             : 
      49          10 : DbiStream::DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
      50         190 :     : Pdb(File), Stream(std::move(Stream)), Header(nullptr) {
      51          10 : }
      52             : 
      53             : DbiStream::~DbiStream() = default;
      54             : 
      55          10 : Error DbiStream::reload() {
      56          30 :   StreamReader Reader(*Stream);
      57             : 
      58          20 :   if (Stream->getLength() < sizeof(DbiStreamHeader))
      59             :     return make_error<RawError>(raw_error_code::corrupt_file,
      60           0 :                                 "DBI Stream does not contain a header.");
      61          30 :   if (auto EC = Reader.readObject(Header))
      62             :     return make_error<RawError>(raw_error_code::corrupt_file,
      63           0 :                                 "DBI Stream does not contain a header.");
      64             : 
      65          20 :   if (Header->VersionSignature != -1)
      66             :     return make_error<RawError>(raw_error_code::corrupt_file,
      67           0 :                                 "Invalid DBI version signature.");
      68             : 
      69             :   // Require at least version 7, which should be present in all PDBs
      70             :   // produced in the last decade and allows us to avoid having to
      71             :   // special case all kinds of complicated arcane formats.
      72          20 :   if (Header->VersionHeader < PdbDbiV70)
      73             :     return make_error<RawError>(raw_error_code::feature_unsupported,
      74           0 :                                 "Unsupported DBI version.");
      75             : 
      76          10 :   auto IS = Pdb.getPDBInfoStream();
      77          10 :   if (!IS)
      78           0 :     return IS.takeError();
      79             : 
      80          30 :   if (Header->Age != IS->getAge())
      81             :     return make_error<RawError>(raw_error_code::corrupt_file,
      82           0 :                                 "DBI Age does not match PDB Age.");
      83             : 
      84          30 :   if (Stream->getLength() !=
      85          30 :       sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
      86          50 :           Header->SecContrSubstreamSize + Header->SectionMapSize +
      87          50 :           Header->FileInfoSize + Header->TypeServerSize +
      88          40 :           Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
      89             :     return make_error<RawError>(raw_error_code::corrupt_file,
      90           0 :                                 "DBI Length does not equal sum of substreams.");
      91             : 
      92             :   // Only certain substreams are guaranteed to be aligned.  Validate
      93             :   // them here.
      94          20 :   if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
      95             :     return make_error<RawError>(raw_error_code::corrupt_file,
      96           0 :                                 "DBI MODI substream not aligned.");
      97          20 :   if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
      98             :     return make_error<RawError>(
      99             :         raw_error_code::corrupt_file,
     100           0 :         "DBI section contribution substream not aligned.");
     101          20 :   if (Header->SectionMapSize % sizeof(uint32_t) != 0)
     102             :     return make_error<RawError>(raw_error_code::corrupt_file,
     103           0 :                                 "DBI section map substream not aligned.");
     104          20 :   if (Header->FileInfoSize % sizeof(uint32_t) != 0)
     105             :     return make_error<RawError>(raw_error_code::corrupt_file,
     106           0 :                                 "DBI file info substream not aligned.");
     107          20 :   if (Header->TypeServerSize % sizeof(uint32_t) != 0)
     108             :     return make_error<RawError>(raw_error_code::corrupt_file,
     109           0 :                                 "DBI type server substream not aligned.");
     110             : 
     111          10 :   if (auto EC =
     112          30 :           Reader.readStreamRef(ModInfoSubstream, Header->ModiSubstreamSize))
     113           0 :     return EC;
     114          30 :   if (auto EC = initializeModInfoArray())
     115           0 :     return EC;
     116             : 
     117          10 :   if (auto EC = Reader.readStreamRef(SecContrSubstream,
     118          30 :                                      Header->SecContrSubstreamSize))
     119           0 :     return EC;
     120          40 :   if (auto EC = Reader.readStreamRef(SecMapSubstream, Header->SectionMapSize))
     121           0 :     return EC;
     122          40 :   if (auto EC = Reader.readStreamRef(FileInfoSubstream, Header->FileInfoSize))
     123           0 :     return EC;
     124          10 :   if (auto EC =
     125          30 :           Reader.readStreamRef(TypeServerMapSubstream, Header->TypeServerSize))
     126           0 :     return EC;
     127          40 :   if (auto EC = Reader.readStreamRef(ECSubstream, Header->ECSubstreamSize))
     128           0 :     return EC;
     129          30 :   if (auto EC = Reader.readArray(DbgStreams, Header->OptionalDbgHdrSize /
     130          40 :                                                  sizeof(ulittle16_t)))
     131           0 :     return EC;
     132             : 
     133          30 :   if (auto EC = initializeSectionContributionData())
     134           0 :     return EC;
     135          30 :   if (auto EC = initializeSectionHeadersData())
     136           0 :     return EC;
     137          30 :   if (auto EC = initializeSectionMapData())
     138           0 :     return EC;
     139          30 :   if (auto EC = initializeFileInfo())
     140           0 :     return EC;
     141          30 :   if (auto EC = initializeFpoRecords())
     142           0 :     return EC;
     143             : 
     144          10 :   if (Reader.bytesRemaining() > 0)
     145             :     return make_error<RawError>(raw_error_code::corrupt_file,
     146           0 :                                 "Found unexpected bytes in DBI Stream.");
     147             : 
     148          10 :   if (ECSubstream.getLength() > 0) {
     149           8 :     StreamReader ECReader(ECSubstream);
     150          24 :     if (auto EC = ECNames.load(ECReader))
     151           0 :       return EC;
     152             :   }
     153             : 
     154          30 :   return Error::success();
     155             : }
     156             : 
     157           8 : PdbRaw_DbiVer DbiStream::getDbiVersion() const {
     158          16 :   uint32_t Value = Header->VersionHeader;
     159           8 :   return static_cast<PdbRaw_DbiVer>(Value);
     160             : }
     161             : 
     162          16 : uint32_t DbiStream::getAge() const { return Header->Age; }
     163             : 
     164          55 : uint16_t DbiStream::getPublicSymbolStreamIndex() const {
     165         110 :   return Header->PublicSymbolStreamIndex;
     166             : }
     167             : 
     168          59 : uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
     169         118 :   return Header->GlobalSymbolStreamIndex;
     170             : }
     171             : 
     172           6 : uint16_t DbiStream::getFlags() const { return Header->Flags; }
     173             : 
     174           5 : bool DbiStream::isIncrementallyLinked() const {
     175          10 :   return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
     176             : }
     177             : 
     178           5 : bool DbiStream::hasCTypes() const {
     179          10 :   return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
     180             : }
     181             : 
     182           5 : bool DbiStream::isStripped() const {
     183          10 :   return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
     184             : }
     185             : 
     186           6 : uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
     187             : 
     188           5 : uint16_t DbiStream::getBuildMajorVersion() const {
     189          10 :   return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
     190           5 :          DbiBuildNo::BuildMajorShift;
     191             : }
     192             : 
     193           5 : uint16_t DbiStream::getBuildMinorVersion() const {
     194          10 :   return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
     195           5 :          DbiBuildNo::BuildMinorShift;
     196             : }
     197             : 
     198           6 : uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
     199             : 
     200          16 : uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
     201             : 
     202          47 : uint32_t DbiStream::getSymRecordStreamIndex() const {
     203          94 :   return Header->SymRecordStreamIndex;
     204             : }
     205             : 
     206           8 : PDB_Machine DbiStream::getMachineType() const {
     207          16 :   uint16_t Machine = Header->MachineType;
     208           8 :   return static_cast<PDB_Machine>(Machine);
     209             : }
     210             : 
     211           2 : msf::FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() {
     212           2 :   return SectionHeaders;
     213             : }
     214             : 
     215           2 : msf::FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
     216           2 :   return FpoRecords;
     217             : }
     218             : 
     219          42 : ArrayRef<ModuleInfoEx> DbiStream::modules() const { return ModuleInfos; }
     220           2 : msf::FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
     221           2 :   return SectionMap;
     222             : }
     223             : 
     224           2 : void DbiStream::visitSectionContributions(
     225             :     ISectionContribVisitor &Visitor) const {
     226           2 :   if (SectionContribVersion == DbiSecContribVer60) {
     227          30 :     for (auto &SC : SectionContribs)
     228          12 :       Visitor.visit(SC);
     229           0 :   } else if (SectionContribVersion == DbiSecContribV2) {
     230           0 :     for (auto &SC : SectionContribs2)
     231           0 :       Visitor.visit(SC);
     232             :   }
     233           2 : }
     234             : 
     235          10 : Error DbiStream::initializeSectionContributionData() {
     236          10 :   if (SecContrSubstream.getLength() == 0)
     237           3 :     return Error::success();
     238             : 
     239           9 :   StreamReader SCReader(SecContrSubstream);
     240          27 :   if (auto EC = SCReader.readEnum(SectionContribVersion))
     241           0 :     return EC;
     242             : 
     243           9 :   if (SectionContribVersion == DbiSecContribVer60)
     244           9 :     return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
     245           0 :   if (SectionContribVersion == DbiSecContribV2)
     246           0 :     return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
     247             : 
     248             :   return make_error<RawError>(raw_error_code::feature_unsupported,
     249           0 :                               "Unsupported DBI Section Contribution version");
     250             : }
     251             : 
     252          10 : Error DbiStream::initializeModInfoArray() {
     253          10 :   if (ModInfoSubstream.getLength() == 0)
     254           0 :     return Error::success();
     255             : 
     256             :   // Since each ModInfo in the stream is a variable length, we have to iterate
     257             :   // them to know how many there actually are.
     258          10 :   StreamReader Reader(ModInfoSubstream);
     259             : 
     260          10 :   VarStreamArray<ModInfo> ModInfoArray;
     261          30 :   if (auto EC = Reader.readArray(ModInfoArray, ModInfoSubstream.getLength()))
     262           0 :     return EC;
     263         180 :   for (auto &Info : ModInfoArray) {
     264          65 :     ModuleInfos.emplace_back(Info);
     265             :   }
     266             : 
     267          30 :   return Error::success();
     268             : }
     269             : 
     270             : // Initializes this->SectionHeaders.
     271          10 : Error DbiStream::initializeSectionHeadersData() {
     272          20 :   if (DbgStreams.size() == 0)
     273           0 :     return Error::success();
     274             : 
     275          10 :   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::SectionHdr);
     276          10 :   if (StreamNum >= Pdb.getNumStreams())
     277           0 :     return make_error<RawError>(raw_error_code::no_stream);
     278             : 
     279             :   auto SHS = MappedBlockStream::createIndexedStream(
     280          30 :       Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum);
     281             : 
     282          10 :   size_t StreamLen = SHS->getLength();
     283          10 :   if (StreamLen % sizeof(object::coff_section))
     284             :     return make_error<RawError>(raw_error_code::corrupt_file,
     285           0 :                                 "Corrupted section header stream.");
     286             : 
     287          10 :   size_t NumSections = StreamLen / sizeof(object::coff_section);
     288          20 :   msf::StreamReader Reader(*SHS);
     289          30 :   if (auto EC = Reader.readArray(SectionHeaders, NumSections))
     290             :     return make_error<RawError>(raw_error_code::corrupt_file,
     291           0 :                                 "Could not read a bitmap.");
     292             : 
     293          20 :   SectionHeaderStream = std::move(SHS);
     294          30 :   return Error::success();
     295             : }
     296             : 
     297             : // Initializes this->Fpos.
     298          10 : Error DbiStream::initializeFpoRecords() {
     299          20 :   if (DbgStreams.size() == 0)
     300           0 :     return Error::success();
     301             : 
     302          10 :   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO);
     303             : 
     304             :   // This means there is no FPO data.
     305          10 :   if (StreamNum == kInvalidStreamIndex)
     306           0 :     return Error::success();
     307             : 
     308          10 :   if (StreamNum >= Pdb.getNumStreams())
     309           0 :     return make_error<RawError>(raw_error_code::no_stream);
     310             : 
     311             :   auto FS = MappedBlockStream::createIndexedStream(
     312          30 :       Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum);
     313             : 
     314          10 :   size_t StreamLen = FS->getLength();
     315          10 :   if (StreamLen % sizeof(object::FpoData))
     316             :     return make_error<RawError>(raw_error_code::corrupt_file,
     317           0 :                                 "Corrupted New FPO stream.");
     318             : 
     319          10 :   size_t NumRecords = StreamLen / sizeof(object::FpoData);
     320          20 :   msf::StreamReader Reader(*FS);
     321          30 :   if (auto EC = Reader.readArray(FpoRecords, NumRecords))
     322             :     return make_error<RawError>(raw_error_code::corrupt_file,
     323           0 :                                 "Corrupted New FPO stream.");
     324          20 :   FpoStream = std::move(FS);
     325          30 :   return Error::success();
     326             : }
     327             : 
     328          10 : Error DbiStream::initializeSectionMapData() {
     329          10 :   if (SecMapSubstream.getLength() == 0)
     330           3 :     return Error::success();
     331             : 
     332           9 :   StreamReader SMReader(SecMapSubstream);
     333             :   const SecMapHeader *Header;
     334          27 :   if (auto EC = SMReader.readObject(Header))
     335           0 :     return EC;
     336          36 :   if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
     337           0 :     return EC;
     338          27 :   return Error::success();
     339             : }
     340             : 
     341          10 : Error DbiStream::initializeFileInfo() {
     342          10 :   if (FileInfoSubstream.getLength() == 0)
     343           0 :     return Error::success();
     344             : 
     345             :   const FileInfoSubstreamHeader *FH;
     346          10 :   StreamReader FISR(FileInfoSubstream);
     347          30 :   if (auto EC = FISR.readObject(FH))
     348           0 :     return EC;
     349             : 
     350             :   // The number of modules in the stream should be the same as reported by
     351             :   // the FileInfoSubstreamHeader.
     352          30 :   if (FH->NumModules != ModuleInfos.size())
     353             :     return make_error<RawError>(raw_error_code::corrupt_file,
     354           0 :                                 "FileInfo substream count doesn't match DBI.");
     355             : 
     356          10 :   FixedStreamArray<ulittle16_t> ModIndexArray;
     357          10 :   FixedStreamArray<ulittle16_t> ModFileCountArray;
     358             : 
     359             :   // First is an array of `NumModules` module indices.  This is not used for the
     360             :   // same reason that `NumSourceFiles` is not used.  It's an array of uint16's,
     361             :   // but it's possible there are more than 64k source files, which would imply
     362             :   // more than 64k modules (e.g. object files) as well.  So we ignore this
     363             :   // field.
     364          30 :   if (auto EC = FISR.readArray(ModIndexArray, ModuleInfos.size()))
     365           0 :     return EC;
     366          40 :   if (auto EC = FISR.readArray(ModFileCountArray, ModuleInfos.size()))
     367           0 :     return EC;
     368             : 
     369             :   // Compute the real number of source files.
     370          10 :   uint32_t NumSourceFiles = 0;
     371         160 :   for (auto Count : ModFileCountArray)
     372          65 :     NumSourceFiles += Count;
     373             : 
     374             :   // This is the array that in the reference implementation corresponds to
     375             :   // `ModInfo::FileLayout::FileNameOffs`, which is commented there as being a
     376             :   // pointer. Due to the mentioned problems of pointers causing difficulty
     377             :   // when reading from the file on 64-bit systems, we continue to ignore that
     378             :   // field in `ModInfo`, and instead build a vector of StringRefs and stores
     379             :   // them in `ModuleInfoEx`.  The value written to and read from the file is
     380             :   // not used anyway, it is only there as a way to store the offsets for the
     381             :   // purposes of later accessing the names at runtime.
     382          30 :   if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
     383           0 :     return EC;
     384             : 
     385          30 :   if (auto EC = FISR.readStreamRef(NamesBuffer))
     386           0 :     return EC;
     387             : 
     388             :   // We go through each ModuleInfo, determine the number N of source files for
     389             :   // that module, and then get the next N offsets from the Offsets array, using
     390             :   // them to get the corresponding N names from the Names buffer and associating
     391             :   // each one with the corresponding module.
     392          10 :   uint32_t NextFileIndex = 0;
     393         150 :   for (size_t I = 0; I < ModuleInfos.size(); ++I) {
     394         130 :     uint32_t NumFiles = ModFileCountArray[I];
     395         130 :     ModuleInfos[I].SourceFiles.resize(NumFiles);
     396         387 :     for (size_t J = 0; J < NumFiles; ++J, ++NextFileIndex) {
     397         644 :       auto ThisName = getFileNameForIndex(NextFileIndex);
     398         322 :       if (!ThisName)
     399           0 :         return ThisName.takeError();
     400        1288 :       ModuleInfos[I].SourceFiles[J] = *ThisName;
     401             :     }
     402             :   }
     403             : 
     404          30 :   return Error::success();
     405             : }
     406             : 
     407         288 : uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
     408         288 :   uint16_t T = static_cast<uint16_t>(Type);
     409         576 :   if (T >= DbgStreams.size())
     410             :     return kInvalidStreamIndex;
     411         576 :   return DbgStreams[T];
     412             : }
     413             : 
     414         324 : Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const {
     415         324 :   StreamReader Names(NamesBuffer);
     416         648 :   if (Index >= FileNameOffsets.size())
     417           0 :     return make_error<RawError>(raw_error_code::index_out_of_bounds);
     418             : 
     419         648 :   uint32_t FileOffset = FileNameOffsets[Index];
     420         648 :   Names.setOffset(FileOffset);
     421         324 :   StringRef Name;
     422         972 :   if (auto EC = Names.readZeroString(Name))
     423           0 :     return std::move(EC);
     424             :   return Name;
     425             : }

Generated by: LCOV version 1.13