blob: 75840b0e77693c0edf1932833c4cd7efd43c13c1 [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 Turnera3225b02016-07-29 20:56:36 +000013#include "llvm/DebugInfo/MSF/StreamArray.h"
14#include "llvm/DebugInfo/MSF/StreamInterface.h"
15#include "llvm/DebugInfo/MSF/StreamReader.h"
16#include "llvm/DebugInfo/MSF/StreamWriter.h"
Zachary Turner2f09b502016-04-29 17:28:47 +000017#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
18#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
Zachary Turner3df1bfa2016-06-03 05:52:57 +000019#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
Rui Ueyama1f6b6e22016-05-13 21:21:53 +000020#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
Zachary Turner819e77d2016-05-06 20:51:57 +000021#include "llvm/DebugInfo/PDB/Raw/RawError.h"
Rui Ueyama0fcd8262016-05-20 19:55:17 +000022#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h"
Zachary Turnerf5c59652016-05-03 00:28:21 +000023#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
Zachary Turner0a43efe2016-04-25 17:38:08 +000024#include "llvm/Support/Endian.h"
Zachary Turner1dc9fd32016-06-14 20:48:36 +000025#include "llvm/Support/FileOutputBuffer.h"
Zachary Turner0a43efe2016-04-25 17:38:08 +000026#include "llvm/Support/MemoryBuffer.h"
27
28using namespace llvm;
Zachary Turnerb84faa82016-06-10 05:10:19 +000029using namespace llvm::codeview;
Zachary Turnerbac69d32016-07-22 19:56:05 +000030using namespace llvm::msf;
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 Turnerd66889c2016-07-28 19:12:28 +000037PDBFile::PDBFile(std::unique_ptr<ReadableStream> PdbFileBuffer,
Zachary Turnere109dc62016-07-22 19:56:26 +000038 BumpPtrAllocator &Allocator)
Zachary Turnere4a4f332016-07-22 19:56:33 +000039 : Allocator(Allocator), Buffer(std::move(PdbFileBuffer)) {}
Zachary Turner0a43efe2016-04-25 17:38:08 +000040
41PDBFile::~PDBFile() {}
42
Zachary Turnerd66889c2016-07-28 19:12:28 +000043uint32_t PDBFile::getBlockSize() const { return ContainerLayout.SB->BlockSize; }
Zachary Turner0a43efe2016-04-25 17:38:08 +000044
Zachary Turnere4a4f332016-07-22 19:56:33 +000045uint32_t PDBFile::getFreeBlockMapBlock() const {
Zachary Turnerd66889c2016-07-28 19:12:28 +000046 return ContainerLayout.SB->FreeBlockMapBlock;
Zachary Turnere4a4f332016-07-22 19:56:33 +000047}
Zachary Turner0a43efe2016-04-25 17:38:08 +000048
Zachary Turnerd66889c2016-07-28 19:12:28 +000049uint32_t PDBFile::getBlockCount() const {
50 return ContainerLayout.SB->NumBlocks;
51}
Zachary Turner0a43efe2016-04-25 17:38:08 +000052
Zachary Turnere4a4f332016-07-22 19:56:33 +000053uint32_t PDBFile::getNumDirectoryBytes() const {
Zachary Turnerd66889c2016-07-28 19:12:28 +000054 return ContainerLayout.SB->NumDirectoryBytes;
Zachary Turnere4a4f332016-07-22 19:56:33 +000055}
Zachary Turner0a43efe2016-04-25 17:38:08 +000056
Zachary Turnere4a4f332016-07-22 19:56:33 +000057uint32_t PDBFile::getBlockMapIndex() const {
Zachary Turnerd66889c2016-07-28 19:12:28 +000058 return ContainerLayout.SB->BlockMapAddr;
Zachary Turnere4a4f332016-07-22 19:56:33 +000059}
Zachary Turner0a43efe2016-04-25 17:38:08 +000060
Zachary Turnerd66889c2016-07-28 19:12:28 +000061uint32_t PDBFile::getUnknown1() const { return ContainerLayout.SB->Unknown1; }
Zachary Turner0a43efe2016-04-25 17:38:08 +000062
63uint32_t PDBFile::getNumDirectoryBlocks() const {
Zachary Turnerd66889c2016-07-28 19:12:28 +000064 return msf::bytesToBlocks(ContainerLayout.SB->NumDirectoryBytes,
65 ContainerLayout.SB->BlockSize);
Zachary Turner0a43efe2016-04-25 17:38:08 +000066}
67
68uint64_t PDBFile::getBlockMapOffset() const {
Zachary Turnerd66889c2016-07-28 19:12:28 +000069 return (uint64_t)ContainerLayout.SB->BlockMapAddr *
70 ContainerLayout.SB->BlockSize;
Zachary Turner0a43efe2016-04-25 17:38:08 +000071}
72
Zachary Turnerd66889c2016-07-28 19:12:28 +000073uint32_t PDBFile::getNumStreams() const {
74 return ContainerLayout.StreamSizes.size();
75}
Zachary Turner0a43efe2016-04-25 17:38:08 +000076
77uint32_t PDBFile::getStreamByteSize(uint32_t StreamIndex) const {
Zachary Turnerd66889c2016-07-28 19:12:28 +000078 return ContainerLayout.StreamSizes[StreamIndex];
Zachary Turner0a43efe2016-04-25 17:38:08 +000079}
80
Zachary Turnerd8447992016-06-07 05:28:55 +000081ArrayRef<support::ulittle32_t>
Zachary Turner0a43efe2016-04-25 17:38:08 +000082PDBFile::getStreamBlockList(uint32_t StreamIndex) const {
Zachary Turnerd66889c2016-07-28 19:12:28 +000083 return ContainerLayout.StreamMap[StreamIndex];
Zachary Turner0a43efe2016-04-25 17:38:08 +000084}
85
David Majnemer1b79e9a2016-07-10 05:32:05 +000086uint32_t PDBFile::getFileSize() const { return Buffer->getLength(); }
Zachary Turner1dc9fd32016-06-14 20:48:36 +000087
David Majnemer6211b1f2016-07-10 03:34:47 +000088Expected<ArrayRef<uint8_t>> PDBFile::getBlockData(uint32_t BlockIndex,
89 uint32_t NumBytes) const {
Zachary Turnerfaa554b2016-07-15 22:16:56 +000090 uint64_t StreamBlockOffset = msf::blockToOffset(BlockIndex, getBlockSize());
Zachary Turner0a43efe2016-04-25 17:38:08 +000091
Zachary Turnerb84faa82016-06-10 05:10:19 +000092 ArrayRef<uint8_t> Result;
93 if (auto EC = Buffer->readBytes(StreamBlockOffset, NumBytes, Result))
David Majnemer6211b1f2016-07-10 03:34:47 +000094 return std::move(EC);
Zachary Turnerb84faa82016-06-10 05:10:19 +000095 return Result;
Zachary Turner0a43efe2016-04-25 17:38:08 +000096}
97
Zachary Turner5acb4ac2016-06-10 05:09:12 +000098Error PDBFile::setBlockData(uint32_t BlockIndex, uint32_t Offset,
99 ArrayRef<uint8_t> Data) const {
Zachary Turnerd66889c2016-07-28 19:12:28 +0000100 return make_error<RawError>(raw_error_code::not_writable,
101 "PDBFile is immutable");
Zachary Turner5acb4ac2016-06-10 05:09:12 +0000102}
103
Zachary Turner819e77d2016-05-06 20:51:57 +0000104Error PDBFile::parseFileHeaders() {
Zachary Turnerb84faa82016-06-10 05:10:19 +0000105 StreamReader Reader(*Buffer);
Zachary Turnerc59261c2016-05-25 03:53:16 +0000106
Rui Ueyama7a5cdc62016-07-29 21:38:00 +0000107 // Initialize SB.
Zachary Turnere4a4f332016-07-22 19:56:33 +0000108 const msf::SuperBlock *SB = nullptr;
Zachary Turnerb84faa82016-06-10 05:10:19 +0000109 if (auto EC = Reader.readObject(SB)) {
110 consumeError(std::move(EC));
Zachary Turner819e77d2016-05-06 20:51:57 +0000111 return make_error<RawError>(raw_error_code::corrupt_file,
112 "Does not contain superblock");
Zachary Turnerb84faa82016-06-10 05:10:19 +0000113 }
Zachary Turner0a43efe2016-04-25 17:38:08 +0000114
Zachary Turnere4a4f332016-07-22 19:56:33 +0000115 if (auto EC = msf::validateSuperBlock(*SB))
Zachary Turnerab58ae82016-06-30 17:43:00 +0000116 return EC;
Zachary Turner819e77d2016-05-06 20:51:57 +0000117
Zachary Turnere4a4f332016-07-22 19:56:33 +0000118 if (Buffer->getLength() % SB->BlockSize != 0)
119 return make_error<RawError>(raw_error_code::corrupt_file,
120 "File size is not a multiple of block size");
Zachary Turnerd66889c2016-07-28 19:12:28 +0000121 ContainerLayout.SB = SB;
Zachary Turnere4a4f332016-07-22 19:56:33 +0000122
Rui Ueyama7a5cdc62016-07-29 21:38:00 +0000123 // Initialize Free Page Map.
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000124 ContainerLayout.FreePageMap.resize(SB->NumBlocks);
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000125 // The Fpm exists either at block 1 or block 2 of the MSF. However, this
126 // allows for a maximum of getBlockSize() * 8 blocks bits in the Fpm, and
127 // thusly an equal number of total blocks in the file. For a block size
128 // of 4KiB (very common), this would yield 32KiB total blocks in file, for a
129 // maximum file size of 32KiB * 4KiB = 128MiB. Obviously this won't do, so
130 // the Fpm is split across the file at `getBlockSize()` intervals. As a
131 // result, every block whose index is of the form |{1,2} + getBlockSize() * k|
132 // for any non-negative integer k is an Fpm block. In theory, we only really
133 // need to reserve blocks of the form |{1,2} + getBlockSize() * 8 * k|, but
134 // current versions of the MSF format already expect the Fpm to be arranged
135 // at getBlockSize() intervals, so we have to be compatible.
136 // See the function fpmPn() for more information:
137 // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L489
Zachary Turner8cf51c32016-08-03 16:53:21 +0000138 auto FpmStream = MappedBlockStream::createFpmStream(ContainerLayout, *Buffer);
139 StreamReader FpmReader(*FpmStream);
140 ArrayRef<uint8_t> FpmBytes;
141 if (auto EC = FpmReader.readBytes(FpmBytes,
142 msf::getFullFpmByteSize(ContainerLayout)))
143 return EC;
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000144 uint32_t BlocksRemaining = getBlockCount();
Zachary Turner8cf51c32016-08-03 16:53:21 +0000145 uint32_t BI = 0;
146 for (auto Byte : FpmBytes) {
147 uint32_t BlocksThisByte = std::min(BlocksRemaining, 8U);
148 for (uint32_t I = 0; I < BlocksThisByte; ++I) {
149 if (Byte & (1 << I))
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000150 ContainerLayout.FreePageMap[BI] = true;
Zachary Turner8cf51c32016-08-03 16:53:21 +0000151 --BlocksRemaining;
152 ++BI;
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000153 }
Zachary Turnerd3c7b8e2016-08-01 21:19:45 +0000154 }
Rui Ueyama7a5cdc62016-07-29 21:38:00 +0000155
Zachary Turnerab58ae82016-06-30 17:43:00 +0000156 Reader.setOffset(getBlockMapOffset());
Zachary Turnerd66889c2016-07-28 19:12:28 +0000157 if (auto EC = Reader.readArray(ContainerLayout.DirectoryBlocks,
158 getNumDirectoryBlocks()))
Zachary Turnerab58ae82016-06-30 17:43:00 +0000159 return EC;
Zachary Turner0a43efe2016-04-25 17:38:08 +0000160
Zachary Turner819e77d2016-05-06 20:51:57 +0000161 return Error::success();
Zachary Turner0a43efe2016-04-25 17:38:08 +0000162}
163
Zachary Turner819e77d2016-05-06 20:51:57 +0000164Error PDBFile::parseStreamData() {
Zachary Turnerd66889c2016-07-28 19:12:28 +0000165 assert(ContainerLayout.SB);
Zachary Turnerd8447992016-06-07 05:28:55 +0000166 if (DirectoryStream)
167 return Error::success();
Zachary Turner0a43efe2016-04-25 17:38:08 +0000168
Zachary Turner0a43efe2016-04-25 17:38:08 +0000169 uint32_t NumStreams = 0;
Zachary Turner0a43efe2016-04-25 17:38:08 +0000170
Zachary Turnerd8447992016-06-07 05:28:55 +0000171 // Normally you can't use a MappedBlockStream without having fully parsed the
172 // PDB file, because it accesses the directory and various other things, which
173 // is exactly what we are attempting to parse. By specifying a custom
174 // subclass of IPDBStreamData which only accesses the fields that have already
175 // been parsed, we can avoid this and reuse MappedBlockStream.
Zachary Turnerd66889c2016-07-28 19:12:28 +0000176 auto DS = MappedBlockStream::createDirectoryStream(ContainerLayout, *Buffer);
177 StreamReader Reader(*DS);
Zachary Turnerd8447992016-06-07 05:28:55 +0000178 if (auto EC = Reader.readInteger(NumStreams))
179 return EC;
Zachary Turner0a43efe2016-04-25 17:38:08 +0000180
Zachary Turnerd66889c2016-07-28 19:12:28 +0000181 if (auto EC = Reader.readArray(ContainerLayout.StreamSizes, NumStreams))
Zachary Turnerd8447992016-06-07 05:28:55 +0000182 return EC;
183 for (uint32_t I = 0; I < NumStreams; ++I) {
Reid Kleckner5aba52f2016-06-22 22:42:24 +0000184 uint32_t StreamSize = getStreamByteSize(I);
185 // FIXME: What does StreamSize ~0U mean?
David Majnemer9efba742016-05-27 16:16:48 +0000186 uint64_t NumExpectedStreamBlocks =
Zachary Turnere4a4f332016-07-22 19:56:33 +0000187 StreamSize == UINT32_MAX
188 ? 0
Zachary Turnerd66889c2016-07-28 19:12:28 +0000189 : msf::bytesToBlocks(StreamSize, ContainerLayout.SB->BlockSize);
Zachary Turnerb84faa82016-06-10 05:10:19 +0000190
191 // For convenience, we store the block array contiguously. This is because
192 // if someone calls setStreamMap(), it is more convenient to be able to call
193 // it with an ArrayRef instead of setting up a StreamRef. Since the
194 // DirectoryStream is cached in the class and thus lives for the life of the
195 // class, we can be guaranteed that readArray() will return a stable
196 // reference, even if it has to allocate from its internal pool.
197 ArrayRef<support::ulittle32_t> Blocks;
Zachary Turnerd8447992016-06-07 05:28:55 +0000198 if (auto EC = Reader.readArray(Blocks, NumExpectedStreamBlocks))
199 return EC;
David Majnemer1b79e9a2016-07-10 05:32:05 +0000200 for (uint32_t Block : Blocks) {
Zachary Turnerd66889c2016-07-28 19:12:28 +0000201 uint64_t BlockEndOffset =
202 (uint64_t)(Block + 1) * ContainerLayout.SB->BlockSize;
David Majnemer1b79e9a2016-07-10 05:32:05 +0000203 if (BlockEndOffset > getFileSize())
204 return make_error<RawError>(raw_error_code::corrupt_file,
205 "Stream block map is corrupt.");
206 }
Zachary Turnerd66889c2016-07-28 19:12:28 +0000207 ContainerLayout.StreamMap.push_back(Blocks);
David Majnemer9efba742016-05-27 16:16:48 +0000208 }
209
Zachary Turner0a43efe2016-04-25 17:38:08 +0000210 // We should have read exactly SB->NumDirectoryBytes bytes.
Zachary Turnerd8447992016-06-07 05:28:55 +0000211 assert(Reader.bytesRemaining() == 0);
Zachary Turnerd66889c2016-07-28 19:12:28 +0000212 DirectoryStream = std::move(DS);
Zachary Turner819e77d2016-05-06 20:51:57 +0000213 return Error::success();
Zachary Turner0a43efe2016-04-25 17:38:08 +0000214}
215
Zachary Turnerd8447992016-06-07 05:28:55 +0000216llvm::ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {
Zachary Turnerd66889c2016-07-28 19:12:28 +0000217 return ContainerLayout.DirectoryBlocks;
Zachary Turner0a43efe2016-04-25 17:38:08 +0000218}
Zachary Turner53a65ba2016-04-26 18:42:34 +0000219
Zachary Turner819e77d2016-05-06 20:51:57 +0000220Expected<InfoStream &> PDBFile::getPDBInfoStream() {
Zachary Turner2f09b502016-04-29 17:28:47 +0000221 if (!Info) {
Zachary Turnerd66889c2016-07-28 19:12:28 +0000222 auto InfoS = MappedBlockStream::createIndexedStream(ContainerLayout,
223 *Buffer, StreamPDB);
224 auto TempInfo = llvm::make_unique<InfoStream>(std::move(InfoS));
Zachary Turnera1657a92016-06-08 17:26:39 +0000225 if (auto EC = TempInfo->reload())
Zachary Turner819e77d2016-05-06 20:51:57 +0000226 return std::move(EC);
Zachary Turnera1657a92016-06-08 17:26:39 +0000227 Info = std::move(TempInfo);
Zachary Turner53a65ba2016-04-26 18:42:34 +0000228 }
Zachary Turner2f09b502016-04-29 17:28:47 +0000229 return *Info;
Zachary Turner53a65ba2016-04-26 18:42:34 +0000230}
231
Zachary Turner819e77d2016-05-06 20:51:57 +0000232Expected<DbiStream &> PDBFile::getPDBDbiStream() {
Zachary Turner2f09b502016-04-29 17:28:47 +0000233 if (!Dbi) {
Zachary Turnerd66889c2016-07-28 19:12:28 +0000234 auto DbiS = MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer,
235 StreamDBI);
236 auto TempDbi = llvm::make_unique<DbiStream>(*this, std::move(DbiS));
Zachary Turnera1657a92016-06-08 17:26:39 +0000237 if (auto EC = TempDbi->reload())
Zachary Turner819e77d2016-05-06 20:51:57 +0000238 return std::move(EC);
Zachary Turnera1657a92016-06-08 17:26:39 +0000239 Dbi = std::move(TempDbi);
Zachary Turner53a65ba2016-04-26 18:42:34 +0000240 }
Zachary Turner2f09b502016-04-29 17:28:47 +0000241 return *Dbi;
Zachary Turner53a65ba2016-04-26 18:42:34 +0000242}
Zachary Turnerf5c59652016-05-03 00:28:21 +0000243
Zachary Turner819e77d2016-05-06 20:51:57 +0000244Expected<TpiStream &> PDBFile::getPDBTpiStream() {
Zachary Turnerf5c59652016-05-03 00:28:21 +0000245 if (!Tpi) {
Zachary Turnerd66889c2016-07-28 19:12:28 +0000246 auto TpiS = MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer,
247 StreamTPI);
248 auto TempTpi = llvm::make_unique<TpiStream>(*this, std::move(TpiS));
Zachary Turnera1657a92016-06-08 17:26:39 +0000249 if (auto EC = TempTpi->reload())
Zachary Turner819e77d2016-05-06 20:51:57 +0000250 return std::move(EC);
Zachary Turnera1657a92016-06-08 17:26:39 +0000251 Tpi = std::move(TempTpi);
Zachary Turnerf5c59652016-05-03 00:28:21 +0000252 }
253 return *Tpi;
254}
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000255
Zachary Turnerc9972c62016-05-25 04:35:22 +0000256Expected<TpiStream &> PDBFile::getPDBIpiStream() {
257 if (!Ipi) {
Zachary Turnerd66889c2016-07-28 19:12:28 +0000258 auto IpiS = MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer,
259 StreamIPI);
260 auto TempIpi = llvm::make_unique<TpiStream>(*this, std::move(IpiS));
Zachary Turnera1657a92016-06-08 17:26:39 +0000261 if (auto EC = TempIpi->reload())
Zachary Turnerc9972c62016-05-25 04:35:22 +0000262 return std::move(EC);
Zachary Turnera1657a92016-06-08 17:26:39 +0000263 Ipi = std::move(TempIpi);
Zachary Turnerc9972c62016-05-25 04:35:22 +0000264 }
265 return *Ipi;
266}
267
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000268Expected<PublicsStream &> PDBFile::getPDBPublicsStream() {
269 if (!Publics) {
270 auto DbiS = getPDBDbiStream();
Zachary Turnera1657a92016-06-08 17:26:39 +0000271 if (!DbiS)
272 return DbiS.takeError();
273
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000274 uint32_t PublicsStreamNum = DbiS->getPublicSymbolStreamIndex();
275
Zachary Turnerd66889c2016-07-28 19:12:28 +0000276 auto PublicS = MappedBlockStream::createIndexedStream(
277 ContainerLayout, *Buffer, PublicsStreamNum);
Zachary Turnera1657a92016-06-08 17:26:39 +0000278 auto TempPublics =
Zachary Turnerd66889c2016-07-28 19:12:28 +0000279 llvm::make_unique<PublicsStream>(*this, std::move(PublicS));
Zachary Turnera1657a92016-06-08 17:26:39 +0000280 if (auto EC = TempPublics->reload())
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000281 return std::move(EC);
Zachary Turnera1657a92016-06-08 17:26:39 +0000282 Publics = std::move(TempPublics);
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000283 }
284 return *Publics;
285}
Rui Ueyama0fcd8262016-05-20 19:55:17 +0000286
287Expected<SymbolStream &> PDBFile::getPDBSymbolStream() {
288 if (!Symbols) {
289 auto DbiS = getPDBDbiStream();
Zachary Turnera1657a92016-06-08 17:26:39 +0000290 if (!DbiS)
291 return DbiS.takeError();
292
Rui Ueyama0fcd8262016-05-20 19:55:17 +0000293 uint32_t SymbolStreamNum = DbiS->getSymRecordStreamIndex();
Zachary Turnerd66889c2016-07-28 19:12:28 +0000294 auto SymbolS = MappedBlockStream::createIndexedStream(
295 ContainerLayout, *Buffer, SymbolStreamNum);
Rui Ueyama0fcd8262016-05-20 19:55:17 +0000296
Zachary Turnerd66889c2016-07-28 19:12:28 +0000297 auto TempSymbols = llvm::make_unique<SymbolStream>(std::move(SymbolS));
Zachary Turnera1657a92016-06-08 17:26:39 +0000298 if (auto EC = TempSymbols->reload())
Rui Ueyama0fcd8262016-05-20 19:55:17 +0000299 return std::move(EC);
Zachary Turnera1657a92016-06-08 17:26:39 +0000300 Symbols = std::move(TempSymbols);
Rui Ueyama0fcd8262016-05-20 19:55:17 +0000301 }
302 return *Symbols;
303}
Zachary Turner3df1bfa2016-06-03 05:52:57 +0000304
305Expected<NameHashTable &> PDBFile::getStringTable() {
306 if (!StringTable || !StringTableStream) {
Zachary Turnera1657a92016-06-08 17:26:39 +0000307 auto IS = getPDBInfoStream();
308 if (!IS)
309 return IS.takeError();
310
311 uint32_t NameStreamIndex = IS->getNamedStreamIndex("/names");
Zachary Turner3df1bfa2016-06-03 05:52:57 +0000312
313 if (NameStreamIndex == 0)
314 return make_error<RawError>(raw_error_code::no_stream);
Zachary Turnerd2b2bfe2016-06-08 00:25:08 +0000315 if (NameStreamIndex >= getNumStreams())
316 return make_error<RawError>(raw_error_code::no_stream);
Zachary Turnerd66889c2016-07-28 19:12:28 +0000317 auto NS = MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer,
318 NameStreamIndex);
Zachary Turnerd2b2bfe2016-06-08 00:25:08 +0000319
Zachary Turnerd66889c2016-07-28 19:12:28 +0000320 StreamReader Reader(*NS);
Zachary Turner3df1bfa2016-06-03 05:52:57 +0000321 auto N = llvm::make_unique<NameHashTable>();
322 if (auto EC = N->load(Reader))
323 return std::move(EC);
324 StringTable = std::move(N);
Zachary Turnerd66889c2016-07-28 19:12:28 +0000325 StringTableStream = std::move(NS);
Zachary Turner3df1bfa2016-06-03 05:52:57 +0000326 }
327 return *StringTable;
328}