LCOV - code coverage report
Current view: top level - lib/DebugInfo/PDB/Native - PDBFileBuilder.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 111 131 84.7 %
Date: 2017-09-14 15:23:50 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          60 : PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
      35         480 :     : Allocator(Allocator) {}
      36             : 
      37         240 : PDBFileBuilder::~PDBFileBuilder() {}
      38             : 
      39          60 : Error PDBFileBuilder::initialize(uint32_t BlockSize) {
      40         120 :   auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
      41          60 :   if (!ExpectedMsf)
      42             :     return ExpectedMsf.takeError();
      43         120 :   Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf));
      44         180 :   return Error::success();
      45             : }
      46             : 
      47         600 : MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
      48             : 
      49          85 : InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
      50         170 :   if (!Info)
      51         180 :     Info = llvm::make_unique<InfoStreamBuilder>(*Msf, NamedStreams);
      52         170 :   return *Info;
      53             : }
      54             : 
      55         466 : DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
      56         932 :   if (!Dbi)
      57         171 :     Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf);
      58         932 :   return *Dbi;
      59             : }
      60             : 
      61          60 : TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
      62         120 :   if (!Tpi)
      63         180 :     Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
      64         120 :   return *Tpi;
      65             : }
      66             : 
      67          60 : TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
      68         120 :   if (!Ipi)
      69         180 :     Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
      70         120 :   return *Ipi;
      71             : }
      72             : 
      73          57 : PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() {
      74          57 :   return Strings;
      75             : }
      76             : 
      77         148 : GSIStreamBuilder &PDBFileBuilder::getGsiBuilder() {
      78         296 :   if (!Gsi)
      79         120 :     Gsi = llvm::make_unique<GSIStreamBuilder>(*Msf);
      80         296 :   return *Gsi;
      81             : }
      82             : 
      83         120 : Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) {
      84         360 :   auto ExpectedStream = Msf->addStream(Size);
      85         120 :   if (!ExpectedStream)
      86             :     return ExpectedStream.takeError();
      87         240 :   NamedStreams.set(Name, *ExpectedStream);
      88         360 :   return Error::success();
      89             : }
      90             : 
      91          60 : Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
      92             : 
      93         240 :   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          25 :     auto &Info = getInfoBuilder();
      99          25 :     Info.addFeature(PdbRaw_FeatureSig::VC140);
     100             :   }
     101             : 
     102          60 :   uint32_t StringsLen = Strings.calculateSerializedSize();
     103             : 
     104         180 :   if (auto EC = addNamedStream("/names", StringsLen))
     105           0 :     return std::move(EC);
     106         180 :   if (auto EC = addNamedStream("/LinkInfo", 0))
     107           0 :     return std::move(EC);
     108             : 
     109         120 :   if (Info) {
     110         240 :     if (auto EC = Info->finalizeMsfLayout())
     111           0 :       return std::move(EC);
     112             :   }
     113         120 :   if (Dbi) {
     114         228 :     if (auto EC = Dbi->finalizeMsfLayout())
     115           0 :       return std::move(EC);
     116             :   }
     117         120 :   if (Tpi) {
     118         240 :     if (auto EC = Tpi->finalizeMsfLayout())
     119           0 :       return std::move(EC);
     120             :   }
     121         120 :   if (Ipi) {
     122         240 :     if (auto EC = Ipi->finalizeMsfLayout())
     123           0 :       return std::move(EC);
     124             :   }
     125         120 :   if (Gsi) {
     126         160 :     if (auto EC = Gsi->finalizeMsfLayout())
     127           0 :       return std::move(EC);
     128          80 :     if (Dbi) {
     129         120 :       Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex());
     130         120 :       Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex());
     131         120 :       Dbi->setSymbolRecordStreamIndex(Gsi->getRecordStreamIdx());
     132             :     }
     133             :   }
     134             : 
     135         120 :   return Msf->build();
     136             : }
     137             : 
     138          60 : Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
     139          60 :   uint32_t SN = 0;
     140          60 :   if (!NamedStreams.get(Name, SN))
     141           0 :     return llvm::make_error<pdb::RawError>(raw_error_code::no_stream);
     142             :   return SN;
     143             : }
     144             : 
     145          60 : void PDBFileBuilder::commitFpm(WritableBinaryStream &MsfBuffer,
     146             :                                const MSFLayout &Layout) {
     147             :   auto FpmStream =
     148         180 :       WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator);
     149             : 
     150             :   // We only need to create the alt fpm stream so that it gets initialized.
     151         180 :   WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator,
     152             :                                              true);
     153             : 
     154          60 :   uint32_t BI = 0;
     155         120 :   BinaryStreamWriter FpmWriter(*FpmStream);
     156         552 :   while (BI < Layout.SB->NumBlocks) {
     157         144 :     uint8_t ThisByte = 0;
     158        1296 :     for (uint32_t I = 0; I < 8; ++I) {
     159             :       bool IsFree =
     160        3258 :           (BI < Layout.SB->NumBlocks) ? Layout.FreePageMap.test(BI) : true;
     161        1152 :       uint8_t Mask = uint8_t(IsFree) << I;
     162        1152 :       ThisByte |= Mask;
     163        1152 :       ++BI;
     164             :     }
     165         432 :     cantFail(FpmWriter.writeObject(ThisByte));
     166             :   }
     167             :   assert(FpmWriter.bytesRemaining() == 0);
     168          60 : }
     169             : 
     170          60 : Error PDBFileBuilder::commit(StringRef Filename) {
     171             :   assert(!Filename.empty());
     172         120 :   auto ExpectedLayout = finalizeMsfLayout();
     173          60 :   if (!ExpectedLayout)
     174             :     return ExpectedLayout.takeError();
     175          60 :   auto &Layout = *ExpectedLayout;
     176             : 
     177         180 :   uint64_t Filesize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
     178          60 :   auto OutFileOrError = FileOutputBuffer::create(Filename, Filesize);
     179          60 :   if (OutFileOrError.getError())
     180             :     return llvm::make_error<pdb::GenericError>(generic_error_code::invalid_path,
     181           0 :                                                Filename);
     182          60 :   FileBufferByteStream Buffer(std::move(*OutFileOrError),
     183          60 :                               llvm::support::little);
     184         120 :   BinaryStreamWriter Writer(Buffer);
     185             : 
     186         240 :   if (auto EC = Writer.writeObject(*Layout.SB))
     187           0 :     return EC;
     188             : 
     189          60 :   commitFpm(Buffer, Layout);
     190             : 
     191             :   uint32_t BlockMapOffset =
     192         240 :       msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
     193         120 :   Writer.setOffset(BlockMapOffset);
     194         180 :   if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
     195           0 :     return EC;
     196             : 
     197             :   auto DirStream = WritableMappedBlockStream::createDirectoryStream(
     198         120 :       Layout, Buffer, Allocator);
     199         120 :   BinaryStreamWriter DW(*DirStream);
     200         180 :   if (auto EC = DW.writeInteger<uint32_t>(Layout.StreamSizes.size()))
     201           0 :     return EC;
     202             : 
     203         180 :   if (auto EC = DW.writeArray(Layout.StreamSizes))
     204           0 :     return EC;
     205             : 
     206        1021 :   for (const auto &Blocks : Layout.StreamMap) {
     207        2343 :     if (auto EC = DW.writeArray(Blocks))
     208           0 :       return EC;
     209             :   }
     210             : 
     211          60 :   auto ExpectedSN = getNamedStreamIndex("/names");
     212          60 :   if (!ExpectedSN)
     213             :     return ExpectedSN.takeError();
     214             : 
     215             :   auto NS = WritableMappedBlockStream::createIndexedStream(
     216         180 :       Layout, Buffer, *ExpectedSN, Allocator);
     217         120 :   BinaryStreamWriter NSWriter(*NS);
     218         180 :   if (auto EC = Strings.commit(NSWriter))
     219           0 :     return EC;
     220             : 
     221         120 :   if (Info) {
     222         300 :     if (auto EC = Info->commit(Layout, Buffer))
     223           0 :       return EC;
     224             :   }
     225             : 
     226         120 :   if (Dbi) {
     227         285 :     if (auto EC = Dbi->commit(Layout, Buffer))
     228           0 :       return EC;
     229             :   }
     230             : 
     231         120 :   if (Tpi) {
     232         240 :     if (auto EC = Tpi->commit(Layout, Buffer))
     233           0 :       return EC;
     234             :   }
     235             : 
     236         120 :   if (Ipi) {
     237         300 :     if (auto EC = Ipi->commit(Layout, Buffer))
     238           0 :       return EC;
     239             :   }
     240             : 
     241         120 :   if (Gsi) {
     242         200 :     if (auto EC = Gsi->commit(Layout, Buffer))
     243           0 :       return EC;
     244             :   }
     245             : 
     246             :   return Buffer.commit();
     247             : }

Generated by: LCOV version 1.13