LCOV - code coverage report
Current view: top level - lib/DebugInfo/PDB/Native - DbiStream.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 140 187 74.9 %
Date: 2017-09-14 15:23:50 Functions: 33 36 91.7 %
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/DebugInfo/PDB/Native/DbiStream.h"
      11             : #include "llvm/ADT/StringRef.h"
      12             : #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
      13             : #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
      14             : #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
      15             : #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
      16             : #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
      17             : #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
      18             : #include "llvm/DebugInfo/PDB/Native/RawError.h"
      19             : #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
      20             : #include "llvm/DebugInfo/PDB/PDBTypes.h"
      21             : #include "llvm/Object/COFF.h"
      22             : #include "llvm/Support/BinaryStreamArray.h"
      23             : #include "llvm/Support/BinaryStreamReader.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          58 : static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
      37             :                                  BinaryStreamReader &Reader) {
      38          58 :   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          58 :   uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
      44         174 :   if (auto EC = Reader.readArray(Output, Count))
      45           0 :     return EC;
      46         174 :   return Error::success();
      47             : }
      48             : 
      49          65 : DbiStream::DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
      50        1105 :     : Pdb(File), Stream(std::move(Stream)), Header(nullptr) {}
      51             : 
      52             : DbiStream::~DbiStream() = default;
      53             : 
      54          65 : Error DbiStream::reload() {
      55         195 :   BinaryStreamReader Reader(*Stream);
      56             : 
      57         130 :   if (Stream->getLength() < sizeof(DbiStreamHeader))
      58             :     return make_error<RawError>(raw_error_code::corrupt_file,
      59           0 :                                 "DBI Stream does not contain a header.");
      60         195 :   if (auto EC = Reader.readObject(Header))
      61             :     return make_error<RawError>(raw_error_code::corrupt_file,
      62           0 :                                 "DBI Stream does not contain a header.");
      63             : 
      64         130 :   if (Header->VersionSignature != -1)
      65             :     return make_error<RawError>(raw_error_code::corrupt_file,
      66           0 :                                 "Invalid DBI version signature.");
      67             : 
      68             :   // Require at least version 7, which should be present in all PDBs
      69             :   // produced in the last decade and allows us to avoid having to
      70             :   // special case all kinds of complicated arcane formats.
      71         130 :   if (Header->VersionHeader < PdbDbiV70)
      72             :     return make_error<RawError>(raw_error_code::feature_unsupported,
      73           0 :                                 "Unsupported DBI version.");
      74             : 
      75         195 :   if (Stream->getLength() !=
      76         195 :       sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
      77         325 :           Header->SecContrSubstreamSize + Header->SectionMapSize +
      78         325 :           Header->FileInfoSize + Header->TypeServerSize +
      79         260 :           Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
      80             :     return make_error<RawError>(raw_error_code::corrupt_file,
      81           0 :                                 "DBI Length does not equal sum of substreams.");
      82             : 
      83             :   // Only certain substreams are guaranteed to be aligned.  Validate
      84             :   // them here.
      85         130 :   if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
      86             :     return make_error<RawError>(raw_error_code::corrupt_file,
      87           0 :                                 "DBI MODI substream not aligned.");
      88         130 :   if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
      89             :     return make_error<RawError>(
      90             :         raw_error_code::corrupt_file,
      91           0 :         "DBI section contribution substream not aligned.");
      92         130 :   if (Header->SectionMapSize % sizeof(uint32_t) != 0)
      93             :     return make_error<RawError>(raw_error_code::corrupt_file,
      94           0 :                                 "DBI section map substream not aligned.");
      95         130 :   if (Header->FileInfoSize % sizeof(uint32_t) != 0)
      96             :     return make_error<RawError>(raw_error_code::corrupt_file,
      97           0 :                                 "DBI file info substream not aligned.");
      98         130 :   if (Header->TypeServerSize % sizeof(uint32_t) != 0)
      99             :     return make_error<RawError>(raw_error_code::corrupt_file,
     100           0 :                                 "DBI type server substream not aligned.");
     101             : 
     102         260 :   if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize))
     103           0 :     return EC;
     104             : 
     105          65 :   if (auto EC = Reader.readSubstream(SecContrSubstream,
     106         260 :                                      Header->SecContrSubstreamSize))
     107           0 :     return EC;
     108         260 :   if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize))
     109           0 :     return EC;
     110         260 :   if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize))
     111           0 :     return EC;
     112          65 :   if (auto EC =
     113         260 :           Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize))
     114           0 :     return EC;
     115         260 :   if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize))
     116           0 :     return EC;
     117          65 :   if (auto EC = Reader.readArray(
     118         260 :           DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))
     119           0 :     return EC;
     120             : 
     121          65 :   if (auto EC = Modules.initialize(ModiSubstream.StreamData,
     122         455 :                                    FileInfoSubstream.StreamData))
     123           0 :     return EC;
     124             : 
     125         195 :   if (auto EC = initializeSectionContributionData())
     126           0 :     return EC;
     127         195 :   if (auto EC = initializeSectionHeadersData())
     128           0 :     return EC;
     129         195 :   if (auto EC = initializeSectionMapData())
     130           0 :     return EC;
     131         195 :   if (auto EC = initializeFpoRecords())
     132           0 :     return EC;
     133             : 
     134          65 :   if (Reader.bytesRemaining() > 0)
     135             :     return make_error<RawError>(raw_error_code::corrupt_file,
     136           0 :                                 "Found unexpected bytes in DBI Stream.");
     137             : 
     138         130 :   if (!ECSubstream.empty()) {
     139         260 :     BinaryStreamReader ECReader(ECSubstream.StreamData);
     140         195 :     if (auto EC = ECNames.reload(ECReader))
     141           0 :       return EC;
     142             :   }
     143             : 
     144         195 :   return Error::success();
     145             : }
     146             : 
     147          14 : PdbRaw_DbiVer DbiStream::getDbiVersion() const {
     148          28 :   uint32_t Value = Header->VersionHeader;
     149          14 :   return static_cast<PdbRaw_DbiVer>(Value);
     150             : }
     151             : 
     152          28 : uint32_t DbiStream::getAge() const { return Header->Age; }
     153             : 
     154         131 : uint16_t DbiStream::getPublicSymbolStreamIndex() const {
     155         262 :   return Header->PublicSymbolStreamIndex;
     156             : }
     157             : 
     158         157 : uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
     159         314 :   return Header->GlobalSymbolStreamIndex;
     160             : }
     161             : 
     162          28 : uint16_t DbiStream::getFlags() const { return Header->Flags; }
     163             : 
     164           6 : bool DbiStream::isIncrementallyLinked() const {
     165          12 :   return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
     166             : }
     167             : 
     168          10 : bool DbiStream::hasCTypes() const {
     169          20 :   return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
     170             : }
     171             : 
     172          10 : bool DbiStream::isStripped() const {
     173          20 :   return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
     174             : }
     175             : 
     176          28 : uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
     177             : 
     178           2 : uint16_t DbiStream::getBuildMajorVersion() const {
     179           4 :   return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
     180           2 :          DbiBuildNo::BuildMajorShift;
     181             : }
     182             : 
     183           2 : uint16_t DbiStream::getBuildMinorVersion() const {
     184           4 :   return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
     185           2 :          DbiBuildNo::BuildMinorShift;
     186             : }
     187             : 
     188          28 : uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
     189             : 
     190          28 : uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
     191             : 
     192         122 : uint32_t DbiStream::getSymRecordStreamIndex() const {
     193         244 :   return Header->SymRecordStreamIndex;
     194             : }
     195             : 
     196          14 : PDB_Machine DbiStream::getMachineType() const {
     197          28 :   uint16_t Machine = Header->MachineType;
     198          14 :   return static_cast<PDB_Machine>(Machine);
     199             : }
     200             : 
     201           0 : FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() {
     202           0 :   return SectionHeaders;
     203             : }
     204             : 
     205           0 : FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
     206           0 :   return FpoRecords;
     207             : }
     208             : 
     209         907 : const DbiModuleList &DbiStream::modules() const { return Modules; }
     210             : 
     211           2 : FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
     212           4 :   return SectionMap;
     213             : }
     214             : 
     215           3 : void DbiStream::visitSectionContributions(
     216             :     ISectionContribVisitor &Visitor) const {
     217           6 :   if (!SectionContribs.empty()) {
     218             :     assert(SectionContribVersion == DbiSecContribVer60);
     219          43 :     for (auto &SC : SectionContribs)
     220          28 :       Visitor.visit(SC);
     221           0 :   } else if (!SectionContribs2.empty()) {
     222             :     assert(SectionContribVersion == DbiSecContribV2);
     223           0 :     for (auto &SC : SectionContribs2)
     224           0 :       Visitor.visit(SC);
     225             :   }
     226           3 : }
     227             : 
     228         220 : Expected<StringRef> DbiStream::getECName(uint32_t NI) const {
     229         220 :   return ECNames.getStringForID(NI);
     230             : }
     231             : 
     232          65 : Error DbiStream::initializeSectionContributionData() {
     233         130 :   if (SecContrSubstream.empty())
     234          21 :     return Error::success();
     235             : 
     236         174 :   BinaryStreamReader SCReader(SecContrSubstream.StreamData);
     237         174 :   if (auto EC = SCReader.readEnum(SectionContribVersion))
     238           0 :     return EC;
     239             : 
     240          58 :   if (SectionContribVersion == DbiSecContribVer60)
     241          58 :     return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
     242           0 :   if (SectionContribVersion == DbiSecContribV2)
     243           0 :     return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
     244             : 
     245             :   return make_error<RawError>(raw_error_code::feature_unsupported,
     246           0 :                               "Unsupported DBI Section Contribution version");
     247             : }
     248             : 
     249             : // Initializes this->SectionHeaders.
     250          65 : Error DbiStream::initializeSectionHeadersData() {
     251         130 :   if (DbgStreams.size() == 0)
     252           0 :     return Error::success();
     253             : 
     254          65 :   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::SectionHdr);
     255          65 :   if (StreamNum == kInvalidStreamIndex)
     256          21 :     return Error::success();
     257             : 
     258          58 :   if (StreamNum >= Pdb.getNumStreams())
     259           0 :     return make_error<RawError>(raw_error_code::no_stream);
     260             : 
     261             :   auto SHS = MappedBlockStream::createIndexedStream(
     262         232 :       Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator());
     263             : 
     264          58 :   size_t StreamLen = SHS->getLength();
     265          58 :   if (StreamLen % sizeof(object::coff_section))
     266             :     return make_error<RawError>(raw_error_code::corrupt_file,
     267           0 :                                 "Corrupted section header stream.");
     268             : 
     269          58 :   size_t NumSections = StreamLen / sizeof(object::coff_section);
     270          58 :   BinaryStreamReader Reader(*SHS);
     271         174 :   if (auto EC = Reader.readArray(SectionHeaders, NumSections))
     272             :     return make_error<RawError>(raw_error_code::corrupt_file,
     273           0 :                                 "Could not read a bitmap.");
     274             : 
     275         116 :   SectionHeaderStream = std::move(SHS);
     276         174 :   return Error::success();
     277             : }
     278             : 
     279             : // Initializes this->Fpos.
     280          65 : Error DbiStream::initializeFpoRecords() {
     281          65 :   if (DbgStreams.size() == 0)
     282           0 :     return Error::success();
     283             : 
     284          65 :   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO);
     285             : 
     286             :   // This means there is no FPO data.
     287          65 :   if (StreamNum == kInvalidStreamIndex)
     288          21 :     return Error::success();
     289             : 
     290          58 :   if (StreamNum >= Pdb.getNumStreams())
     291           0 :     return make_error<RawError>(raw_error_code::no_stream);
     292             : 
     293             :   auto FS = MappedBlockStream::createIndexedStream(
     294         232 :       Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum, Pdb.getAllocator());
     295             : 
     296          58 :   size_t StreamLen = FS->getLength();
     297          58 :   if (StreamLen % sizeof(object::FpoData))
     298             :     return make_error<RawError>(raw_error_code::corrupt_file,
     299           0 :                                 "Corrupted New FPO stream.");
     300             : 
     301          58 :   size_t NumRecords = StreamLen / sizeof(object::FpoData);
     302          58 :   BinaryStreamReader Reader(*FS);
     303         174 :   if (auto EC = Reader.readArray(FpoRecords, NumRecords))
     304             :     return make_error<RawError>(raw_error_code::corrupt_file,
     305           0 :                                 "Corrupted New FPO stream.");
     306         116 :   FpoStream = std::move(FS);
     307         174 :   return Error::success();
     308             : }
     309             : 
     310           1 : BinarySubstreamRef DbiStream::getSectionContributionData() const {
     311           2 :   return SecContrSubstream;
     312             : }
     313             : 
     314           1 : BinarySubstreamRef DbiStream::getSecMapSubstreamData() const {
     315           2 :   return SecMapSubstream;
     316             : }
     317             : 
     318           1 : BinarySubstreamRef DbiStream::getModiSubstreamData() const {
     319           2 :   return ModiSubstream;
     320             : }
     321             : 
     322           1 : BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const {
     323           2 :   return FileInfoSubstream;
     324             : }
     325             : 
     326           1 : BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const {
     327           2 :   return TypeServerMapSubstream;
     328             : }
     329             : 
     330           2 : BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; }
     331             : 
     332          65 : Error DbiStream::initializeSectionMapData() {
     333         130 :   if (SecMapSubstream.empty())
     334          21 :     return Error::success();
     335             : 
     336         174 :   BinaryStreamReader SMReader(SecMapSubstream.StreamData);
     337             :   const SecMapHeader *Header;
     338         174 :   if (auto EC = SMReader.readObject(Header))
     339           0 :     return EC;
     340         232 :   if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
     341           0 :     return EC;
     342         174 :   return Error::success();
     343             : }
     344             : 
     345         876 : uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
     346         876 :   uint16_t T = static_cast<uint16_t>(Type);
     347        1752 :   if (T >= DbgStreams.size())
     348             :     return kInvalidStreamIndex;
     349        1752 :   return DbgStreams[T];
     350             : }

Generated by: LCOV version 1.13