LCOV - code coverage report
Current view: top level - lib/DebugInfo/PDB/Native - TpiStream.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 54 71 76.1 %
Date: 2017-09-14 15:23:50 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          82 : TpiStream::TpiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
      35         656 :     : Pdb(File), Stream(std::move(Stream)) {}
      36             : 
      37             : TpiStream::~TpiStream() = default;
      38             : 
      39          82 : Error TpiStream::reload() {
      40         246 :   BinaryStreamReader Reader(*Stream);
      41             : 
      42          82 :   if (Reader.bytesRemaining() < sizeof(TpiStreamHeader))
      43             :     return make_error<RawError>(raw_error_code::corrupt_file,
      44           0 :                                 "TPI Stream does not contain a header.");
      45             : 
      46         246 :   if (Reader.readObject(Header))
      47             :     return make_error<RawError>(raw_error_code::corrupt_file,
      48           0 :                                 "TPI Stream does not contain a header.");
      49             : 
      50         164 :   if (Header->Version != PdbTpiV80)
      51             :     return make_error<RawError>(raw_error_code::corrupt_file,
      52           0 :                                 "Unsupported TPI Version.");
      53             : 
      54         164 :   if (Header->HeaderSize != sizeof(TpiStreamHeader))
      55             :     return make_error<RawError>(raw_error_code::corrupt_file,
      56           0 :                                 "Corrupt TPI Header size.");
      57             : 
      58         164 :   if (Header->HashKeySize != sizeof(ulittle32_t))
      59             :     return make_error<RawError>(raw_error_code::corrupt_file,
      60           0 :                                 "TPI Stream expected 4 byte hash key size.");
      61             : 
      62         246 :   if (Header->NumHashBuckets < MinTpiHashBuckets ||
      63         164 :       Header->NumHashBuckets > MaxTpiHashBuckets)
      64             :     return make_error<RawError>(raw_error_code::corrupt_file,
      65           0 :                                 "TPI Stream Invalid number of hash buckets.");
      66             : 
      67             :   // The actual type records themselves come from this stream
      68          82 :   if (auto EC =
      69         328 :           Reader.readSubstream(TypeRecordsSubstream, Header->TypeRecordBytes))
      70           0 :     return EC;
      71             : 
      72         246 :   BinaryStreamReader RecordReader(TypeRecordsSubstream.StreamData);
      73          82 :   if (auto EC =
      74         328 :           RecordReader.readArray(TypeRecords, TypeRecordsSubstream.size()))
      75           0 :     return EC;
      76             : 
      77             :   // Hash indices, hash values, etc come from the hash stream.
      78         164 :   if (Header->HashStreamIndex != kInvalidStreamIndex) {
      79         146 :     if (Header->HashStreamIndex >= Pdb.getNumStreams())
      80             :       return make_error<RawError>(raw_error_code::corrupt_file,
      81           0 :                                   "Invalid TPI hash stream index.");
      82             : 
      83             :     auto HS = MappedBlockStream::createIndexedStream(
      84         292 :         Pdb.getMsfLayout(), Pdb.getMsfBuffer(), Header->HashStreamIndex,
      85         365 :         Pdb.getAllocator());
      86         146 :     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         146 :         Header->HashValueBuffer.Length / sizeof(ulittle32_t);
      91          73 :     if (NumHashValues != getNumTypeRecords() && NumHashValues != 0)
      92             :       return make_error<RawError>(
      93             :           raw_error_code::corrupt_file,
      94           0 :           "TPI hash count does not match with the number of type records.");
      95         219 :     HSR.setOffset(Header->HashValueBuffer.Off);
      96         219 :     if (auto EC = HSR.readArray(HashValues, NumHashValues))
      97           0 :       return EC;
      98             : 
      99         219 :     HSR.setOffset(Header->IndexOffsetBuffer.Off);
     100             :     uint32_t NumTypeIndexOffsets =
     101         146 :         Header->IndexOffsetBuffer.Length / sizeof(TypeIndexOffset);
     102         219 :     if (auto EC = HSR.readArray(TypeIndexOffsets, NumTypeIndexOffsets))
     103           0 :       return EC;
     104             : 
     105         146 :     if (Header->HashAdjBuffer.Length > 0) {
     106           0 :       HSR.setOffset(Header->HashAdjBuffer.Off);
     107           0 :       if (auto EC = HashAdjusters.load(HSR))
     108           0 :         return EC;
     109             :     }
     110             : 
     111         146 :     HashStream = std::move(HS);
     112             :   }
     113             : 
     114         246 :   Types = llvm::make_unique<LazyRandomTypeCollection>(
     115         328 :       TypeRecords, getNumTypeRecords(), getTypeIndexOffsets());
     116         246 :   return Error::success();
     117             : }
     118             : 
     119          10 : PdbRaw_TpiVer TpiStream::getTpiVersion() const {
     120          20 :   uint32_t Value = Header->Version;
     121          10 :   return static_cast<PdbRaw_TpiVer>(Value);
     122             : }
     123             : 
     124         444 : uint32_t TpiStream::TypeIndexBegin() const { return Header->TypeIndexBegin; }
     125             : 
     126         444 : uint32_t TpiStream::TypeIndexEnd() const { return Header->TypeIndexEnd; }
     127             : 
     128         222 : uint32_t TpiStream::getNumTypeRecords() const {
     129         222 :   return TypeIndexEnd() - TypeIndexBegin();
     130             : }
     131             : 
     132         183 : uint16_t TpiStream::getTypeHashStreamIndex() const {
     133         366 :   return Header->HashStreamIndex;
     134             : }
     135             : 
     136         161 : uint16_t TpiStream::getTypeHashStreamAuxIndex() const {
     137         322 :   return Header->HashAuxStreamIndex;
     138             : }
     139             : 
     140          30 : 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           8 :   return TypeRecordsSubstream;
     145             : }
     146             : 
     147          15 : FixedStreamArray<support::ulittle32_t> TpiStream::getHashValues() const {
     148          30 :   return HashValues;
     149             : }
     150             : 
     151         125 : FixedStreamArray<TypeIndexOffset> TpiStream::getTypeIndexOffsets() const {
     152         250 :   return TypeIndexOffsets;
     153             : }
     154             : 
     155           4 : HashTable &TpiStream::getHashAdjusters() { return HashAdjusters; }
     156             : 
     157          10 : CVTypeRange TpiStream::types(bool *HadError) const {
     158          50 :   return make_range(TypeRecords.begin(HadError), TypeRecords.end());
     159             : }
     160             : 
     161           0 : Error TpiStream::commit() { return Error::success(); }

Generated by: LCOV version 1.13