Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
Line
Count
Source (jump to first uncovered line)
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
PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
35
60
    : Allocator(Allocator) {}
36
37
60
PDBFileBuilder::~PDBFileBuilder() {}
38
39
60
Error PDBFileBuilder::initialize(uint32_t BlockSize) {
40
60
  auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
41
60
  if (!ExpectedMsf)
42
0
    return ExpectedMsf.takeError();
43
60
  Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf));
44
60
  return Error::success();
45
60
}
46
47
300
MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
48
49
85
InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
50
85
  if (!Info)
51
60
    Info = llvm::make_unique<InfoStreamBuilder>(*Msf, NamedStreams);
52
85
  return *Info;
53
85
}
54
55
466
DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
56
466
  if (!Dbi)
57
57
    Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf);
58
466
  return *Dbi;
59
466
}
60
61
60
TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
62
60
  if (!Tpi)
63
60
    Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
64
60
  return *Tpi;
65
60
}
66
67
60
TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
68
60
  if (!Ipi)
69
60
    Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
70
60
  return *Ipi;
71
60
}
72
73
57
PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() {
74
57
  return Strings;
75
57
}
76
77
148
GSIStreamBuilder &PDBFileBuilder::getGsiBuilder() {
78
148
  if (!Gsi)
79
40
    Gsi = llvm::make_unique<GSIStreamBuilder>(*Msf);
80
148
  return *Gsi;
81
148
}
82
83
120
Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) {
84
120
  auto ExpectedStream = Msf->addStream(Size);
85
120
  if (!ExpectedStream)
86
0
    return ExpectedStream.takeError();
87
120
  NamedStreams.set(Name, *ExpectedStream);
88
120
  return Error::success();
89
120
}
90
91
60
Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
92
60
93
60
  if (
Ipi && 60
Ipi->getRecordCount() > 060
) {
94
25
    // In theory newer PDBs always have an ID stream, but by saying that we're
95
25
    // only going to *really* have an ID stream if there is at least one ID
96
25
    // record, we leave open the opportunity to test older PDBs such as those
97
25
    // that don't have an ID stream.
98
25
    auto &Info = getInfoBuilder();
99
25
    Info.addFeature(PdbRaw_FeatureSig::VC140);
100
25
  }
101
60
102
60
  uint32_t StringsLen = Strings.calculateSerializedSize();
103
60
104
60
  if (auto EC = addNamedStream("/names", StringsLen))
105
0
    return std::move(EC);
106
60
  
if (auto 60
EC60
= addNamedStream("/LinkInfo", 0))
107
0
    return std::move(EC);
108
60
109
60
  
if (60
Info60
) {
110
60
    if (auto EC = Info->finalizeMsfLayout())
111
0
      return std::move(EC);
112
60
  }
113
60
  
if (60
Dbi60
) {
114
57
    if (auto EC = Dbi->finalizeMsfLayout())
115
0
      return std::move(EC);
116
60
  }
117
60
  
if (60
Tpi60
) {
118
60
    if (auto EC = Tpi->finalizeMsfLayout())
119
0
      return std::move(EC);
120
60
  }
121
60
  
if (60
Ipi60
) {
122
60
    if (auto EC = Ipi->finalizeMsfLayout())
123
0
      return std::move(EC);
124
60
  }
125
60
  
if (60
Gsi60
) {
126
40
    if (auto EC = Gsi->finalizeMsfLayout())
127
0
      return std::move(EC);
128
40
    
if (40
Dbi40
) {
129
40
      Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex());
130
40
      Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex());
131
40
      Dbi->setSymbolRecordStreamIndex(Gsi->getRecordStreamIdx());
132
40
    }
133
40
  }
134
60
135
60
  return Msf->build();
136
60
}
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
60
  return SN;
143
60
}
144
145
void PDBFileBuilder::commitFpm(WritableBinaryStream &MsfBuffer,
146
60
                               const MSFLayout &Layout) {
147
60
  auto FpmStream =
148
60
      WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator);
149
60
150
60
  // We only need to create the alt fpm stream so that it gets initialized.
