Home | History | Annotate | Download | only in Raw
      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/Raw/PDBFileBuilder.h"
     11 
     12 #include "llvm/DebugInfo/CodeView/StreamInterface.h"
     13 #include "llvm/DebugInfo/CodeView/StreamWriter.h"
     14 #include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
     15 #include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h"
     16 #include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
     17 #include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h"
     18 #include "llvm/DebugInfo/PDB/Raw/RawError.h"
     19 
     20 using namespace llvm;
     21 using namespace llvm::codeview;
     22 using namespace llvm::pdb;
     23 
     24 PDBFileBuilder::PDBFileBuilder(
     25     std::unique_ptr<codeview::StreamInterface> PdbFileBuffer)
     26     : File(llvm::make_unique<PDBFile>(std::move(PdbFileBuffer))) {}
     27 
     28 Error PDBFileBuilder::setSuperBlock(const PDBFile::SuperBlock &B) {
     29   auto SB = static_cast<PDBFile::SuperBlock *>(
     30       File->Allocator.Allocate(sizeof(PDBFile::SuperBlock),
     31                                llvm::AlignOf<PDBFile::SuperBlock>::Alignment));
     32   ::memcpy(SB, &B, sizeof(PDBFile::SuperBlock));
     33   return File->setSuperBlock(SB);
     34 }
     35 
     36 void PDBFileBuilder::setStreamSizes(ArrayRef<support::ulittle32_t> S) {
     37   File->StreamSizes = S;
     38 }
     39 
     40 void PDBFileBuilder::setDirectoryBlocks(ArrayRef<support::ulittle32_t> D) {
     41   File->DirectoryBlocks = D;
     42 }
     43 
     44 void PDBFileBuilder::setStreamMap(
     45     const std::vector<ArrayRef<support::ulittle32_t>> &S) {
     46   File->StreamMap = S;
     47 }
     48 
     49 Error PDBFileBuilder::generateSimpleStreamMap() {
     50   if (File->StreamSizes.empty())
     51     return Error::success();
     52 
     53   static std::vector<std::vector<support::ulittle32_t>> StaticMap;
     54   File->StreamMap.clear();
     55   StaticMap.clear();
     56 
     57   // Figure out how many blocks are needed for all streams, and set the first
     58   // used block to the highest block so that we can write the rest of the
     59   // blocks contiguously.
     60   uint32_t TotalFileBlocks = File->getBlockCount();
     61   std::vector<support::ulittle32_t> ReservedBlocks;
     62   ReservedBlocks.push_back(support::ulittle32_t(0));
     63   ReservedBlocks.push_back(File->SB->BlockMapAddr);
     64   ReservedBlocks.insert(ReservedBlocks.end(), File->DirectoryBlocks.begin(),
     65                         File->DirectoryBlocks.end());
     66 
     67   uint32_t BlocksNeeded = 0;
     68   for (auto Size : File->StreamSizes)
     69     BlocksNeeded += File->bytesToBlocks(Size, File->getBlockSize());
     70 
     71   support::ulittle32_t NextBlock(TotalFileBlocks - BlocksNeeded -
     72                                  ReservedBlocks.size());
     73 
     74   StaticMap.resize(File->StreamSizes.size());
     75   for (uint32_t S = 0; S < File->StreamSizes.size(); ++S) {
     76     uint32_t Size = File->StreamSizes[S];
     77     uint32_t NumBlocks = File->bytesToBlocks(Size, File->getBlockSize());
     78     auto &ThisStream = StaticMap[S];
     79     for (uint32_t I = 0; I < NumBlocks;) {
     80       NextBlock += 1;
     81       if (std::find(ReservedBlocks.begin(), ReservedBlocks.end(), NextBlock) !=
     82           ReservedBlocks.end())
     83         continue;
     84 
     85       ++I;
     86       assert(NextBlock < File->getBlockCount());
     87       ThisStream.push_back(NextBlock);
     88     }
     89     File->StreamMap.push_back(ThisStream);
     90   }
     91   return Error::success();
     92 }
     93 
     94 InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
     95   if (!Info)
     96     Info = llvm::make_unique<InfoStreamBuilder>(*File);
     97   return *Info;
     98 }
     99 
    100 DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
    101   if (!Dbi)
    102     Dbi = llvm::make_unique<DbiStreamBuilder>(*File);
    103   return *Dbi;
    104 }
    105 
    106 Expected<std::unique_ptr<PDBFile>> PDBFileBuilder::build() {
    107   if (Info) {
    108     auto ExpectedInfo = Info->build();
    109     if (!ExpectedInfo)
    110       return ExpectedInfo.takeError();
    111     File->Info = std::move(*ExpectedInfo);
    112   }
    113 
    114   if (Dbi) {
    115     auto ExpectedDbi = Dbi->build();
    116     if (!ExpectedDbi)
    117       return ExpectedDbi.takeError();
    118     File->Dbi = std::move(*ExpectedDbi);
    119   }
    120 
    121   if (File->Info && File->Dbi && File->Info->getAge() != File->Dbi->getAge())
    122     return llvm::make_error<RawError>(
    123         raw_error_code::corrupt_file,
    124         "PDB Stream Age doesn't match Dbi Stream Age!");
    125 
    126   return std::move(File);
    127 }
    128