LCOV - code coverage report
Current view: top level - lib/DebugInfo/PDB/Native - PDBFileBuilder.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 105 106 99.1 %
Date: 2018-02-23 15:42:53 Functions: 15 15 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- PDBFileBuilder.cpp - PDB File Creation -------------------*- C++ -*-===//
       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/PDBFileBuilder.h"
      11             : 
      12             : #include "llvm/ADT/BitVector.h"
      13             : 
      14             : #include "llvm/DebugInfo/MSF/MSFBuilder.h"
      15             : #include "llvm/DebugInfo/PDB/GenericError.h"
      16             : #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
      17             : #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
      18             : #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
      19             : #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
      20             : #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
      21             : #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
      22             : #include "llvm/DebugInfo/PDB/Native/RawError.h"
      23             : #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
      24             : #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
      25             : #include "llvm/Support/BinaryStream.h"
      26             : #include "llvm/Support/BinaryStreamWriter.h"
      27             : 
      28             : using namespace llvm;
      29             : using namespace llvm::codeview;
      30             : using namespace llvm::msf;
      31             : using namespace llvm::pdb;
      32             : using namespace llvm::support;
      33             : 
      34          80 : PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
      35         160 :     : Allocator(Allocator) {}
      36             : 
      37         240 : PDBFileBuilder::~PDBFileBuilder() {}
      38             : 
      39          80 : Error PDBFileBuilder::initialize(uint32_t BlockSize) {
      40         160 :   auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
      41          80 :   if (!ExpectedMsf)
      42             :     return ExpectedMsf.takeError();
      43          80 :   Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf));
      44             :   return Error::success();
      45             : }
      46             : 
      47         800 : MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
      48             : 
      49         113 : InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
      50         113 :   if (!Info)
      51          80 :     Info = llvm::make_unique<InfoStreamBuilder>(*Msf, NamedStreams);
      52         113 :   return *Info;
      53             : }
      54             : 
      55         678 : DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
      56         678 :   if (!Dbi)
      57          77 :     Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf);
      58         678 :   return *Dbi;
      59             : }
      60             : 
      61          80 : TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
      62          80 :   if (!Tpi)
      63          80 :     Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
      64          80 :   return *Tpi;
      65             : }
      66             : 
      67          80 : TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
      68          80 :   if (!Ipi)
      69          80 :     Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
      70          80 :   return *Ipi;
      71             : }
      72             : 
      73          77 : PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() {
      74          77 :   return Strings;
      75             : }
      76             : 
      77         225 : GSIStreamBuilder &PDBFileBuilder::getGsiBuilder() {
      78         225 :   if (!Gsi)
      79          59 :     Gsi = llvm::make_unique<GSIStreamBuilder>(*Msf);
      80         225 :   return *Gsi;
      81             : }
      82             : 
      83         160 : Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) {
      84         160 :   auto ExpectedStream = Msf->addStream(Size);
      85         160 :   if (!ExpectedStream)
      86             :     return ExpectedStream.takeError();
      87         160 :   NamedStreams.set(Name, *ExpectedStream);
      88             :   return Error::success();
      89             : }
      90             : 
      91          80 : Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
      92             : 
      93         160 :   if (Ipi && Ipi->getRecordCount() > 0) {
      94             :     // In theory newer PDBs always have an ID stream, but by saying that we're
      95             :     // only going to *really* have an ID stream if there is at least one ID
      96             :     // record, we leave open the opportunity to test older PDBs such as those
      97             :     // that don't have an ID stream.
      98          33 :     auto &Info = getInfoBuilder();
      99          33 :     Info.addFeature(PdbRaw_FeatureSig::VC140);
     100             :   }
     101             : 
     102          80 :   uint32_t StringsLen = Strings.calculateSerializedSize();
     103             : 
     104         160 :   if (auto EC = addNamedStream("/names", StringsLen))
     105             :     return std::move(EC);
     106         160 :   if (auto EC = addNamedStream("/LinkInfo", 0))
     107             :     return std::move(EC);
     108             : 
     109          80 :   if (Info) {
     110         160 :     if (auto EC = Info->finalizeMsfLayout())
     111             :       return std::move(EC);
     112             :   }
     113          80 :   if (Dbi) {
     114         154 :     if (auto EC = Dbi->finalizeMsfLayout())
     115             :       return std::move(EC);
     116             :   }
     117          80 :   if (Tpi) {
     118         160 :     if (auto EC = Tpi->finalizeMsfLayout())
     119             :       return std::move(EC);
     120             :   }
     121          80 :   if (Ipi) {
     122         160 :     if (auto EC = Ipi->finalizeMsfLayout())
     123             :       return std::move(EC);
     124             :   }
     125          80 :   if (Gsi) {
     126         118 :     if (auto EC = Gsi->finalizeMsfLayout())
     127             :       return std::move(EC);
     128          59 :     if (Dbi) {
     129          59 :       Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex());
     130          59 :       Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex());
     131          59 :       Dbi->setSymbolRecordStreamIndex(Gsi->getRecordStreamIdx());
     132             :     }
     133             :   }
     134             : 
     135          80 :   return Msf->build();
     136             : }
     137             : 
     138          80 : Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
     139          80 :   uint32_t SN = 0;
     140          80 :   if (!NamedStreams.get(Name, SN))
     141           0 :     return llvm::make_error<pdb::RawError>(raw_error_code::no_stream);
     142             :   return SN;
     143             : }
     144             : 
     145          80 : void PDBFileBuilder::commitFpm(WritableBinaryStream &MsfBuffer,
     146             :                                const MSFLayout &Layout) {
     147             :   auto FpmStream =
     148         160 :       WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator);
     149             : 
     150             :   // We only need to create the alt fpm stream so that it gets initialized.
     151         240 :   WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator,
     152             :                                              true);
     153             : 
     154             :   uint32_t BI = 0;
     155          80 :   BinaryStreamWriter FpmWriter(*FpmStream);
     156         742 :   while (BI < Layout.SB->NumBlocks) {
     157         194 :     uint8_t ThisByte = 0;
     158        3298 :     for (uint32_t I = 0; I < 8; ++I) {
     159             :       bool IsFree =
     160        2846 :           (BI < Layout.SB->NumBlocks) ? Layout.FreePageMap.test(BI) : true;
     161        1552 :       uint8_t Mask = uint8_t(IsFree) << I;
     162        1552 :       ThisByte |= Mask;
     163        1552 :       ++BI;
     164             :     }
     165         194 :     cantFail(FpmWriter.writeObject(ThisByte));
     166             :   }
     167             :   assert(FpmWriter.bytesRemaining() == 0);
     168          80 : }
     169             : 
     170          80 : Error PDBFileBuilder::commit(StringRef Filename) {
     171             :   assert(!Filename.empty());
     172         160 :   auto ExpectedLayout = finalizeMsfLayout();
     173          80 :   if (!ExpectedLayout)
     174             :     return ExpectedLayout.takeError();
     175             :   auto &Layout = *ExpectedLayout;
     176             : 
     177         160 :   uint64_t Filesize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
     178         160 :   auto OutFileOrError = FileOutputBuffer::create(Filename, Filesize);
     179          80 :   if (auto E = OutFileOrError.takeError())
     180             :     return E;
     181             :   FileBufferByteStream Buffer(std::move(*OutFileOrError),
     182         160 :                               llvm::support::little);
     183          80 :   BinaryStreamWriter Writer(Buffer);
     184             : 
     185         160 :   if (auto EC = Writer.writeObject(*Layout.SB))
     186             :     return EC;
     187             : 
     188          80 :   commitFpm(Buffer, Layout);
     189             : 
     190             :   uint32_t BlockMapOffset =
     191         320 :       msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
     192             :   Writer.setOffset(BlockMapOffset);
     193         160 :   if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
     194             :     return EC;
     195             : 
     196             :   auto DirStream = WritableMappedBlockStream::createDirectoryStream(
     197         160 :       Layout, Buffer, Allocator);
     198          80 :   BinaryStreamWriter DW(*DirStream);
     199         160 :   if (auto EC = DW.writeInteger<uint32_t>(Layout.StreamSizes.size()))
     200             :     return EC;
     201             : 
     202         160 :   if (auto EC = DW.writeArray(Layout.StreamSizes))
     203             :     return EC;
     204             : 
     205        1158 :   for (const auto &Blocks : Layout.StreamMap) {
     206        2156 :     if (auto EC = DW.writeArray(Blocks))
     207             :       return EC;
     208             :   }
     209             : 
     210          80 :   auto ExpectedSN = getNamedStreamIndex("/names");
     211          80 :   if (!ExpectedSN)
     212             :     return ExpectedSN.takeError();
     213             : 
     214             :   auto NS = WritableMappedBlockStream::createIndexedStream(
     215         160 :       Layout, Buffer, *ExpectedSN, Allocator);
     216          80 :   BinaryStreamWriter NSWriter(*NS);
     217         160 :   if (auto EC = Strings.commit(NSWriter))
     218             :     return EC;
     219             : 
     220          80 :   if (Info) {
     221         240 :     if (auto EC = Info->commit(Layout, Buffer))
     222             :       return EC;
     223             :   }
     224             : 
     225          80 :   if (Dbi) {
     226         231 :     if (auto EC = Dbi->commit(Layout, Buffer))
     227             :       return EC;
     228             :   }
     229             : 
     230          80 :   if (Tpi) {
     231         240 :     if (auto EC = Tpi->commit(Layout, Buffer))
     232             :       return EC;
     233             :   }
     234             : 
     235          80 :   if (Ipi) {
     236         240 :     if (auto EC = Ipi->commit(Layout, Buffer))
     237             :       return EC;
     238             :   }
     239             : 
     240          80 :   if (Gsi) {
     241         177 :     if (auto EC = Gsi->commit(Layout, Buffer))
     242             :       return EC;
     243             :   }
     244             : 
     245             :   return Buffer.commit();
     246             : }

Generated by: LCOV version 1.13