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

Generated by: LCOV version 1.13