LCOV - code coverage report
Current view: top level - lib/DebugInfo/PDB/Native - TpiStreamBuilder.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 78 85 91.8 %
Date: 2017-09-14 15:23:50 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- TpiStreamBuilder.cpp -   -------------------------------------------===//
       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/TpiStreamBuilder.h"
      11             : #include "llvm/ADT/ArrayRef.h"
      12             : #include "llvm/ADT/STLExtras.h"
      13             : #include "llvm/DebugInfo/CodeView/TypeIndex.h"
      14             : #include "llvm/DebugInfo/CodeView/TypeRecord.h"
      15             : #include "llvm/DebugInfo/MSF/MSFBuilder.h"
      16             : #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
      17             : #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
      18             : #include "llvm/DebugInfo/PDB/Native/RawError.h"
      19             : #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
      20             : #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
      21             : #include "llvm/Support/Allocator.h"
      22             : #include "llvm/Support/BinaryByteStream.h"
      23             : #include "llvm/Support/BinaryStreamArray.h"
      24             : #include "llvm/Support/BinaryStreamReader.h"
      25             : #include "llvm/Support/BinaryStreamWriter.h"
      26             : #include "llvm/Support/Endian.h"
      27             : #include "llvm/Support/Error.h"
      28             : #include <algorithm>
      29             : #include <cstdint>
      30             : 
      31             : using namespace llvm;
      32             : using namespace llvm::msf;
      33             : using namespace llvm::pdb;
      34             : using namespace llvm::support;
      35             : 
      36         120 : TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx)
      37         600 :     : Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr), Idx(StreamIdx) {
      38         120 : }
      39             : 
      40             : TpiStreamBuilder::~TpiStreamBuilder() = default;
      41             : 
      42         114 : void TpiStreamBuilder::setVersionHeader(PdbRaw_TpiVer Version) {
      43         114 :   VerHeader = Version;
      44         114 : }
      45             : 
      46         907 : void TpiStreamBuilder::addTypeRecord(ArrayRef<uint8_t> Record,
      47             :                                      Optional<uint32_t> Hash) {
      48             :   // If we just crossed an 8KB threshold, add a type index offset.
      49         907 :   size_t NewSize = TypeRecordBytes + Record.size();
      50         907 :   constexpr size_t EightKB = 8 * 1024;
      51        1812 :   if (NewSize / EightKB > TypeRecordBytes / EightKB || TypeRecords.empty()) {
      52         270 :     TypeIndexOffsets.push_back(
      53             :         {codeview::TypeIndex(codeview::TypeIndex::FirstNonSimpleIndex +
      54          54 :                              TypeRecords.size()),
      55             :          ulittle32_t(TypeRecordBytes)});
      56             :   }
      57         907 :   TypeRecordBytes = NewSize;
      58             : 
      59         907 :   TypeRecords.push_back(Record);
      60         907 :   if (Hash)
      61         924 :     TypeHashes.push_back(*Hash);
      62         907 : }
      63             : 
      64         120 : Error TpiStreamBuilder::finalize() {
      65         120 :   if (Header)
      66           0 :     return Error::success();
      67             : 
      68         240 :   TpiStreamHeader *H = Allocator.Allocate<TpiStreamHeader>();
      69             : 
      70         240 :   uint32_t Count = TypeRecords.size();
      71             : 
      72         240 :   H->Version = VerHeader;
      73         240 :   H->HeaderSize = sizeof(TpiStreamHeader);
      74         240 :   H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex;
      75         360 :   H->TypeIndexEnd = H->TypeIndexBegin + Count;
      76         240 :   H->TypeRecordBytes = TypeRecordBytes;
      77             : 
      78         240 :   H->HashStreamIndex = HashStreamIndex;
      79         240 :   H->HashAuxStreamIndex = kInvalidStreamIndex;
      80         240 :   H->HashKeySize = sizeof(ulittle32_t);
      81         240 :   H->NumHashBuckets = MinTpiHashBuckets;
      82             : 
      83             :   // Recall that hash values go into a completely different stream identified by
      84             :   // the `HashStreamIndex` field of the `TpiStreamHeader`.  Therefore, the data
      85             :   // begins at offset 0 of this independent stream.
      86         240 :   H->HashValueBuffer.Off = 0;
      87         240 :   H->HashValueBuffer.Length = calculateHashBufferSize();
      88             : 
      89             :   // We never write any adjustments into our PDBs, so this is usually some
      90             :   // offset with zero length.
      91         480 :   H->HashAdjBuffer.Off = H->HashValueBuffer.Off + H->HashValueBuffer.Length;
      92         240 :   H->HashAdjBuffer.Length = 0;
      93             : 
      94         480 :   H->IndexOffsetBuffer.Off = H->HashAdjBuffer.Off + H->HashAdjBuffer.Length;
      95         240 :   H->IndexOffsetBuffer.Length = calculateIndexOffsetSize();
      96             : 
      97         120 :   Header = H;
      98         360 :   return Error::success();
      99             : }
     100             : 
     101         120 : uint32_t TpiStreamBuilder::calculateSerializedLength() {
     102         120 :   return sizeof(TpiStreamHeader) + TypeRecordBytes;
     103             : }
     104             : 
     105         274 : uint32_t TpiStreamBuilder::calculateHashBufferSize() const {
     106             :   assert((TypeRecords.size() == TypeHashes.size() || TypeHashes.empty()) &&
     107             :          "either all or no type records should have hashes");
     108         548 :   return TypeHashes.size() * sizeof(ulittle32_t);
     109             : }
     110             : 
     111         240 : uint32_t TpiStreamBuilder::calculateIndexOffsetSize() const {
     112         480 :   return TypeIndexOffsets.size() * sizeof(codeview::TypeIndexOffset);
     113             : }
     114             : 
     115         120 : Error TpiStreamBuilder::finalizeMsfLayout() {
     116         120 :   uint32_t Length = calculateSerializedLength();
     117         360 :   if (auto EC = Msf.setStreamSize(Idx, Length))
     118           0 :     return EC;
     119             : 
     120             :   uint32_t HashStreamSize =
     121         120 :       calculateHashBufferSize() + calculateIndexOffsetSize();
     122             : 
     123         120 :   if (HashStreamSize == 0)
     124         201 :     return Error::success();
     125             : 
     126          53 :   auto ExpectedIndex = Msf.addStream(HashStreamSize);
     127          53 :   if (!ExpectedIndex)
     128             :     return ExpectedIndex.takeError();
     129          53 :   HashStreamIndex = *ExpectedIndex;
     130         106 :   if (!TypeHashes.empty()) {
     131         102 :     ulittle32_t *H = Allocator.Allocate<ulittle32_t>(TypeHashes.size());
     132         102 :     MutableArrayRef<ulittle32_t> HashBuffer(H, TypeHashes.size());
     133         496 :     for (uint32_t I = 0; I < TypeHashes.size(); ++I) {
     134        1848 :       HashBuffer[I] = TypeHashes[I] % MinTpiHashBuckets;
     135             :     }
     136             :     ArrayRef<uint8_t> Bytes(
     137          34 :         reinterpret_cast<const uint8_t *>(HashBuffer.data()),
     138          68 :         calculateHashBufferSize());
     139          34 :     HashValueStream =
     140         102 :         llvm::make_unique<BinaryByteStream>(Bytes, llvm::support::little);
     141             :   }
     142         159 :   return Error::success();
     143             : }
     144             : 
     145         120 : Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout,
     146             :                                WritableBinaryStreamRef Buffer) {
     147         360 :   if (auto EC = finalize())
     148           0 :     return EC;
     149             : 
     150             :   auto InfoS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
     151         360 :                                                               Idx, Allocator);
     152             : 
     153         240 :   BinaryStreamWriter Writer(*InfoS);
     154         480 :   if (auto EC = Writer.writeObject(*Header))
     155           0 :     return EC;
     156             : 
     157        1387 :   for (auto Rec : TypeRecords)
     158        2721 :     if (auto EC = Writer.writeBytes(Rec))
     159           0 :       return EC;
     160             : 
     161         120 :   if (HashStreamIndex != kInvalidStreamIndex) {
     162             :     auto HVS = WritableMappedBlockStream::createIndexedStream(
     163         212 :         Layout, Buffer, HashStreamIndex, Allocator);
     164         106 :     BinaryStreamWriter HW(*HVS);
     165         106 :     if (HashValueStream) {
     166         170 :       if (auto EC = HW.writeStreamRef(*HashValueStream))
     167           0 :         return EC;
     168             :     }
     169             : 
     170         266 :     for (auto &IndexOffset : TypeIndexOffsets) {
     171         162 :       if (auto EC = HW.writeObject(IndexOffset))
     172           0 :         return EC;
     173             :     }
     174             :   }
     175             : 
     176         360 :   return Error::success();
     177             : }

Generated by: LCOV version 1.13