LCOV - code coverage report
Current view: top level - lib/DebugInfo/PDB/Native - TpiStream.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 51 54 94.4 %
Date: 2018-06-17 00:07:59 Functions: 14 16 87.5 %
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/DebugInfo/PDB/Native/TpiStream.h"
      11             : 
      12             : #include "llvm/ADT/iterator_range.h"
      13             : #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
      14             : #include "llvm/DebugInfo/CodeView/TypeRecord.h"
      15             : #include "llvm/DebugInfo/MSF/MappedBlockStream.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/Native/TpiHashing.h"
      21             : #include "llvm/Support/BinaryStreamReader.h"
      22             : #include "llvm/Support/Endian.h"
      23             : #include "llvm/Support/Error.h"
      24             : #include <algorithm>
      25             : #include <cstdint>
      26             : #include <vector>
      27             : 
      28             : using namespace llvm;
      29             : using namespace llvm::codeview;
      30             : using namespace llvm::support;
      31             : using namespace llvm::msf;
      32             : using namespace llvm::pdb;
      33             : 
      34          94 : TpiStream::TpiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
      35         188 :     : Pdb(File), Stream(std::move(Stream)) {}
      36             : 
      37             : TpiStream::~TpiStream() = default;
      38             : 
      39          94 : Error TpiStream::reload() {
      40          94 :   BinaryStreamReader Reader(*Stream);
      41             : 
      42          94 :   if (Reader.bytesRemaining() < sizeof(TpiStreamHeader))
      43             :     return make_error<RawError>(raw_error_code::corrupt_file,
      44             :                                 "TPI Stream does not contain a header.");
      45             : 
      46         188 :   if (Reader.readObject(Header))
      47             :     return make_error<RawError>(raw_error_code::corrupt_file,
      48             :                                 "TPI Stream does not contain a header.");
      49             : 
      50         188 :   if (Header->Version != PdbTpiV80)
      51             :     return make_error<RawError>(raw_error_code::corrupt_file,
      52             :                                 "Unsupported TPI Version.");
      53             : 
      54          94 :   if (Header->HeaderSize != sizeof(TpiStreamHeader))
      55             :     return make_error<RawError>(raw_error_code::corrupt_file,
      56             :                                 "Corrupt TPI Header size.");
      57             : 
      58          94 :   if (Header->HashKeySize != sizeof(ulittle32_t))
      59             :     return make_error<RawError>(raw_error_code::corrupt_file,
      60             :                                 "TPI Stream expected 4 byte hash key size.");
      61             : 
      62          94 :   if (Header->NumHashBuckets < MinTpiHashBuckets ||
      63             :       Header->NumHashBuckets > MaxTpiHashBuckets)
      64             :     return make_error<RawError>(raw_error_code::corrupt_file,
      65             :                                 "TPI Stream Invalid number of hash buckets.");
      66             : 
      67             :   // The actual type records themselves come from this stream
      68          94 :   if (auto EC =
      69             :           Reader.readSubstream(TypeRecordsSubstream, Header->TypeRecordBytes))
      70             :     return EC;
      71             : 
      72         188 :   BinaryStreamReader RecordReader(TypeRecordsSubstream.StreamData);
      73          94 :   if (auto EC =
      74          94 :           RecordReader.readArray(TypeRecords, TypeRecordsSubstream.size()))
      75             :     return EC;
      76             : 
      77             :   // Hash indices, hash values, etc come from the hash stream.
      78         188 :   if (Header->HashStreamIndex != kInvalidStreamIndex) {
      79          85 :     if (Header->HashStreamIndex >= Pdb.getNumStreams())
      80             :       return make_error<RawError>(raw_error_code::corrupt_file,
      81             :                                   "Invalid TPI hash stream index.");
      82             : 
      83             :     auto HS = MappedBlockStream::createIndexedStream(
      84         255 :         Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex,
      85         255 :         Pdb.getAllocator());
      86          85 :     BinaryStreamReader HSR(*HS);
      87             : 
      88             :     // There should be a hash value for every type record, or no hashes at all.
      89             :     uint32_t NumHashValues =
      90         170 :         Header->HashValueBuffer.Length / sizeof(ulittle32_t);
      91          85 :     if (NumHashValues != getNumTypeRecords() && NumHashValues != 0)
      92             :       return make_error<RawError>(
      93             :           raw_error_code::corrupt_file,
      94             :           "TPI hash count does not match with the number of type records.");
      95          85 :     HSR.setOffset(Header->HashValueBuffer.Off);
      96         170 :     if (auto EC = HSR.readArray(HashValues, NumHashValues))
      97             :       return EC;
      98             : 
      99          85 :     HSR.setOffset(Header->IndexOffsetBuffer.Off);
     100             :     uint32_t NumTypeIndexOffsets =
     101          85 :         Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset);
     102         170 :     if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets))
     103             :       return EC;
     104             : 
     105         170 :     if (Header->HashAdjBuffer.Length > 0) {
     106             :       HSR.setOffset(Header->HashAdjBuffer.Off);
     107           0 :       if (auto EC = HashAdjusters.load(HSR))
     108             :         return EC;
     109             :     }
     110             : 
     111             :     HashStream = std::move(HS);
     112             :   }
     113             : 
     114         188 :   Types = llvm::make_unique<LazyRandomTypeCollection>(
     115         188 :       TypeRecords, getNumTypeRecords(), getTypeIndexOffsets());
     116             :   return Error::success();
     117             : }
     118             : 
     119          10 : PdbRaw_TpiVer TpiStream::getTpiVersion() const {
     120          10 :   uint32_t Value = Header->Version;
     121          10 :   return static_cast<PdbRaw_TpiVer>(Value);
     122             : }
     123             : 
     124         506 : uint32_t TpiStream::TypeIndexBegin() const { return Header->TypeIndexBegin; }
     125             : 
     126         506 : uint32_t TpiStream::TypeIndexEnd() const { return Header->TypeIndexEnd; }
     127             : 
     128         253 : uint32_t TpiStream::getNumTypeRecords() const {
     129         253 :   return TypeIndexEnd() - TypeIndexBegin();
     130             : }
     131             : 
     132         153 : uint16_t TpiStream::getTypeHashStreamIndex() const {
     133         306 :   return Header->HashStreamIndex;
     134             : }
     135             : 
     136         135 : uint16_t TpiStream::getTypeHashStreamAuxIndex() const {
     137         270 :   return Header->HashAuxStreamIndex;
     138             : }
     139             : 
     140          42 : uint32_t TpiStream::getNumHashBuckets() const { return Header->NumHashBuckets; }
     141           0 : uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; }
     142             : 
     143           4 : BinarySubstreamRef TpiStream::getTypeRecordsSubstream() const {
     144           4 :   return TypeRecordsSubstream;
     145             : }
     146             : 
     147          21 : FixedStreamArray<support::ulittle32_t> TpiStream::getHashValues() const {
     148          21 :   return HashValues;
     149             : }
     150             : 
     151         151 : FixedStreamArray<TypeIndexOffset> TpiStream::getTypeIndexOffsets() const {
     152         151 :   return TypeIndexOffsets;
     153             : }
     154             : 
     155           4 : HashTable<support::ulittle32_t> &TpiStream::getHashAdjusters() {
     156           4 :   return HashAdjusters;
     157             : }
     158             : 
     159          10 : CVTypeRange TpiStream::types(bool *HadError) const {
     160          40 :   return make_range(TypeRecords.begin(HadError), TypeRecords.end());
     161             : }
     162             : 
     163           0 : Error TpiStream::commit() { return Error::success(); }

Generated by: LCOV version 1.13