blob: a5c383e5f49e3cc2143aad7c63aeb6cad74e6b42 [file] [log] [blame]
Zachary Turner0a43efe2016-04-25 17:38:08 +00001//===- PDBFile.cpp - Low level interface to a PDB file ----------*- 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/PDBFile.h"
Zachary Turnerd8447992016-06-07 05:28:55 +000011
Zachary Turner0a43efe2016-04-25 17:38:08 +000012#include "llvm/ADT/ArrayRef.h"
Zachary Turnerd8447992016-06-07 05:28:55 +000013#include "llvm/DebugInfo/CodeView/StreamArray.h"
Zachary Turnerb84faa82016-06-10 05:10:19 +000014#include "llvm/DebugInfo/CodeView/StreamInterface.h"
Zachary Turnerd8447992016-06-07 05:28:55 +000015#include "llvm/DebugInfo/CodeView/StreamReader.h"
Zachary Turner2f09b502016-04-29 17:28:47 +000016#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
Zachary Turnera1657a92016-06-08 17:26:39 +000017#include "llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h"
Zachary Turnerd8447992016-06-07 05:28:55 +000018#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
Zachary Turner2f09b502016-04-29 17:28:47 +000019#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
Zachary Turner3df1bfa2016-06-03 05:52:57 +000020#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
Rui Ueyama1f6b6e22016-05-13 21:21:53 +000021#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
Zachary Turner819e77d2016-05-06 20:51:57 +000022#include "llvm/DebugInfo/PDB/Raw/RawError.h"
Rui Ueyama0fcd8262016-05-20 19:55:17 +000023#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h"
Zachary Turnerf5c59652016-05-03 00:28:21 +000024#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
Zachary Turner0a43efe2016-04-25 17:38:08 +000025#include "llvm/Support/Endian.h"
Zachary Turner1dc9fd32016-06-14 20:48:36 +000026#include "llvm/Support/FileOutputBuffer.h"
Zachary Turner0a43efe2016-04-25 17:38:08 +000027#include "llvm/Support/MemoryBuffer.h"
28
29using namespace llvm;
Zachary Turnerb84faa82016-06-10 05:10:19 +000030using namespace llvm::codeview;
Zachary Turner2f09b502016-04-29 17:28:47 +000031using namespace llvm::pdb;
Zachary Turner0a43efe2016-04-25 17:38:08 +000032
33namespace {
Zachary Turnerb84faa82016-06-10 05:10:19 +000034typedef FixedStreamArray<support::ulittle32_t> ulittle_array;
Zachary Turner0a43efe2016-04-25 17:38:08 +000035}
36
Zachary Turnerb84faa82016-06-10 05:10:19 +000037PDBFile::PDBFile(std::unique_ptr<StreamInterface> PdbFileBuffer)
38 : Buffer(std::move(PdbFileBuffer)), SB(nullptr) {}
Zachary Turner0a43efe2016-04-25 17:38:08 +000039
40PDBFile::~PDBFile() {}
41
Zachary Turnerb84faa82016-06-10 05:10:19 +000042uint32_t PDBFile::getBlockSize() const { return SB->BlockSize; }
Zachary Turner0a43efe2016-04-25 17:38:08 +000043
Zachary Turnerb84faa82016-06-10 05:10:19 +000044uint32_t PDBFile::getUnknown0() const { return SB->Unknown0; }
Zachary Turner0a43efe2016-04-25 17:38:08 +000045
Zachary Turnerb84faa82016-06-10 05:10:19 +000046uint32_t PDBFile::getBlockCount() const { return SB->NumBlocks; }
Zachary Turner0a43efe2016-04-25 17:38:08 +000047
Zachary Turnerb84faa82016-06-10 05:10:19 +000048uint32_t PDBFile::getNumDirectoryBytes() const { return SB->NumDirectoryBytes; }
Zachary Turner0a43efe2016-04-25 17:38:08 +000049
Zachary Turnerb84faa82016-06-10 05:10:19 +000050uint32_t PDBFile::getBlockMapIndex() const { return SB->BlockMapAddr; }
Zachary Turner0a43efe2016-04-25 17:38:08 +000051
Zachary Turnerb84faa82016-06-10 05:10:19 +000052uint32_t PDBFile::getUnknown1() const { return SB->Unknown1; }
Zachary Turner0a43efe2016-04-25 17:38:08 +000053
54uint32_t PDBFile::getNumDirectoryBlocks() const {
Zachary Turnerb84faa82016-06-10 05:10:19 +000055 return bytesToBlocks(SB->NumDirectoryBytes, SB->BlockSize);
Zachary Turner0a43efe2016-04-25 17:38:08 +000056}
57
58uint64_t PDBFile::getBlockMapOffset() const {
Zachary Turnerb84faa82016-06-10 05:10:19 +000059 return (uint64_t)SB->BlockMapAddr * SB->BlockSize;
Zachary Turner0a43efe2016-04-25 17:38:08 +000060}
61
Zachary Turnerb84faa82016-06-10 05:10:19 +000062uint32_t PDBFile::getNumStreams() const { return StreamSizes.size(); }
Zachary Turner0a43efe2016-04-25 17:38:08 +000063
64uint32_t PDBFile::getStreamByteSize(uint32_t StreamIndex) const {
Zachary Turnerb84faa82016-06-10 05:10:19 +000065 return StreamSizes[StreamIndex];
Zachary Turner0a43efe2016-04-25 17:38:08 +000066}
67
Zachary Turnerd8447992016-06-07 05:28:55 +000068ArrayRef<support::ulittle32_t>
Zachary Turner0a43efe2016-04-25 17:38:08 +000069PDBFile::getStreamBlockList(uint32_t StreamIndex) const {
Zachary Turnerb84faa82016-06-10 05:10:19 +000070 return StreamMap[StreamIndex];
Zachary Turner0a43efe2016-04-25 17:38:08 +000071}
72
Zachary Turner1dc9fd32016-06-14 20:48:36 +000073size_t PDBFile::getFileSize() const { return Buffer->getLength(); }
74
Zachary Turnere6fee882016-06-07 20:38:37 +000075ArrayRef<uint8_t> PDBFile::getBlockData(uint32_t BlockIndex,
76 uint32_t NumBytes) const {
Zachary Turner0a43efe2016-04-25 17:38:08 +000077 uint64_t StreamBlockOffset = blockToOffset(BlockIndex, getBlockSize());
78
Zachary Turnerb84faa82016-06-10 05:10:19 +000079 ArrayRef<uint8_t> Result;
80 if (auto EC = Buffer->readBytes(StreamBlockOffset, NumBytes, Result))
81 consumeError(std::move(EC));
82 return Result;
Zachary Turner0a43efe2016-04-25 17:38:08 +000083}
84
Zachary Turner5acb4ac2016-06-10 05:09:12 +000085Error PDBFile::setBlockData(uint32_t BlockIndex, uint32_t Offset,
86 ArrayRef<uint8_t> Data) const {
Zachary Turnerb84faa82016-06-10 05:10:19 +000087 if (Offset >= getBlockSize())
88 return make_error<RawError>(
89 raw_error_code::invalid_block_address,
90 "setBlockData attempted to write out of block bounds.");
91 if (Data.size() >= getBlockSize() - Offset)
92 return make_error<RawError>(
93 raw_error_code::invalid_block_address,
94 "setBlockData attempted to write out of block bounds.");
Zachary Turner5acb4ac2016-06-10 05:09:12 +000095
Zachary Turnerb84faa82016-06-10 05:10:19 +000096 uint64_t StreamBlockOffset = blockToOffset(BlockIndex, getBlockSize());
97 StreamBlockOffset += Offset;
98 return Buffer->writeBytes(StreamBlockOffset, Data);
Zachary Turner5acb4ac2016-06-10 05:09:12 +000099}
100
Zachary Turner819e77d2016-05-06 20:51:57 +0000101Error PDBFile::parseFileHeaders() {
Zachary Turnerb84faa82016-06-10 05:10:19 +0000102 StreamReader Reader(*Buffer);
Zachary Turnerc59261c2016-05-25 03:53:16 +0000103
Zachary Turnerb84faa82016-06-10 05:10:19 +0000104 if (auto EC = Reader.readObject(SB)) {
105 consumeError(std::move(EC));
Zachary Turner819e77d2016-05-06 20:51:57 +0000106 return make_error<RawError>(raw_error_code::corrupt_file,
107 "Does not contain superblock");
Zachary Turnerb84faa82016-06-10 05:10:19 +0000108 }
Zachary Turner0a43efe2016-04-25 17:38:08 +0000109
Zachary Turner819e77d2016-05-06 20:51:57 +0000110 // Check the magic bytes.
Zachary Turnerb84faa82016-06-10 05:10:19 +0000111 if (memcmp(SB->MagicBytes, MsfMagic, sizeof(MsfMagic)) != 0)
Zachary Turner819e77d2016-05-06 20:51:57 +0000112 return make_error<RawError>(raw_error_code::corrupt_file,
113 "MSF magic header doesn't match");
114
David Majnemer878cadb2016-05-27 15:57:38 +0000115 // We don't support blocksizes which aren't a multiple of four bytes.
116 if (SB->BlockSize % sizeof(support::ulittle32_t) != 0)
Zachary Turner819e77d2016-05-06 20:51:57 +0000117 return make_error<RawError>(raw_error_code::corrupt_file,
David Majnemer878cadb2016-05-27 15:57:38 +0000118 "Block size is not multiple of 4.");
Zachary Turner819e77d2016-05-06 20:51:57 +0000119
Zachary Turner9213ba52016-04-29 18:09:19 +0000120 switch (SB->BlockSize) {
121 case 512: case 1024: case 2048: case 4096:
122 break;
123 default:
124 // An invalid block size suggests a corrupt PDB file.
Zachary Turner819e77d2016-05-06 20:51:57 +0000125 return make_error<RawError>(raw_error_code::corrupt_file,
126 "Unsupported block size.");
Zachary Turner9213ba52016-04-29 18:09:19 +0000127 }
Zachary Turner0a43efe2016-04-25 17:38:08 +0000128
Zachary Turnerb84faa82016-06-10 05:10:19 +0000129 if (Buffer->getLength() % SB->BlockSize != 0)
Zachary Turner819e77d2016-05-06 20:51:57 +0000130 return make_error<RawError>(raw_error_code::corrupt_file,
David Majnemer878cadb2016-05-27 15:57:38 +0000131 "File size is not a multiple of block size");
Zachary Turner0a43efe2016-04-25 17:38:08 +0000132
133 // We don't support directories whose sizes aren't a multiple of four bytes.
134 if (SB->NumDirectoryBytes % sizeof(support::ulittle32_t) != 0)
Zachary Turner819e77d2016-05-06 20:51:57 +0000135 return make_error<RawError>(raw_error_code::corrupt_file,
136 "Directory size is not multiple of 4.");
Zachary Turner0a43efe2016-04-25 17:38:08 +0000137
138 // The number of blocks which comprise the directory is a simple function of
139 // the number of bytes it contains.
140 uint64_t NumDirectoryBlocks = getNumDirectoryBlocks();
141
Zachary Turnerb84faa82016-06-10 05:10:19 +0000142 // The directory, as we understand it, is a block which consists of a list of
143 // block numbers. It is unclear what would happen if the number of blocks
144 // couldn't fit on a single block.
Zachary Turner0a43efe2016-04-25 17:38:08 +0000145 if (NumDirectoryBlocks > SB->BlockSize / sizeof(support::ulittle32_t))
Zachary Turner819e77d2016-05-06 20:51:57 +0000146 return make_error<RawError>(raw_error_code::corrupt_file,
147 "Too many directory blocks.");
Zachary Turner0a43efe2016-04-25 17:38:08 +0000148
Zachary Turner819e77d2016-05-06 20:51:57 +0000149 return Error::success();
Zachary Turner0a43efe2016-04-25 17:38:08 +0000150}
151
Zachary Turner819e77d2016-05-06 20:51:57 +0000152Error PDBFile::parseStreamData() {
Zachary Turnerb84faa82016-06-10 05:10:19 +0000153 assert(SB);
Zachary Turnerd8447992016-06-07 05:28:55 +0000154 if (DirectoryStream)
155 return Error::success();
Zachary Turner0a43efe2016-04-25 17:38:08 +0000156
Zachary Turner0a43efe2016-04-25 17:38:08 +0000157 uint32_t NumStreams = 0;
Zachary Turner0a43efe2016-04-25 17:38:08 +0000158
Zachary Turnerd8447992016-06-07 05:28:55 +0000159 // Normally you can't use a MappedBlockStream without having fully parsed the
160 // PDB file, because it accesses the directory and various other things, which
161 // is exactly what we are attempting to parse. By specifying a custom
162 // subclass of IPDBStreamData which only accesses the fields that have already
163 // been parsed, we can avoid this and reuse MappedBlockStream.
Zachary Turnera1657a92016-06-08 17:26:39 +0000164 auto DS = MappedBlockStream::createDirectoryStream(*this);
165 if (!DS)
166 return DS.takeError();
Zachary Turnerb84faa82016-06-10 05:10:19 +0000167 StreamReader Reader(**DS);
Zachary Turnerd8447992016-06-07 05:28:55 +0000168 if (auto EC = Reader.readInteger(NumStreams))
169 return EC;
Zachary Turner0a43efe2016-04-25 17:38:08 +0000170
Zachary Turnerb84faa82016-06-10 05:10:19 +0000171 if (auto EC = Reader.readArray(StreamSizes, NumStreams))
Zachary Turnerd8447992016-06-07 05:28:55 +0000172 return EC;
173 for (uint32_t I = 0; I < NumStreams; ++I) {
David Majnemer9efba742016-05-27 16:16:48 +0000174 uint64_t NumExpectedStreamBlocks =
Zachary Turnerd8447992016-06-07 05:28:55 +0000175 bytesToBlocks(getStreamByteSize(I), SB->BlockSize);
Zachary Turnerb84faa82016-06-10 05:10:19 +0000176
177 // For convenience, we store the block array contiguously. This is because
178 // if someone calls setStreamMap(), it is more convenient to be able to call
179 // it with an ArrayRef instead of setting up a StreamRef. Since the
180 // DirectoryStream is cached in the class and thus lives for the life of the
181 // class, we can be guaranteed that readArray() will return a stable
182 // reference, even if it has to allocate from its internal pool.
183 ArrayRef<support::ulittle32_t> Blocks;
Zachary Turnerd8447992016-06-07 05:28:55 +0000184 if (auto EC = Reader.readArray(Blocks, NumExpectedStreamBlocks))
185 return EC;
Zachary Turnerb84faa82016-06-10 05:10:19 +0000186 StreamMap.push_back(Blocks);
David Majnemer9efba742016-05-27 16:16:48 +0000187 }
188
Zachary Turner0a43efe2016-04-25 17:38:08 +0000189 // We should have read exactly SB->NumDirectoryBytes bytes.
Zachary Turnerd8447992016-06-07 05:28:55 +0000190 assert(Reader.bytesRemaining() == 0);
Zachary Turnera1657a92016-06-08 17:26:39 +0000191 DirectoryStream = std::move(*DS);
Zachary Turner819e77d2016-05-06 20:51:57 +0000192 return Error::success();
Zachary Turner0a43efe2016-04-25 17:38:08 +0000193}
194
Zachary Turnerd8447992016-06-07 05:28:55 +0000195llvm::ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {
Zachary Turnerb84faa82016-06-10 05:10:19 +0000196 StreamReader Reader(*Buffer);
197 Reader.setOffset(getBlockMapOffset());
198 llvm::ArrayRef<support::ulittle32_t> Result;
199 if (auto EC = Reader.readArray(Result, getNumDirectoryBlocks()))
200 consumeError(std::move(EC));
201 return Result;
Zachary Turner0a43efe2016-04-25 17:38:08 +0000202}
Zachary Turner53a65ba2016-04-26 18:42:34 +0000203
Zachary Turner819e77d2016-05-06 20:51:57 +0000204Expected<InfoStream &> PDBFile::getPDBInfoStream() {
Zachary Turner2f09b502016-04-29 17:28:47 +0000205 if (!Info) {
Zachary Turnera1657a92016-06-08 17:26:39 +0000206 auto InfoS = MappedBlockStream::createIndexedStream(StreamPDB, *this);
207 if (!InfoS)
208 return InfoS.takeError();
209 auto TempInfo = llvm::make_unique<InfoStream>(std::move(*InfoS));
210 if (auto EC = TempInfo->reload())
Zachary Turner819e77d2016-05-06 20:51:57 +0000211 return std::move(EC);
Zachary Turnera1657a92016-06-08 17:26:39 +0000212 Info = std::move(TempInfo);
Zachary Turner53a65ba2016-04-26 18:42:34 +0000213 }
Zachary Turner2f09b502016-04-29 17:28:47 +0000214 return *Info;
Zachary Turner53a65ba2016-04-26 18:42:34 +0000215}
216
Zachary Turner819e77d2016-05-06 20:51:57 +0000217Expected<DbiStream &> PDBFile::getPDBDbiStream() {
Zachary Turner2f09b502016-04-29 17:28:47 +0000218 if (!Dbi) {
Zachary Turnera1657a92016-06-08 17:26:39 +0000219 auto DbiS = MappedBlockStream::createIndexedStream(StreamDBI, *this);
220 if (!DbiS)
221 return DbiS.takeError();
222 auto TempDbi = llvm::make_unique<DbiStream>(*this, std::move(*DbiS));
223 if (auto EC = TempDbi->reload())
Zachary Turner819e77d2016-05-06 20:51:57 +0000224 return std::move(EC);
Zachary Turnera1657a92016-06-08 17:26:39 +0000225 Dbi = std::move(TempDbi);
Zachary Turner53a65ba2016-04-26 18:42:34 +0000226 }
Zachary Turner2f09b502016-04-29 17:28:47 +0000227 return *Dbi;
Zachary Turner53a65ba2016-04-26 18:42:34 +0000228}
Zachary Turnerf5c59652016-05-03 00:28:21 +0000229
Zachary Turner819e77d2016-05-06 20:51:57 +0000230Expected<TpiStream &> PDBFile::getPDBTpiStream() {
Zachary Turnerf5c59652016-05-03 00:28:21 +0000231 if (!Tpi) {
Zachary Turnera1657a92016-06-08 17:26:39 +0000232 auto TpiS = MappedBlockStream::createIndexedStream(StreamTPI, *this);
233 if (!TpiS)
234 return TpiS.takeError();
235 auto TempTpi = llvm::make_unique<TpiStream>(*this, std::move(*TpiS));
236 if (auto EC = TempTpi->reload())
Zachary Turner819e77d2016-05-06 20:51:57 +0000237 return std::move(EC);
Zachary Turnera1657a92016-06-08 17:26:39 +0000238 Tpi = std::move(TempTpi);
Zachary Turnerf5c59652016-05-03 00:28:21 +0000239 }
240 return *Tpi;
241}
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000242
Zachary Turnerc9972c62016-05-25 04:35:22 +0000243Expected<TpiStream &> PDBFile::getPDBIpiStream() {
244 if (!Ipi) {
Zachary Turnera1657a92016-06-08 17:26:39 +0000245 auto IpiS = MappedBlockStream::createIndexedStream(StreamIPI, *this);
246 if (!IpiS)
247 return IpiS.takeError();
248 auto TempIpi = llvm::make_unique<TpiStream>(*this, std::move(*IpiS));
249 if (auto EC = TempIpi->reload())
Zachary Turnerc9972c62016-05-25 04:35:22 +0000250 return std::move(EC);
Zachary Turnera1657a92016-06-08 17:26:39 +0000251 Ipi = std::move(TempIpi);
Zachary Turnerc9972c62016-05-25 04:35:22 +0000252 }
253 return *Ipi;
254}
255
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000256Expected<PublicsStream &> PDBFile::getPDBPublicsStream() {
257 if (!Publics) {
258 auto DbiS = getPDBDbiStream();
Zachary Turnera1657a92016-06-08 17:26:39 +0000259 if (!DbiS)
260 return DbiS.takeError();
261
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000262 uint32_t PublicsStreamNum = DbiS->getPublicSymbolStreamIndex();
263
Zachary Turnera1657a92016-06-08 17:26:39 +0000264 auto PublicS =
265 MappedBlockStream::createIndexedStream(PublicsStreamNum, *this);
266 if (!PublicS)
267 return PublicS.takeError();
268 auto TempPublics =
269 llvm::make_unique<PublicsStream>(*this, std::move(*PublicS));
270 if (auto EC = TempPublics->reload())
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000271 return std::move(EC);
Zachary Turnera1657a92016-06-08 17:26:39 +0000272 Publics = std::move(TempPublics);
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000273 }
274 return *Publics;
275}
Rui Ueyama0fcd8262016-05-20 19:55:17 +0000276
277Expected<SymbolStream &> PDBFile::getPDBSymbolStream() {
278 if (!Symbols) {
279 auto DbiS = getPDBDbiStream();
Zachary Turnera1657a92016-06-08 17:26:39 +0000280 if (!DbiS)
281 return DbiS.takeError();
282
Rui Ueyama0fcd8262016-05-20 19:55:17 +0000283 uint32_t SymbolStreamNum = DbiS->getSymRecordStreamIndex();
284
Zachary Turnera1657a92016-06-08 17:26:39 +0000285 auto SymbolS =
286 MappedBlockStream::createIndexedStream(SymbolStreamNum, *this);
287 if (!SymbolS)
288 return SymbolS.takeError();
289 auto TempSymbols = llvm::make_unique<SymbolStream>(std::move(*SymbolS));
290 if (auto EC = TempSymbols->reload())
Rui Ueyama0fcd8262016-05-20 19:55:17 +0000291 return std::move(EC);
Zachary Turnera1657a92016-06-08 17:26:39 +0000292 Symbols = std::move(TempSymbols);
Rui Ueyama0fcd8262016-05-20 19:55:17 +0000293 }
294 return *Symbols;
295}
Zachary Turner3df1bfa2016-06-03 05:52:57 +0000296
297Expected<NameHashTable &> PDBFile::getStringTable() {
298 if (!StringTable || !StringTableStream) {
Zachary Turnera1657a92016-06-08 17:26:39 +0000299 auto IS = getPDBInfoStream();
300 if (!IS)
301 return IS.takeError();
302
303 uint32_t NameStreamIndex = IS->getNamedStreamIndex("/names");
Zachary Turner3df1bfa2016-06-03 05:52:57 +0000304
305 if (NameStreamIndex == 0)
306 return make_error<RawError>(raw_error_code::no_stream);
Zachary Turnerd2b2bfe2016-06-08 00:25:08 +0000307 if (NameStreamIndex >= getNumStreams())
308 return make_error<RawError>(raw_error_code::no_stream);
309
Zachary Turnera1657a92016-06-08 17:26:39 +0000310 auto NS = MappedBlockStream::createIndexedStream(NameStreamIndex, *this);
311 if (!NS)
312 return NS.takeError();
313
Zachary Turnerb84faa82016-06-10 05:10:19 +0000314 StreamReader Reader(**NS);
Zachary Turner3df1bfa2016-06-03 05:52:57 +0000315 auto N = llvm::make_unique<NameHashTable>();
316 if (auto EC = N->load(Reader))
317 return std::move(EC);
318 StringTable = std::move(N);
Zachary Turnera1657a92016-06-08 17:26:39 +0000319 StringTableStream = std::move(*NS);
Zachary Turner3df1bfa2016-06-03 05:52:57 +0000320 }
321 return *StringTable;
322}
Zachary Turner1dc9fd32016-06-14 20:48:36 +0000323
324void PDBFile::setSuperBlock(const SuperBlock *Block) { SB = Block; }
325
326void PDBFile::setStreamSizes(ArrayRef<support::ulittle32_t> Sizes) {
327 StreamSizes = Sizes;
328}
329
330void PDBFile::setStreamMap(ArrayRef<ArrayRef<support::ulittle32_t>> Blocks) {
331 StreamMap = Blocks;
332}
333
334void PDBFile::commit() {}