151
60
  WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator,
152
60
                                             true);
153
60
154
60
  uint32_t BI = 0;
155
60
  BinaryStreamWriter FpmWriter(*FpmStream);
156
204
  while (
BI < Layout.SB->NumBlocks204
) {
157
144
    uint8_t ThisByte = 0;
158
1.29k
    for (uint32_t I = 0; 
I < 81.29k
;
++I1.15k
) {
159
1.15k
      bool IsFree =
160
1.15k
          (BI < Layout.SB->NumBlocks) ? 
Layout.FreePageMap.test(BI)954
:
true198
;
161
1.15k
      uint8_t Mask = uint8_t(IsFree) << I;
162
1.15k
      ThisByte |= Mask;
163
1.15k
      ++BI;
164
1.15k
    }
165
144
    cantFail(FpmWriter.writeObject(ThisByte));
166
144
  }
167
60
  assert(FpmWriter.bytesRemaining() == 0);
168
60
}
169
170
60
Error PDBFileBuilder::commit(StringRef Filename) {
171
60
  assert(!Filename.empty());
172
60
  auto ExpectedLayout = finalizeMsfLayout();
173
60
  if (!ExpectedLayout)
174
0
    return ExpectedLayout.takeError();
175
60
  auto &Layout = *ExpectedLayout;
176
60
177
60
  uint64_t Filesize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
178
60
  auto OutFileOrError = FileOutputBuffer::create(Filename, Filesize);
179
60
  if (OutFileOrError.getError())
180
0
    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
60
  BinaryStreamWriter Writer(Buffer);
185
60
186
60
  if (auto EC = Writer.writeObject(*Layout.SB))
187
0
    return EC;
188
60
189
60
  commitFpm(Buffer, Layout);
190
60
191
60
  uint32_t BlockMapOffset =
192
60
      msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
193
60
  Writer.setOffset(BlockMapOffset);
194
60
  if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
195
0
    return EC;
196
60
197
60
  auto DirStream = WritableMappedBlockStream::createDirectoryStream(
198
60
      Layout, Buffer, Allocator);
199
60
  BinaryStreamWriter DW(*DirStream);
200
60
  if (auto EC = DW.writeInteger<uint32_t>(Layout.StreamSizes.size()))
201
0
    return EC;
202
60
203
60
  
if (auto 60
EC60
= DW.writeArray(Layout.StreamSizes))
204
0
    return EC;
205
60
206
60
  
for (const auto &Blocks : Layout.StreamMap) 60
{
207
781
    if (auto EC = DW.writeArray(Blocks))
208
0
      return EC;
209
60
  }
210
60
211
60
  auto ExpectedSN = getNamedStreamIndex("/names");
212
60
  if (!ExpectedSN)
213
0
    return ExpectedSN.takeError();
214
60
215
60
  auto NS = WritableMappedBlockStream::createIndexedStream(
216
60
      Layout, Buffer, *ExpectedSN, Allocator);
217
60
  BinaryStreamWriter NSWriter(*NS);
218
60
  if (auto EC = Strings.commit(NSWriter))
219
0
    return EC;
220
60
221
60
  
if (60
Info60
) {
222
60
    if (auto EC = Info->commit(Layout, Buffer))
223
0
      return EC;
224
60
  }
225
60
226
60
  
if (60
Dbi60
) {
227
57
    if (auto EC = Dbi->commit(Layout, Buffer))
228
0
      return EC;
229
60
  }
230
60
231
60
  
if (60
Tpi60
) {
232
60
    if (auto EC = Tpi->commit(Layout, Buffer))
233
0
      return EC;
234
60
  }
235
60
236
60
  
if (60
Ipi60
) {
237
60
    if (auto EC = Ipi->commit(Layout, Buffer))
238
0
      return EC;
239
60
  }
240
60
241
60
  
if (60
Gsi60
) {
242
40
    if (auto EC = Gsi->commit(Layout, Buffer))
243
0
      return EC;
244
60
  }
245
60
246
60
  return Buffer.commit();
247
60
}