blob: d587704c62c951c27a6382f632c35d697b1a26ee [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"
11#include "llvm/ADT/ArrayRef.h"
Zachary Turner2f09b502016-04-29 17:28:47 +000012#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
13#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
Rui Ueyama1f6b6e22016-05-13 21:21:53 +000014#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
Zachary Turner819e77d2016-05-06 20:51:57 +000015#include "llvm/DebugInfo/PDB/Raw/RawError.h"
Zachary Turnerf5c59652016-05-03 00:28:21 +000016#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
Zachary Turner0a43efe2016-04-25 17:38:08 +000017#include "llvm/Support/Endian.h"
18#include "llvm/Support/MemoryBuffer.h"
19
20using namespace llvm;
Zachary Turner2f09b502016-04-29 17:28:47 +000021using namespace llvm::pdb;
Zachary Turner0a43efe2016-04-25 17:38:08 +000022
23namespace {
24static const char Magic[] = {'M', 'i', 'c', 'r', 'o', 's', 'o', 'f',
25 't', ' ', 'C', '/', 'C', '+', '+', ' ',
26 'M', 'S', 'F', ' ', '7', '.', '0', '0',
27 '\r', '\n', '\x1a', 'D', 'S', '\0', '\0', '\0'};
28
29// The superblock is overlaid at the beginning of the file (offset 0).
30// It starts with a magic header and is followed by information which describes
31// the layout of the file system.
32struct SuperBlock {
33 char MagicBytes[sizeof(Magic)];
34 // The file system is split into a variable number of fixed size elements.
35 // These elements are referred to as blocks. The size of a block may vary
36 // from system to system.
37 support::ulittle32_t BlockSize;
38 // This field's purpose is not yet known.
39 support::ulittle32_t Unknown0;
40 // This contains the number of blocks resident in the file system. In
41 // practice, NumBlocks * BlockSize is equivalent to the size of the PDB file.
42 support::ulittle32_t NumBlocks;
43 // This contains the number of bytes which make up the directory.
44 support::ulittle32_t NumDirectoryBytes;
45 // This field's purpose is not yet known.
46 support::ulittle32_t Unknown1;
47 // This contains the block # of the block map.
48 support::ulittle32_t BlockMapAddr;
49};
50}
51
Zachary Turner2f09b502016-04-29 17:28:47 +000052struct llvm::pdb::PDBFileContext {
Zachary Turner0a43efe2016-04-25 17:38:08 +000053 std::unique_ptr<MemoryBuffer> Buffer;
54 const SuperBlock *SB;
55 std::vector<uint32_t> StreamSizes;
56 DenseMap<uint32_t, std::vector<uint32_t>> StreamMap;
57};
58
Zachary Turner819e77d2016-05-06 20:51:57 +000059static Error checkOffset(MemoryBufferRef M, uintptr_t Addr,
60 const uint64_t Size) {
Zachary Turner0a43efe2016-04-25 17:38:08 +000061 if (Addr + Size < Addr || Addr + Size < Size ||
62 Addr + Size > uintptr_t(M.getBufferEnd()) ||
63 Addr < uintptr_t(M.getBufferStart())) {
Zachary Turner819e77d2016-05-06 20:51:57 +000064 return make_error<RawError>(raw_error_code::corrupt_file,
65 "Invalid buffer address");
Zachary Turner0a43efe2016-04-25 17:38:08 +000066 }
Zachary Turner819e77d2016-05-06 20:51:57 +000067 return Error::success();
Zachary Turner0a43efe2016-04-25 17:38:08 +000068}
69
70template <typename T>
Zachary Turner819e77d2016-05-06 20:51:57 +000071static Error checkOffset(MemoryBufferRef M, ArrayRef<T> AR) {
Zachary Turner0a43efe2016-04-25 17:38:08 +000072 return checkOffset(M, uintptr_t(AR.data()), (uint64_t)AR.size() * sizeof(T));
73}
74
75PDBFile::PDBFile(std::unique_ptr<MemoryBuffer> MemBuffer) {
76 Context.reset(new PDBFileContext());
77 Context->Buffer = std::move(MemBuffer);
78}
79
80PDBFile::~PDBFile() {}
81
82uint32_t PDBFile::getBlockSize() const { return Context->SB->BlockSize; }
83
84uint32_t PDBFile::getUnknown0() const { return Context->SB->Unknown0; }
85
86uint32_t PDBFile::getBlockCount() const { return Context->SB->NumBlocks; }
87
88uint32_t PDBFile::getNumDirectoryBytes() const {
89 return Context->SB->NumDirectoryBytes;
90}
91
92uint32_t PDBFile::getBlockMapIndex() const { return Context->SB->BlockMapAddr; }
93
94uint32_t PDBFile::getUnknown1() const { return Context->SB->Unknown1; }
95
96uint32_t PDBFile::getNumDirectoryBlocks() const {
97 return bytesToBlocks(Context->SB->NumDirectoryBytes, Context->SB->BlockSize);
98}
99
100uint64_t PDBFile::getBlockMapOffset() const {
101 return (uint64_t)Context->SB->BlockMapAddr * Context->SB->BlockSize;
102}
103
104uint32_t PDBFile::getNumStreams() const { return Context->StreamSizes.size(); }
105
106uint32_t PDBFile::getStreamByteSize(uint32_t StreamIndex) const {
107 return Context->StreamSizes[StreamIndex];
108}
109
110llvm::ArrayRef<uint32_t>
111PDBFile::getStreamBlockList(uint32_t StreamIndex) const {
112 auto &Data = Context->StreamMap[StreamIndex];
113 return llvm::ArrayRef<uint32_t>(Data);
114}
115
116StringRef PDBFile::getBlockData(uint32_t BlockIndex, uint32_t NumBytes) const {
117 uint64_t StreamBlockOffset = blockToOffset(BlockIndex, getBlockSize());
118
119 return StringRef(Context->Buffer->getBufferStart() + StreamBlockOffset,
120 NumBytes);
121}
122
Zachary Turner819e77d2016-05-06 20:51:57 +0000123Error PDBFile::parseFileHeaders() {
Zachary Turner0a43efe2016-04-25 17:38:08 +0000124 std::error_code EC;
125 MemoryBufferRef BufferRef = *Context->Buffer;
Zachary Turnerf5c59652016-05-03 00:28:21 +0000126 // Make sure the file is sufficiently large to hold a super block.
127 // Do this before attempting to read the super block.
Zachary Turnerd6192f42016-05-02 22:16:57 +0000128 if (BufferRef.getBufferSize() < sizeof(SuperBlock))
Zachary Turner819e77d2016-05-06 20:51:57 +0000129 return make_error<RawError>(raw_error_code::corrupt_file,
130 "Does not contain superblock");
Zachary Turner0a43efe2016-04-25 17:38:08 +0000131
132 Context->SB =
133 reinterpret_cast<const SuperBlock *>(BufferRef.getBufferStart());
134 const SuperBlock *SB = Context->SB;
Zachary Turner819e77d2016-05-06 20:51:57 +0000135 // Check the magic bytes.
136 if (memcmp(SB->MagicBytes, Magic, sizeof(Magic)) != 0)
137 return make_error<RawError>(raw_error_code::corrupt_file,
138 "MSF magic header doesn't match");
139
140 if (BufferRef.getBufferSize() % SB->BlockSize != 0)
141 return make_error<RawError>(raw_error_code::corrupt_file,
142 "File size is not a multiple of block size");
143
Zachary Turner9213ba52016-04-29 18:09:19 +0000144 switch (SB->BlockSize) {
145 case 512: case 1024: case 2048: case 4096:
146 break;
147 default:
148 // An invalid block size suggests a corrupt PDB file.
Zachary Turner819e77d2016-05-06 20:51:57 +0000149 return make_error<RawError>(raw_error_code::corrupt_file,
150 "Unsupported block size.");
Zachary Turner9213ba52016-04-29 18:09:19 +0000151 }
Zachary Turner0a43efe2016-04-25 17:38:08 +0000152
153 // We don't support blocksizes which aren't a multiple of four bytes.
Zachary Turner819e77d2016-05-06 20:51:57 +0000154 if (SB->BlockSize % sizeof(support::ulittle32_t) != 0)
155 return make_error<RawError>(raw_error_code::corrupt_file,
156 "Block size is not multiple of 4.");
Zachary Turner0a43efe2016-04-25 17:38:08 +0000157
158 // We don't support directories whose sizes aren't a multiple of four bytes.
159 if (SB->NumDirectoryBytes % sizeof(support::ulittle32_t) != 0)
Zachary Turner819e77d2016-05-06 20:51:57 +0000160 return make_error<RawError>(raw_error_code::corrupt_file,
161 "Directory size is not multiple of 4.");
Zachary Turner0a43efe2016-04-25 17:38:08 +0000162
163 // The number of blocks which comprise the directory is a simple function of
164 // the number of bytes it contains.
165 uint64_t NumDirectoryBlocks = getNumDirectoryBlocks();
166
167 // The block map, as we understand it, is a block which consists of a list of
168 // block numbers.
169 // It is unclear what would happen if the number of blocks couldn't fit on a
170 // single block.
171 if (NumDirectoryBlocks > SB->BlockSize / sizeof(support::ulittle32_t))
Zachary Turner819e77d2016-05-06 20:51:57 +0000172 return make_error<RawError>(raw_error_code::corrupt_file,
173 "Too many directory blocks.");
Zachary Turner0a43efe2016-04-25 17:38:08 +0000174
Zachary Turner819e77d2016-05-06 20:51:57 +0000175 return Error::success();
Zachary Turner0a43efe2016-04-25 17:38:08 +0000176}
177
Zachary Turner819e77d2016-05-06 20:51:57 +0000178Error PDBFile::parseStreamData() {
Zachary Turner0a43efe2016-04-25 17:38:08 +0000179 assert(Context && Context->SB);
180
181 bool SeenNumStreams = false;
182 uint32_t NumStreams = 0;
183 uint32_t StreamIdx = 0;
184 uint64_t DirectoryBytesRead = 0;
185
186 MemoryBufferRef M = *Context->Buffer;
187 const SuperBlock *SB = Context->SB;
188
189 auto DirectoryBlocks = getDirectoryBlockArray();
190
191 // The structure of the directory is as follows:
192 // struct PDBDirectory {
193 // uint32_t NumStreams;
194 // uint32_t StreamSizes[NumStreams];
195 // uint32_t StreamMap[NumStreams][];
196 // };
197 //
198 // Empty streams don't consume entries in the StreamMap.
199 for (uint32_t DirectoryBlockAddr : DirectoryBlocks) {
200 uint64_t DirectoryBlockOffset =
201 blockToOffset(DirectoryBlockAddr, SB->BlockSize);
202 auto DirectoryBlock =
203 makeArrayRef(reinterpret_cast<const support::ulittle32_t *>(
204 M.getBufferStart() + DirectoryBlockOffset),
205 SB->BlockSize / sizeof(support::ulittle32_t));
206 if (auto EC = checkOffset(M, DirectoryBlock))
207 return EC;
208
209 // We read data out of the directory four bytes at a time. Depending on
210 // where we are in the directory, the contents may be: the number of streams
211 // in the directory, a stream's size, or a block in the stream map.
212 for (uint32_t Data : DirectoryBlock) {
213 // Don't read beyond the end of the directory.
214 if (DirectoryBytesRead == SB->NumDirectoryBytes)
215 break;
216
217 DirectoryBytesRead += sizeof(Data);
218
219 // This data must be the number of streams if we haven't seen it yet.
220 if (!SeenNumStreams) {
221 NumStreams = Data;
222 SeenNumStreams = true;
223 continue;
224 }
225 // This data must be a stream size if we have not seen them all yet.
226 if (Context->StreamSizes.size() < NumStreams) {
227 // It seems like some streams have their set to -1 when their contents
228 // are not present. Treat them like empty streams for now.
229 if (Data == UINT32_MAX)
230 Context->StreamSizes.push_back(0);
231 else
232 Context->StreamSizes.push_back(Data);
233 continue;
234 }
235
236 // This data must be a stream block number if we have seen all of the
237 // stream sizes.
238 std::vector<uint32_t> *StreamBlocks = nullptr;
239 // Figure out which stream this block number belongs to.
240 while (StreamIdx < NumStreams) {
241 uint64_t NumExpectedStreamBlocks =
242 bytesToBlocks(Context->StreamSizes[StreamIdx], SB->BlockSize);
243 StreamBlocks = &Context->StreamMap[StreamIdx];
244 if (NumExpectedStreamBlocks > StreamBlocks->size())
245 break;
246 ++StreamIdx;
247 }
248 // It seems this block doesn't belong to any stream? The stream is either
249 // corrupt or something more mysterious is going on.
250 if (StreamIdx == NumStreams)
Zachary Turner819e77d2016-05-06 20:51:57 +0000251 return make_error<RawError>(raw_error_code::corrupt_file,
252 "Orphaned block found?");
Zachary Turner0a43efe2016-04-25 17:38:08 +0000253
254 StreamBlocks->push_back(Data);
255 }
256 }
257
258 // We should have read exactly SB->NumDirectoryBytes bytes.
259 assert(DirectoryBytesRead == SB->NumDirectoryBytes);
Zachary Turner819e77d2016-05-06 20:51:57 +0000260 return Error::success();
Zachary Turner0a43efe2016-04-25 17:38:08 +0000261}
262
263llvm::ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() {
264 return makeArrayRef(
265 reinterpret_cast<const support::ulittle32_t *>(
266 Context->Buffer->getBufferStart() + getBlockMapOffset()),
267 getNumDirectoryBlocks());
268}
Zachary Turner53a65ba2016-04-26 18:42:34 +0000269
Zachary Turner819e77d2016-05-06 20:51:57 +0000270Expected<InfoStream &> PDBFile::getPDBInfoStream() {
Zachary Turner2f09b502016-04-29 17:28:47 +0000271 if (!Info) {
272 Info.reset(new InfoStream(*this));
Zachary Turner819e77d2016-05-06 20:51:57 +0000273 if (auto EC = Info->reload())
274 return std::move(EC);
Zachary Turner53a65ba2016-04-26 18:42:34 +0000275 }
Zachary Turner2f09b502016-04-29 17:28:47 +0000276 return *Info;
Zachary Turner53a65ba2016-04-26 18:42:34 +0000277}
278
Zachary Turner819e77d2016-05-06 20:51:57 +0000279Expected<DbiStream &> PDBFile::getPDBDbiStream() {
Zachary Turner2f09b502016-04-29 17:28:47 +0000280 if (!Dbi) {
281 Dbi.reset(new DbiStream(*this));
Zachary Turner819e77d2016-05-06 20:51:57 +0000282 if (auto EC = Dbi->reload())
283 return std::move(EC);
Zachary Turner53a65ba2016-04-26 18:42:34 +0000284 }
Zachary Turner2f09b502016-04-29 17:28:47 +0000285 return *Dbi;
Zachary Turner53a65ba2016-04-26 18:42:34 +0000286}
Zachary Turnerf5c59652016-05-03 00:28:21 +0000287
Zachary Turner819e77d2016-05-06 20:51:57 +0000288Expected<TpiStream &> PDBFile::getPDBTpiStream() {
Zachary Turnerf5c59652016-05-03 00:28:21 +0000289 if (!Tpi) {
290 Tpi.reset(new TpiStream(*this));
Zachary Turner819e77d2016-05-06 20:51:57 +0000291 if (auto EC = Tpi->reload())
292 return std::move(EC);
Zachary Turnerf5c59652016-05-03 00:28:21 +0000293 }
294 return *Tpi;
295}
Rui Ueyama1f6b6e22016-05-13 21:21:53 +0000296
297Expected<PublicsStream &> PDBFile::getPDBPublicsStream() {
298 if (!Publics) {
299 auto DbiS = getPDBDbiStream();
300 if (auto EC = DbiS.takeError())
301 return std::move(EC);
302 uint32_t PublicsStreamNum = DbiS->getPublicSymbolStreamIndex();
303
304 Publics.reset(new PublicsStream(*this, PublicsStreamNum));
305 if (auto EC = Publics->reload())
306 return std::move(EC);
307 }
308 return *Publics;
309}