LCOV - code coverage report
Current view: top level - lib/DebugInfo/PDB/Raw - TpiStream.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 62 76 81.6 %
Date: 2017-01-24 23:09:07 Functions: 15 16 93.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- TpiStream.cpp - PDB Type Info (TPI) Stream 2 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/iterator_range.h"
      11             : #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
      12             : #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
      13             : #include "llvm/DebugInfo/CodeView/TypeRecord.h"
      14             : #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
      15             : #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
      16             : #include "llvm/DebugInfo/MSF/StreamReader.h"
      17             : #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
      18             : #include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
      19             : #include "llvm/DebugInfo/PDB/Raw/RawError.h"
      20             : #include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
      21             : #include "llvm/DebugInfo/PDB/Raw/TpiHashing.h"
      22             : #include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
      23             : #include "llvm/Support/Endian.h"
      24             : #include "llvm/Support/Error.h"
      25             : #include <algorithm>
      26             : #include <cstdint>
      27             : #include <vector>
      28             : 
      29             : using namespace llvm;
      30             : using namespace llvm::codeview;
      31             : using namespace llvm::support;
      32             : using namespace llvm::msf;
      33             : using namespace llvm::pdb;
      34             : 
      35          17 : TpiStream::TpiStream(const PDBFile &File,
      36          17 :                      std::unique_ptr<MappedBlockStream> Stream)
      37         119 :     : Pdb(File), Stream(std::move(Stream)) {}
      38             : 
      39             : TpiStream::~TpiStream() = default;
      40             : 
      41             : // Verifies that a given type record matches with a given hash value.
      42             : // Currently we only verify SRC_LINE records.
      43          13 : Error TpiStream::verifyHashValues() {
      44          52 :   TpiHashVerifier Verifier(HashValues, Header->NumHashBuckets);
      45          26 :   TypeDeserializer Deserializer;
      46             : 
      47          26 :   TypeVisitorCallbackPipeline Pipeline;
      48          13 :   Pipeline.addCallbackToPipeline(Deserializer);
      49          13 :   Pipeline.addCallbackToPipeline(Verifier);
      50             : 
      51          13 :   CVTypeVisitor Visitor(Pipeline);
      52          26 :   return Visitor.visitTypeStream(TypeRecords);
      53             : }
      54             : 
      55          17 : Error TpiStream::reload() {
      56          51 :   StreamReader Reader(*Stream);
      57             : 
      58          17 :   if (Reader.bytesRemaining() < sizeof(TpiStreamHeader))
      59             :     return make_error<RawError>(raw_error_code::corrupt_file,
      60           0 :                                 "TPI Stream does not contain a header.");
      61             : 
      62          51 :   if (Reader.readObject(Header))
      63             :     return make_error<RawError>(raw_error_code::corrupt_file,
      64           0 :                                 "TPI Stream does not contain a header.");
      65             : 
      66          34 :   if (Header->Version != PdbTpiV80)
      67             :     return make_error<RawError>(raw_error_code::corrupt_file,
      68           0 :                                 "Unsupported TPI Version.");
      69             : 
      70          34 :   if (Header->HeaderSize != sizeof(TpiStreamHeader))
      71             :     return make_error<RawError>(raw_error_code::corrupt_file,
      72           0 :                                 "Corrupt TPI Header size.");
      73             : 
      74          34 :   if (Header->HashKeySize != sizeof(ulittle32_t))
      75             :     return make_error<RawError>(raw_error_code::corrupt_file,
      76           0 :                                 "TPI Stream expected 4 byte hash key size.");
      77             : 
      78          51 :   if (Header->NumHashBuckets < MinTpiHashBuckets ||
      79          34 :       Header->NumHashBuckets > MaxTpiHashBuckets)
      80             :     return make_error<RawError>(raw_error_code::corrupt_file,
      81           0 :                                 "TPI Stream Invalid number of hash buckets.");
      82             : 
      83             :   // The actual type records themselves come from this stream
      84          68 :   if (auto EC = Reader.readArray(TypeRecords, Header->TypeRecordBytes))
      85           0 :     return EC;
      86             : 
      87             :   // Hash indices, hash values, etc come from the hash stream.
      88          34 :   if (Header->HashStreamIndex != kInvalidStreamIndex) {
      89          26 :     if (Header->HashStreamIndex >= Pdb.getNumStreams())
      90             :       return make_error<RawError>(raw_error_code::corrupt_file,
      91           0 :                                   "Invalid TPI hash stream index.");
      92             : 
      93             :     auto HS = MappedBlockStream::createIndexedStream(
      94          65 :         Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex);
      95          26 :     StreamReader HSR(*HS);
      96             : 
      97             :     uint32_t NumHashValues =
      98          26 :         Header->HashValueBuffer.Length / sizeof(ulittle32_t);
      99          13 :     if (NumHashValues != NumTypeRecords())
     100             :       return make_error<RawError>(
     101             :           raw_error_code::corrupt_file,
     102           0 :           "TPI hash count does not match with the number of type records.");
     103          39 :     HSR.setOffset(Header->HashValueBuffer.Off);
     104          39 :     if (auto EC = HSR.readArray(HashValues, NumHashValues))
     105           0 :       return EC;
     106          26 :     std::vector<ulittle32_t> HashValueList;
     107        1509 :     for (auto I : HashValues)
     108         735 :       HashValueList.push_back(I);
     109             : 
     110          39 :     HSR.setOffset(Header->IndexOffsetBuffer.Off);
     111             :     uint32_t NumTypeIndexOffsets =
     112          26 :         Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset);
     113          39 :     if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets))
     114           0 :       return EC;
     115             : 
     116          39 :     HSR.setOffset(Header->HashAdjBuffer.Off);
     117             :     uint32_t NumHashAdjustments =
     118          26 :         Header->HashAdjBuffer.Length / sizeof(TypeIndexOffset);
     119          39 :     if (auto EC = HSR.readArray(HashAdjustments, NumHashAdjustments))
     120           0 :       return EC;
     121             : 
     122          26 :     HashStream = std::move(HS);
     123             : 
     124             :     // TPI hash table is a parallel array for the type records.
     125             :     // Verify that the hash values match with type records.
     126          39 :     if (auto EC = verifyHashValues())
     127           0 :       return EC;
     128             :   }
     129             : 
     130          51 :   return Error::success();
     131             : }
     132             : 
     133          13 : PdbRaw_TpiVer TpiStream::getTpiVersion() const {
     134          26 :   uint32_t Value = Header->Version;
     135          13 :   return static_cast<PdbRaw_TpiVer>(Value);
     136             : }
     137             : 
     138          38 : uint32_t TpiStream::TypeIndexBegin() const { return Header->TypeIndexBegin; }
     139             : 
     140          38 : uint32_t TpiStream::TypeIndexEnd() const { return Header->TypeIndexEnd; }
     141             : 
     142          19 : uint32_t TpiStream::NumTypeRecords() const {
     143          19 :   return TypeIndexEnd() - TypeIndexBegin();
     144             : }
     145             : 
     146          68 : uint16_t TpiStream::getTypeHashStreamIndex() const {
     147         136 :   return Header->HashStreamIndex;
     148             : }
     149             : 
     150          60 : uint16_t TpiStream::getTypeHashStreamAuxIndex() const {
     151         120 :   return Header->HashAuxStreamIndex;
     152             : }
     153             : 
     154           8 : uint32_t TpiStream::NumHashBuckets() const { return Header->NumHashBuckets; }
     155           8 : uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; }
     156             : 
     157             : FixedStreamArray<support::ulittle32_t>
     158           4 : TpiStream::getHashValues() const {
     159           4 :   return HashValues;
     160             : }
     161             : 
     162             : FixedStreamArray<TypeIndexOffset>
     163          10 : TpiStream::getTypeIndexOffsets() const {
     164          10 :   return TypeIndexOffsets;
     165             : }
     166             : 
     167             : FixedStreamArray<TypeIndexOffset>
     168           4 : TpiStream::getHashAdjustments() const {
     169           4 :   return HashAdjustments;
     170             : }
     171             : 
     172             : iterator_range<CVTypeArray::Iterator>
     173          13 : TpiStream::types(bool *HadError) const {
     174          65 :   return make_range(TypeRecords.begin(HadError), TypeRecords.end());
     175             : }
     176             : 
     177           0 : Error TpiStream::commit() { return Error::success(); }

Generated by: LCOV version 1.13