1*9880d681SAndroid Build Coastguard Worker //===- PDBFile.cpp - Low level interface to a PDB file ----------*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
11*9880d681SAndroid Build Coastguard Worker
12*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/ArrayRef.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/StreamArray.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/StreamInterface.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/StreamReader.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/CodeView/StreamWriter.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/RawError.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/SymbolStream.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Endian.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FileOutputBuffer.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Worker using namespace llvm;
31*9880d681SAndroid Build Coastguard Worker using namespace llvm::codeview;
32*9880d681SAndroid Build Coastguard Worker using namespace llvm::pdb;
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker namespace {
35*9880d681SAndroid Build Coastguard Worker typedef FixedStreamArray<support::ulittle32_t> ulittle_array;
36*9880d681SAndroid Build Coastguard Worker }
37*9880d681SAndroid Build Coastguard Worker
PDBFile(std::unique_ptr<StreamInterface> PdbFileBuffer)38*9880d681SAndroid Build Coastguard Worker PDBFile::PDBFile(std::unique_ptr<StreamInterface> PdbFileBuffer)
39*9880d681SAndroid Build Coastguard Worker : Buffer(std::move(PdbFileBuffer)), SB(nullptr) {}
40*9880d681SAndroid Build Coastguard Worker
~PDBFile()41*9880d681SAndroid Build Coastguard Worker PDBFile::~PDBFile() {}
42*9880d681SAndroid Build Coastguard Worker
getBlockSize() const43*9880d681SAndroid Build Coastguard Worker uint32_t PDBFile::getBlockSize() const { return SB->BlockSize; }
44*9880d681SAndroid Build Coastguard Worker
getUnknown0() const45*9880d681SAndroid Build Coastguard Worker uint32_t PDBFile::getUnknown0() const { return SB->Unknown0; }
46*9880d681SAndroid Build Coastguard Worker
getBlockCount() const47*9880d681SAndroid Build Coastguard Worker uint32_t PDBFile::getBlockCount() const { return SB->NumBlocks; }
48*9880d681SAndroid Build Coastguard Worker
getNumDirectoryBytes() const49*9880d681SAndroid Build Coastguard Worker uint32_t PDBFile::getNumDirectoryBytes() const { return SB->NumDirectoryBytes; }
50*9880d681SAndroid Build Coastguard Worker
getBlockMapIndex() const51*9880d681SAndroid Build Coastguard Worker uint32_t PDBFile::getBlockMapIndex() const { return SB->BlockMapAddr; }
52*9880d681SAndroid Build Coastguard Worker
getUnknown1() const53*9880d681SAndroid Build Coastguard Worker uint32_t PDBFile::getUnknown1() const { return SB->Unknown1; }
54*9880d681SAndroid Build Coastguard Worker
getNumDirectoryBlocks() const55*9880d681SAndroid Build Coastguard Worker uint32_t PDBFile::getNumDirectoryBlocks() const {
56*9880d681SAndroid Build Coastguard Worker return bytesToBlocks(SB->NumDirectoryBytes, SB->BlockSize);
57*9880d681SAndroid Build Coastguard Worker }
58*9880d681SAndroid Build Coastguard Worker
getBlockMapOffset() const59*9880d681SAndroid Build Coastguard Worker uint64_t PDBFile::getBlockMapOffset() const {
60*9880d681SAndroid Build Coastguard Worker return (uint64_t)SB->BlockMapAddr * SB->BlockSize;
61*9880d681SAndroid Build Coastguard Worker }
62*9880d681SAndroid Build Coastguard Worker
getNumStreams() const63*9880d681SAndroid Build Coastguard Worker uint32_t PDBFile::getNumStreams() const { return StreamSizes.size(); }
64*9880d681SAndroid Build Coastguard Worker
getStreamByteSize(uint32_t StreamIndex) const65*9880d681SAndroid Build Coastguard Worker uint32_t PDBFile::getStreamByteSize(uint32_t StreamIndex) const {
66*9880d681SAndroid Build Coastguard Worker return StreamSizes[StreamIndex];
67*9880d681SAndroid Build Coastguard Worker }
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker ArrayRef<support::ulittle32_t>
getStreamBlockList(uint32_t StreamIndex) const70*9880d681SAndroid Build Coastguard Worker PDBFile::getStreamBlockList(uint32_t StreamIndex) const {
71*9880d681SAndroid Build Coastguard Worker return StreamMap[StreamIndex];
72*9880d681SAndroid Build Coastguard Worker }
73*9880d681SAndroid Build Coastguard Worker
getFileSize() const74*9880d681SAndroid Build Coastguard Worker uint32_t PDBFile::getFileSize() const { return Buffer->getLength(); }
75*9880d681SAndroid Build Coastguard Worker
getBlockData(uint32_t BlockIndex,uint32_t NumBytes) const76*9880d681SAndroid Build Coastguard Worker Expected<ArrayRef<uint8_t>> PDBFile::getBlockData(uint32_t BlockIndex,
77*9880d681SAndroid Build Coastguard Worker uint32_t NumBytes) const {
78*9880d681SAndroid Build Coastguard Worker uint64_t StreamBlockOffset = blockToOffset(BlockIndex, getBlockSize());
79*9880d681SAndroid Build Coastguard Worker
80*9880d681SAndroid Build Coastguard Worker ArrayRef<uint8_t> Result;
81*9880d681SAndroid Build Coastguard Worker if (auto EC = Buffer->readBytes(StreamBlockOffset, NumBytes, Result))
82*9880d681SAndroid Build Coastguard Worker return std::move(EC);
83*9880d681SAndroid Build Coastguard Worker return Result;
84*9880d681SAndroid Build Coastguard Worker }
85*9880d681SAndroid Build Coastguard Worker
setBlockData(uint32_t BlockIndex,uint32_t Offset,ArrayRef<uint8_t> Data) const86*9880d681SAndroid Build Coastguard Worker Error PDBFile::setBlockData(uint32_t BlockIndex, uint32_t Offset,
87*9880d681SAndroid Build Coastguard Worker ArrayRef<uint8_t> Data) const {
88*9880d681SAndroid Build Coastguard Worker if (Offset >= getBlockSize())
89*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(
90*9880d681SAndroid Build Coastguard Worker raw_error_code::invalid_block_address,
91*9880d681SAndroid Build Coastguard Worker "setBlockData attempted to write out of block bounds.");
92*9880d681SAndroid Build Coastguard Worker if (Data.size() > getBlockSize() - Offset)
93*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(
94*9880d681SAndroid Build Coastguard Worker raw_error_code::invalid_block_address,
95*9880d681SAndroid Build Coastguard Worker "setBlockData attempted to write out of block bounds.");
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Worker uint64_t StreamBlockOffset = blockToOffset(BlockIndex, getBlockSize());
98*9880d681SAndroid Build Coastguard Worker StreamBlockOffset += Offset;
99*9880d681SAndroid Build Coastguard Worker return Buffer->writeBytes(StreamBlockOffset, Data);
100*9880d681SAndroid Build Coastguard Worker }
101*9880d681SAndroid Build Coastguard Worker
parseFileHeaders()102*9880d681SAndroid Build Coastguard Worker Error PDBFile::parseFileHeaders() {
103*9880d681SAndroid Build Coastguard Worker StreamReader Reader(*Buffer);
104*9880d681SAndroid Build Coastguard Worker
105*9880d681SAndroid Build Coastguard Worker if (auto EC = Reader.readObject(SB)) {
106*9880d681SAndroid Build Coastguard Worker consumeError(std::move(EC));
107*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::corrupt_file,
108*9880d681SAndroid Build Coastguard Worker "Does not contain superblock");
109*9880d681SAndroid Build Coastguard Worker }
110*9880d681SAndroid Build Coastguard Worker
111*9880d681SAndroid Build Coastguard Worker if (auto EC = setSuperBlock(SB))
112*9880d681SAndroid Build Coastguard Worker return EC;
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker Reader.setOffset(getBlockMapOffset());
115*9880d681SAndroid Build Coastguard Worker if (auto EC = Reader.readArray(DirectoryBlocks, getNumDirectoryBlocks()))
116*9880d681SAndroid Build Coastguard Worker return EC;
117*9880d681SAndroid Build Coastguard Worker
118*9880d681SAndroid Build Coastguard Worker return Error::success();
119*9880d681SAndroid Build Coastguard Worker }
120*9880d681SAndroid Build Coastguard Worker
parseStreamData()121*9880d681SAndroid Build Coastguard Worker Error PDBFile::parseStreamData() {
122*9880d681SAndroid Build Coastguard Worker assert(SB);
123*9880d681SAndroid Build Coastguard Worker if (DirectoryStream)
124*9880d681SAndroid Build Coastguard Worker return Error::success();
125*9880d681SAndroid Build Coastguard Worker
126*9880d681SAndroid Build Coastguard Worker uint32_t NumStreams = 0;
127*9880d681SAndroid Build Coastguard Worker
128*9880d681SAndroid Build Coastguard Worker // Normally you can't use a MappedBlockStream without having fully parsed the
129*9880d681SAndroid Build Coastguard Worker // PDB file, because it accesses the directory and various other things, which
130*9880d681SAndroid Build Coastguard Worker // is exactly what we are attempting to parse. By specifying a custom
131*9880d681SAndroid Build Coastguard Worker // subclass of IPDBStreamData which only accesses the fields that have already
132*9880d681SAndroid Build Coastguard Worker // been parsed, we can avoid this and reuse MappedBlockStream.
133*9880d681SAndroid Build Coastguard Worker auto DS = MappedBlockStream::createDirectoryStream(*this);
134*9880d681SAndroid Build Coastguard Worker if (!DS)
135*9880d681SAndroid Build Coastguard Worker return DS.takeError();
136*9880d681SAndroid Build Coastguard Worker StreamReader Reader(**DS);
137*9880d681SAndroid Build Coastguard Worker if (auto EC = Reader.readInteger(NumStreams))
138*9880d681SAndroid Build Coastguard Worker return EC;
139*9880d681SAndroid Build Coastguard Worker
140*9880d681SAndroid Build Coastguard Worker if (auto EC = Reader.readArray(StreamSizes, NumStreams))
141*9880d681SAndroid Build Coastguard Worker return EC;
142*9880d681SAndroid Build Coastguard Worker for (uint32_t I = 0; I < NumStreams; ++I) {
143*9880d681SAndroid Build Coastguard Worker uint32_t StreamSize = getStreamByteSize(I);
144*9880d681SAndroid Build Coastguard Worker // FIXME: What does StreamSize ~0U mean?
145*9880d681SAndroid Build Coastguard Worker uint64_t NumExpectedStreamBlocks =
146*9880d681SAndroid Build Coastguard Worker StreamSize == UINT32_MAX ? 0 : bytesToBlocks(StreamSize, SB->BlockSize);
147*9880d681SAndroid Build Coastguard Worker
148*9880d681SAndroid Build Coastguard Worker // For convenience, we store the block array contiguously. This is because
149*9880d681SAndroid Build Coastguard Worker // if someone calls setStreamMap(), it is more convenient to be able to call
150*9880d681SAndroid Build Coastguard Worker // it with an ArrayRef instead of setting up a StreamRef. Since the
151*9880d681SAndroid Build Coastguard Worker // DirectoryStream is cached in the class and thus lives for the life of the
152*9880d681SAndroid Build Coastguard Worker // class, we can be guaranteed that readArray() will return a stable
153*9880d681SAndroid Build Coastguard Worker // reference, even if it has to allocate from its internal pool.
154*9880d681SAndroid Build Coastguard Worker ArrayRef<support::ulittle32_t> Blocks;
155*9880d681SAndroid Build Coastguard Worker if (auto EC = Reader.readArray(Blocks, NumExpectedStreamBlocks))
156*9880d681SAndroid Build Coastguard Worker return EC;
157*9880d681SAndroid Build Coastguard Worker for (uint32_t Block : Blocks) {
158*9880d681SAndroid Build Coastguard Worker uint64_t BlockEndOffset = (uint64_t)(Block + 1) * SB->BlockSize;
159*9880d681SAndroid Build Coastguard Worker if (BlockEndOffset > getFileSize())
160*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::corrupt_file,
161*9880d681SAndroid Build Coastguard Worker "Stream block map is corrupt.");
162*9880d681SAndroid Build Coastguard Worker }
163*9880d681SAndroid Build Coastguard Worker StreamMap.push_back(Blocks);
164*9880d681SAndroid Build Coastguard Worker }
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Worker // We should have read exactly SB->NumDirectoryBytes bytes.
167*9880d681SAndroid Build Coastguard Worker assert(Reader.bytesRemaining() == 0);
168*9880d681SAndroid Build Coastguard Worker DirectoryStream = std::move(*DS);
169*9880d681SAndroid Build Coastguard Worker return Error::success();
170*9880d681SAndroid Build Coastguard Worker }
171*9880d681SAndroid Build Coastguard Worker
getDirectoryBlockArray() const172*9880d681SAndroid Build Coastguard Worker llvm::ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {
173*9880d681SAndroid Build Coastguard Worker return DirectoryBlocks;
174*9880d681SAndroid Build Coastguard Worker }
175*9880d681SAndroid Build Coastguard Worker
getPDBInfoStream()176*9880d681SAndroid Build Coastguard Worker Expected<InfoStream &> PDBFile::getPDBInfoStream() {
177*9880d681SAndroid Build Coastguard Worker if (!Info) {
178*9880d681SAndroid Build Coastguard Worker auto InfoS = MappedBlockStream::createIndexedStream(StreamPDB, *this);
179*9880d681SAndroid Build Coastguard Worker if (!InfoS)
180*9880d681SAndroid Build Coastguard Worker return InfoS.takeError();
181*9880d681SAndroid Build Coastguard Worker auto TempInfo = llvm::make_unique<InfoStream>(std::move(*InfoS));
182*9880d681SAndroid Build Coastguard Worker if (auto EC = TempInfo->reload())
183*9880d681SAndroid Build Coastguard Worker return std::move(EC);
184*9880d681SAndroid Build Coastguard Worker Info = std::move(TempInfo);
185*9880d681SAndroid Build Coastguard Worker }
186*9880d681SAndroid Build Coastguard Worker return *Info;
187*9880d681SAndroid Build Coastguard Worker }
188*9880d681SAndroid Build Coastguard Worker
getPDBDbiStream()189*9880d681SAndroid Build Coastguard Worker Expected<DbiStream &> PDBFile::getPDBDbiStream() {
190*9880d681SAndroid Build Coastguard Worker if (!Dbi) {
191*9880d681SAndroid Build Coastguard Worker auto DbiS = MappedBlockStream::createIndexedStream(StreamDBI, *this);
192*9880d681SAndroid Build Coastguard Worker if (!DbiS)
193*9880d681SAndroid Build Coastguard Worker return DbiS.takeError();
194*9880d681SAndroid Build Coastguard Worker auto TempDbi = llvm::make_unique<DbiStream>(*this, std::move(*DbiS));
195*9880d681SAndroid Build Coastguard Worker if (auto EC = TempDbi->reload())
196*9880d681SAndroid Build Coastguard Worker return std::move(EC);
197*9880d681SAndroid Build Coastguard Worker Dbi = std::move(TempDbi);
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker return *Dbi;
200*9880d681SAndroid Build Coastguard Worker }
201*9880d681SAndroid Build Coastguard Worker
getPDBTpiStream()202*9880d681SAndroid Build Coastguard Worker Expected<TpiStream &> PDBFile::getPDBTpiStream() {
203*9880d681SAndroid Build Coastguard Worker if (!Tpi) {
204*9880d681SAndroid Build Coastguard Worker auto TpiS = MappedBlockStream::createIndexedStream(StreamTPI, *this);
205*9880d681SAndroid Build Coastguard Worker if (!TpiS)
206*9880d681SAndroid Build Coastguard Worker return TpiS.takeError();
207*9880d681SAndroid Build Coastguard Worker auto TempTpi = llvm::make_unique<TpiStream>(*this, std::move(*TpiS));
208*9880d681SAndroid Build Coastguard Worker if (auto EC = TempTpi->reload())
209*9880d681SAndroid Build Coastguard Worker return std::move(EC);
210*9880d681SAndroid Build Coastguard Worker Tpi = std::move(TempTpi);
211*9880d681SAndroid Build Coastguard Worker }
212*9880d681SAndroid Build Coastguard Worker return *Tpi;
213*9880d681SAndroid Build Coastguard Worker }
214*9880d681SAndroid Build Coastguard Worker
getPDBIpiStream()215*9880d681SAndroid Build Coastguard Worker Expected<TpiStream &> PDBFile::getPDBIpiStream() {
216*9880d681SAndroid Build Coastguard Worker if (!Ipi) {
217*9880d681SAndroid Build Coastguard Worker auto IpiS = MappedBlockStream::createIndexedStream(StreamIPI, *this);
218*9880d681SAndroid Build Coastguard Worker if (!IpiS)
219*9880d681SAndroid Build Coastguard Worker return IpiS.takeError();
220*9880d681SAndroid Build Coastguard Worker auto TempIpi = llvm::make_unique<TpiStream>(*this, std::move(*IpiS));
221*9880d681SAndroid Build Coastguard Worker if (auto EC = TempIpi->reload())
222*9880d681SAndroid Build Coastguard Worker return std::move(EC);
223*9880d681SAndroid Build Coastguard Worker Ipi = std::move(TempIpi);
224*9880d681SAndroid Build Coastguard Worker }
225*9880d681SAndroid Build Coastguard Worker return *Ipi;
226*9880d681SAndroid Build Coastguard Worker }
227*9880d681SAndroid Build Coastguard Worker
getPDBPublicsStream()228*9880d681SAndroid Build Coastguard Worker Expected<PublicsStream &> PDBFile::getPDBPublicsStream() {
229*9880d681SAndroid Build Coastguard Worker if (!Publics) {
230*9880d681SAndroid Build Coastguard Worker auto DbiS = getPDBDbiStream();
231*9880d681SAndroid Build Coastguard Worker if (!DbiS)
232*9880d681SAndroid Build Coastguard Worker return DbiS.takeError();
233*9880d681SAndroid Build Coastguard Worker
234*9880d681SAndroid Build Coastguard Worker uint32_t PublicsStreamNum = DbiS->getPublicSymbolStreamIndex();
235*9880d681SAndroid Build Coastguard Worker
236*9880d681SAndroid Build Coastguard Worker auto PublicS =
237*9880d681SAndroid Build Coastguard Worker MappedBlockStream::createIndexedStream(PublicsStreamNum, *this);
238*9880d681SAndroid Build Coastguard Worker if (!PublicS)
239*9880d681SAndroid Build Coastguard Worker return PublicS.takeError();
240*9880d681SAndroid Build Coastguard Worker auto TempPublics =
241*9880d681SAndroid Build Coastguard Worker llvm::make_unique<PublicsStream>(*this, std::move(*PublicS));
242*9880d681SAndroid Build Coastguard Worker if (auto EC = TempPublics->reload())
243*9880d681SAndroid Build Coastguard Worker return std::move(EC);
244*9880d681SAndroid Build Coastguard Worker Publics = std::move(TempPublics);
245*9880d681SAndroid Build Coastguard Worker }
246*9880d681SAndroid Build Coastguard Worker return *Publics;
247*9880d681SAndroid Build Coastguard Worker }
248*9880d681SAndroid Build Coastguard Worker
getPDBSymbolStream()249*9880d681SAndroid Build Coastguard Worker Expected<SymbolStream &> PDBFile::getPDBSymbolStream() {
250*9880d681SAndroid Build Coastguard Worker if (!Symbols) {
251*9880d681SAndroid Build Coastguard Worker auto DbiS = getPDBDbiStream();
252*9880d681SAndroid Build Coastguard Worker if (!DbiS)
253*9880d681SAndroid Build Coastguard Worker return DbiS.takeError();
254*9880d681SAndroid Build Coastguard Worker
255*9880d681SAndroid Build Coastguard Worker uint32_t SymbolStreamNum = DbiS->getSymRecordStreamIndex();
256*9880d681SAndroid Build Coastguard Worker
257*9880d681SAndroid Build Coastguard Worker auto SymbolS =
258*9880d681SAndroid Build Coastguard Worker MappedBlockStream::createIndexedStream(SymbolStreamNum, *this);
259*9880d681SAndroid Build Coastguard Worker if (!SymbolS)
260*9880d681SAndroid Build Coastguard Worker return SymbolS.takeError();
261*9880d681SAndroid Build Coastguard Worker auto TempSymbols = llvm::make_unique<SymbolStream>(std::move(*SymbolS));
262*9880d681SAndroid Build Coastguard Worker if (auto EC = TempSymbols->reload())
263*9880d681SAndroid Build Coastguard Worker return std::move(EC);
264*9880d681SAndroid Build Coastguard Worker Symbols = std::move(TempSymbols);
265*9880d681SAndroid Build Coastguard Worker }
266*9880d681SAndroid Build Coastguard Worker return *Symbols;
267*9880d681SAndroid Build Coastguard Worker }
268*9880d681SAndroid Build Coastguard Worker
getStringTable()269*9880d681SAndroid Build Coastguard Worker Expected<NameHashTable &> PDBFile::getStringTable() {
270*9880d681SAndroid Build Coastguard Worker if (!StringTable || !StringTableStream) {
271*9880d681SAndroid Build Coastguard Worker auto IS = getPDBInfoStream();
272*9880d681SAndroid Build Coastguard Worker if (!IS)
273*9880d681SAndroid Build Coastguard Worker return IS.takeError();
274*9880d681SAndroid Build Coastguard Worker
275*9880d681SAndroid Build Coastguard Worker uint32_t NameStreamIndex = IS->getNamedStreamIndex("/names");
276*9880d681SAndroid Build Coastguard Worker
277*9880d681SAndroid Build Coastguard Worker if (NameStreamIndex == 0)
278*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::no_stream);
279*9880d681SAndroid Build Coastguard Worker if (NameStreamIndex >= getNumStreams())
280*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::no_stream);
281*9880d681SAndroid Build Coastguard Worker
282*9880d681SAndroid Build Coastguard Worker auto NS = MappedBlockStream::createIndexedStream(NameStreamIndex, *this);
283*9880d681SAndroid Build Coastguard Worker if (!NS)
284*9880d681SAndroid Build Coastguard Worker return NS.takeError();
285*9880d681SAndroid Build Coastguard Worker
286*9880d681SAndroid Build Coastguard Worker StreamReader Reader(**NS);
287*9880d681SAndroid Build Coastguard Worker auto N = llvm::make_unique<NameHashTable>();
288*9880d681SAndroid Build Coastguard Worker if (auto EC = N->load(Reader))
289*9880d681SAndroid Build Coastguard Worker return std::move(EC);
290*9880d681SAndroid Build Coastguard Worker StringTable = std::move(N);
291*9880d681SAndroid Build Coastguard Worker StringTableStream = std::move(*NS);
292*9880d681SAndroid Build Coastguard Worker }
293*9880d681SAndroid Build Coastguard Worker return *StringTable;
294*9880d681SAndroid Build Coastguard Worker }
295*9880d681SAndroid Build Coastguard Worker
setSuperBlock(const SuperBlock * Block)296*9880d681SAndroid Build Coastguard Worker Error PDBFile::setSuperBlock(const SuperBlock *Block) {
297*9880d681SAndroid Build Coastguard Worker SB = Block;
298*9880d681SAndroid Build Coastguard Worker
299*9880d681SAndroid Build Coastguard Worker // Check the magic bytes.
300*9880d681SAndroid Build Coastguard Worker if (memcmp(SB->MagicBytes, MsfMagic, sizeof(MsfMagic)) != 0)
301*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::corrupt_file,
302*9880d681SAndroid Build Coastguard Worker "MSF magic header doesn't match");
303*9880d681SAndroid Build Coastguard Worker
304*9880d681SAndroid Build Coastguard Worker // We don't support blocksizes which aren't a multiple of four bytes.
305*9880d681SAndroid Build Coastguard Worker if (SB->BlockSize % sizeof(support::ulittle32_t) != 0)
306*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::corrupt_file,
307*9880d681SAndroid Build Coastguard Worker "Block size is not multiple of 4.");
308*9880d681SAndroid Build Coastguard Worker
309*9880d681SAndroid Build Coastguard Worker switch (SB->BlockSize) {
310*9880d681SAndroid Build Coastguard Worker case 512:
311*9880d681SAndroid Build Coastguard Worker case 1024:
312*9880d681SAndroid Build Coastguard Worker case 2048:
313*9880d681SAndroid Build Coastguard Worker case 4096:
314*9880d681SAndroid Build Coastguard Worker break;
315*9880d681SAndroid Build Coastguard Worker default:
316*9880d681SAndroid Build Coastguard Worker // An invalid block size suggests a corrupt PDB file.
317*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::corrupt_file,
318*9880d681SAndroid Build Coastguard Worker "Unsupported block size.");
319*9880d681SAndroid Build Coastguard Worker }
320*9880d681SAndroid Build Coastguard Worker
321*9880d681SAndroid Build Coastguard Worker if (Buffer->getLength() % SB->BlockSize != 0)
322*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::corrupt_file,
323*9880d681SAndroid Build Coastguard Worker "File size is not a multiple of block size");
324*9880d681SAndroid Build Coastguard Worker
325*9880d681SAndroid Build Coastguard Worker // We don't support directories whose sizes aren't a multiple of four bytes.
326*9880d681SAndroid Build Coastguard Worker if (SB->NumDirectoryBytes % sizeof(support::ulittle32_t) != 0)
327*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::corrupt_file,
328*9880d681SAndroid Build Coastguard Worker "Directory size is not multiple of 4.");
329*9880d681SAndroid Build Coastguard Worker
330*9880d681SAndroid Build Coastguard Worker // The number of blocks which comprise the directory is a simple function of
331*9880d681SAndroid Build Coastguard Worker // the number of bytes it contains.
332*9880d681SAndroid Build Coastguard Worker uint64_t NumDirectoryBlocks = getNumDirectoryBlocks();
333*9880d681SAndroid Build Coastguard Worker
334*9880d681SAndroid Build Coastguard Worker // The directory, as we understand it, is a block which consists of a list of
335*9880d681SAndroid Build Coastguard Worker // block numbers. It is unclear what would happen if the number of blocks
336*9880d681SAndroid Build Coastguard Worker // couldn't fit on a single block.
337*9880d681SAndroid Build Coastguard Worker if (NumDirectoryBlocks > SB->BlockSize / sizeof(support::ulittle32_t))
338*9880d681SAndroid Build Coastguard Worker return make_error<RawError>(raw_error_code::corrupt_file,
339*9880d681SAndroid Build Coastguard Worker "Too many directory blocks.");
340*9880d681SAndroid Build Coastguard Worker
341*9880d681SAndroid Build Coastguard Worker return Error::success();
342*9880d681SAndroid Build Coastguard Worker }
343*9880d681SAndroid Build Coastguard Worker
commit()344*9880d681SAndroid Build Coastguard Worker Error PDBFile::commit() {
345*9880d681SAndroid Build Coastguard Worker StreamWriter Writer(*Buffer);
346*9880d681SAndroid Build Coastguard Worker
347*9880d681SAndroid Build Coastguard Worker if (auto EC = Writer.writeObject(*SB))
348*9880d681SAndroid Build Coastguard Worker return EC;
349*9880d681SAndroid Build Coastguard Worker Writer.setOffset(getBlockMapOffset());
350*9880d681SAndroid Build Coastguard Worker if (auto EC = Writer.writeArray(DirectoryBlocks))
351*9880d681SAndroid Build Coastguard Worker return EC;
352*9880d681SAndroid Build Coastguard Worker
353*9880d681SAndroid Build Coastguard Worker auto DS = MappedBlockStream::createDirectoryStream(*this);
354*9880d681SAndroid Build Coastguard Worker if (!DS)
355*9880d681SAndroid Build Coastguard Worker return DS.takeError();
356*9880d681SAndroid Build Coastguard Worker auto DirStream = std::move(*DS);
357*9880d681SAndroid Build Coastguard Worker StreamWriter DW(*DirStream);
358*9880d681SAndroid Build Coastguard Worker if (auto EC = DW.writeInteger(this->getNumStreams()))
359*9880d681SAndroid Build Coastguard Worker return EC;
360*9880d681SAndroid Build Coastguard Worker
361*9880d681SAndroid Build Coastguard Worker if (auto EC = DW.writeArray(StreamSizes))
362*9880d681SAndroid Build Coastguard Worker return EC;
363*9880d681SAndroid Build Coastguard Worker
364*9880d681SAndroid Build Coastguard Worker for (const auto &Blocks : StreamMap) {
365*9880d681SAndroid Build Coastguard Worker if (auto EC = DW.writeArray(Blocks))
366*9880d681SAndroid Build Coastguard Worker return EC;
367*9880d681SAndroid Build Coastguard Worker }
368*9880d681SAndroid Build Coastguard Worker
369*9880d681SAndroid Build Coastguard Worker if (Info) {
370*9880d681SAndroid Build Coastguard Worker if (auto EC = Info->commit())
371*9880d681SAndroid Build Coastguard Worker return EC;
372*9880d681SAndroid Build Coastguard Worker }
373*9880d681SAndroid Build Coastguard Worker
374*9880d681SAndroid Build Coastguard Worker if (Dbi) {
375*9880d681SAndroid Build Coastguard Worker if (auto EC = Dbi->commit())
376*9880d681SAndroid Build Coastguard Worker return EC;
377*9880d681SAndroid Build Coastguard Worker }
378*9880d681SAndroid Build Coastguard Worker
379*9880d681SAndroid Build Coastguard Worker if (Symbols) {
380*9880d681SAndroid Build Coastguard Worker if (auto EC = Symbols->commit())
381*9880d681SAndroid Build Coastguard Worker return EC;
382*9880d681SAndroid Build Coastguard Worker }
383*9880d681SAndroid Build Coastguard Worker
384*9880d681SAndroid Build Coastguard Worker if (Publics) {
385*9880d681SAndroid Build Coastguard Worker if (auto EC = Publics->commit())
386*9880d681SAndroid Build Coastguard Worker return EC;
387*9880d681SAndroid Build Coastguard Worker }
388*9880d681SAndroid Build Coastguard Worker
389*9880d681SAndroid Build Coastguard Worker if (Tpi) {
390*9880d681SAndroid Build Coastguard Worker if (auto EC = Tpi->commit())
391*9880d681SAndroid Build Coastguard Worker return EC;
392*9880d681SAndroid Build Coastguard Worker }
393*9880d681SAndroid Build Coastguard Worker
394*9880d681SAndroid Build Coastguard Worker if (Ipi) {
395*9880d681SAndroid Build Coastguard Worker if (auto EC = Ipi->commit())
396*9880d681SAndroid Build Coastguard Worker return EC;
397*9880d681SAndroid Build Coastguard Worker }
398*9880d681SAndroid Build Coastguard Worker
399*9880d681SAndroid Build Coastguard Worker return Buffer->commit();
400*9880d681SAndroid Build Coastguard Worker }
401