LLVM  6.0.0svn
PDBFileBuilder.cpp
Go to the documentation of this file.
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 
11 
12 #include "llvm/ADT/BitVector.h"
13 
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  : Allocator(Allocator) {}
36 
38 
40  auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
41  if (!ExpectedMsf)
42  return ExpectedMsf.takeError();
43  Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf));
44  return Error::success();
45 }
46 
48 
50  if (!Info)
51  Info = llvm::make_unique<InfoStreamBuilder>(*Msf, NamedStreams);
52  return *Info;
53 }
54 
56  if (!Dbi)
57  Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf);
58  return *Dbi;
59 }
60 
62  if (!Tpi)
63  Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
64  return *Tpi;
65 }
66 
68  if (!Ipi)
69  Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
70  return *Ipi;
71 }
72 
74  return Strings;
75 }
76 
78  if (!Gsi)
79  Gsi = llvm::make_unique<GSIStreamBuilder>(*Msf);
80  return *Gsi;
81 }
82 
84  auto ExpectedStream = Msf->addStream(Size);
85  if (!ExpectedStream)
86  return ExpectedStream.takeError();
87  NamedStreams.set(Name, *ExpectedStream);
88  return Error::success();
89 }
90 
91 Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
92 
93  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  auto &Info = getInfoBuilder();
99  Info.addFeature(PdbRaw_FeatureSig::VC140);
100  }
101 
102  uint32_t StringsLen = Strings.calculateSerializedSize();
103 
104  if (auto EC = addNamedStream("/names", StringsLen))
105  return std::move(EC);
106  if (auto EC = addNamedStream("/LinkInfo", 0))
107  return std::move(EC);
108 
109  if (Info) {
110  if (auto EC = Info->finalizeMsfLayout())
111  return std::move(EC);
112  }
113  if (Dbi) {
114  if (auto EC = Dbi->finalizeMsfLayout())
115  return std::move(EC);
116  }
117  if (Tpi) {
118  if (auto EC = Tpi->finalizeMsfLayout())
119  return std::move(EC);
120  }
121  if (Ipi) {
122  if (auto EC = Ipi->finalizeMsfLayout())
123  return std::move(EC);
124  }
125  if (Gsi) {
126  if (auto EC = Gsi->finalizeMsfLayout())
127  return std::move(EC);
128  if (Dbi) {
129  Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex());
130  Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex());
131  Dbi->setSymbolRecordStreamIndex(Gsi->getRecordStreamIdx());
132  }
133  }
134 
135  return Msf->build();
136 }
137 
139  uint32_t SN = 0;
140  if (!NamedStreams.get(Name, SN))
141  return llvm::make_error<pdb::RawError>(raw_error_code::no_stream);
142  return SN;
143 }
144 
145 void PDBFileBuilder::commitFpm(WritableBinaryStream &MsfBuffer,
146  const MSFLayout &Layout) {
147  auto FpmStream =
148  WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator);
149 
150  // We only need to create the alt fpm stream so that it gets initialized.
151  WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator,
152  true);
153 
154  uint32_t BI = 0;
155  BinaryStreamWriter FpmWriter(*FpmStream);
156  while (BI < Layout.SB->NumBlocks) {
157  uint8_t ThisByte = 0;
158  for (uint32_t I = 0; I < 8; ++I) {
159  bool IsFree =
160  (BI < Layout.SB->NumBlocks) ? Layout.FreePageMap.test(BI) : true;
161  uint8_t Mask = uint8_t(IsFree) << I;
162  ThisByte |= Mask;
163  ++BI;
164  }
165  cantFail(FpmWriter.writeObject(ThisByte));
166  }
167  assert(FpmWriter.bytesRemaining() == 0);
168 }
169 
171  assert(!Filename.empty());
172  auto ExpectedLayout = finalizeMsfLayout();
173  if (!ExpectedLayout)
174  return ExpectedLayout.takeError();
175  auto &Layout = *ExpectedLayout;
176 
177  uint64_t Filesize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
178  auto OutFileOrError = FileOutputBuffer::create(Filename, Filesize);
179  if (auto E = OutFileOrError.takeError())
180  return E;
181  FileBufferByteStream Buffer(std::move(*OutFileOrError),
183  BinaryStreamWriter Writer(Buffer);
184 
185  if (auto EC = Writer.writeObject(*Layout.SB))
186  return EC;
187 
188  commitFpm(Buffer, Layout);
189 
190  uint32_t BlockMapOffset =
191  msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
192  Writer.setOffset(BlockMapOffset);
193  if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
194  return EC;
195 
196  auto DirStream = WritableMappedBlockStream::createDirectoryStream(
197  Layout, Buffer, Allocator);
198  BinaryStreamWriter DW(*DirStream);
199  if (auto EC = DW.writeInteger<uint32_t>(Layout.StreamSizes.size()))
200  return EC;
201 
202  if (auto EC = DW.writeArray(Layout.StreamSizes))
203  return EC;
204 
205  for (const auto &Blocks : Layout.StreamMap) {
206  if (auto EC = DW.writeArray(Blocks))
207  return EC;
208  }
209 
210  auto ExpectedSN = getNamedStreamIndex("/names");
211  if (!ExpectedSN)
212  return ExpectedSN.takeError();
213 
214  auto NS = WritableMappedBlockStream::createIndexedStream(
215  Layout, Buffer, *ExpectedSN, Allocator);
216  BinaryStreamWriter NSWriter(*NS);
217  if (auto EC = Strings.commit(NSWriter))
218  return EC;
219 
220  if (Info) {
221  if (auto EC = Info->commit(Layout, Buffer))
222  return EC;
223  }
224 
225  if (Dbi) {
226  if (auto EC = Dbi->commit(Layout, Buffer))
227  return EC;
228  }
229 
230  if (Tpi) {
231  if (auto EC = Tpi->commit(Layout, Buffer))
232  return EC;
233  }
234 
235  if (Ipi) {
236  if (auto EC = Ipi->commit(Layout, Buffer))
237  return EC;
238  }
239 
240  if (Gsi) {
241  if (auto EC = Gsi->commit(Layout, Buffer))
242  return EC;
243  }
244 
245  return Buffer.commit();
246 }
Error writeObject(const T &Obj)
Writes the object Obj to the underlying stream, as if by using memcpy.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:688
static Expected< std::unique_ptr< FileOutputBuffer > > create(StringRef FilePath, size_t Size, unsigned Flags=0)
Factory method to create an OutputBuffer object which manages a read/write buffer of the specified si...
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize)
Definition: MSFCommon.h:103
PDBStringTableBuilder & getStringTableBuilder()
bool test(unsigned Idx) const
Definition: BitVector.h:502
void set(StringRef Stream, uint32_t StreamNo)
DbiStreamBuilder & getDbiBuilder()
Error commit(BinaryStreamWriter &Writer) const
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
TpiStreamBuilder & getIpiBuilder()
Error commit(StringRef Filename)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:133
support::ulittle32_t BlockSize
Definition: MSFCommon.h:37
Error writeArray(ArrayRef< T > Array)
Writes an array of objects of type T to the underlying stream, as if by using memcpy.
Error commit() override
For buffered streams, commits changes to the backing store.
support::ulittle32_t BlockMapAddr
Definition: MSFCommon.h:49
Error initialize(uint32_t BlockSize)
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:138
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Provides write only access to a subclass of WritableBinaryStream.
Error writeInteger(T Value)
Write the the integer Value to the underlying stream in the specified endianness. ...
uint32_t bytesRemaining() const
static const int BlockSize
Definition: TarWriter.cpp:34
Basic Register Allocator
static ErrorSuccess success()
Create a success value.
Definition: Error.h:313
ArrayRef< support::ulittle32_t > DirectoryBlocks
Definition: MSFCommon.h:57
GSIStreamBuilder & getGsiBuilder()
InfoStreamBuilder & getInfoBuilder()
BitVector FreePageMap
Definition: MSFCommon.h:56
void setOffset(uint32_t Off)
#define I(x, y, z)
Definition: MD5.cpp:58
std::vector< ArrayRef< support::ulittle32_t > > StreamMap
Definition: MSFCommon.h:59
bool get(StringRef Stream, uint32_t &StreamNo) const
ArrayRef< support::ulittle32_t > StreamSizes
Definition: MSFCommon.h:58
msf::MSFBuilder & getMsfBuilder()
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Error addNamedStream(StringRef Name, uint32_t Size)
constexpr char Size[]
Key for Kernel::Arg::Metadata::mSize.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E&#39;s largest value.
Definition: BitmaskEnum.h:81
An implementation of WritableBinaryStream backed by an llvm FileOutputBuffer.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
const SuperBlock * SB
Definition: MSFCommon.h:55
Expected< uint32_t > getNamedStreamIndex(StringRef Name) const
support::ulittle32_t NumBlocks
Definition: MSFCommon.h:43
TpiStreamBuilder & getTpiBuilder()
A BinaryStream which can be read from as well as written to.
Definition: BinaryStream.h:63