• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PDBFileBuilder(std::unique_ptr<codeview::StreamInterface> PdbFileBuffer)24 PDBFileBuilder::PDBFileBuilder(
25     std::unique_ptr<codeview::StreamInterface> PdbFileBuffer)
26     : File(llvm::make_unique<PDBFile>(std::move(PdbFileBuffer))) {}
27 
setSuperBlock(const PDBFile::SuperBlock & B)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 
setStreamSizes(ArrayRef<support::ulittle32_t> S)36 void PDBFileBuilder::setStreamSizes(ArrayRef<support::ulittle32_t> S) {
37   File->StreamSizes = S;
38 }
39 
setDirectoryBlocks(ArrayRef<support::ulittle32_t> D)40 void PDBFileBuilder::setDirectoryBlocks(ArrayRef<support::ulittle32_t> D) {
41   File->DirectoryBlocks = D;
42 }
43 
setStreamMap(const std::vector<ArrayRef<support::ulittle32_t>> & S)44 void PDBFileBuilder::setStreamMap(
45     const std::vector<ArrayRef<support::ulittle32_t>> &S) {
46   File->StreamMap = S;
47 }
48 
generateSimpleStreamMap()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 
getInfoBuilder()94 InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
95   if (!Info)
96     Info = llvm::make_unique<InfoStreamBuilder>(*File);
97   return *Info;
98 }
99 
getDbiBuilder()100 DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
101   if (!Dbi)
102     Dbi = llvm::make_unique<DbiStreamBuilder>(*File);
103   return *Dbi;
104 }
105 
build()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