1//===- PDBFile.h - 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#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBFILE_H
11#define LLVM_DEBUGINFO_PDB_RAW_PDBFILE_H
12
13#include "llvm/ADT/DenseMap.h"
14#include "llvm/DebugInfo/CodeView/StreamArray.h"
15#include "llvm/DebugInfo/CodeView/StreamInterface.h"
16#include "llvm/DebugInfo/PDB/Raw/IPDBFile.h"
17#include "llvm/Support/Allocator.h"
18#include "llvm/Support/Endian.h"
19#include "llvm/Support/Error.h"
20#include "llvm/Support/MathExtras.h"
21
22#include <memory>
23
24namespace llvm {
25
26namespace codeview {
27class StreamInterface;
28}
29
30namespace pdb {
31class DbiStream;
32class InfoStream;
33class MappedBlockStream;
34class NameHashTable;
35class PDBFileBuilder;
36class PublicsStream;
37class SymbolStream;
38class TpiStream;
39
40static const char MsfMagic[] = {'M',  'i',  'c',    'r', 'o', 's',  'o',  'f',
41                                't',  ' ',  'C',    '/', 'C', '+',  '+',  ' ',
42                                'M',  'S',  'F',    ' ', '7', '.',  '0',  '0',
43                                '\r', '\n', '\x1a', 'D', 'S', '\0', '\0', '\0'};
44
45class PDBFile : public IPDBFile {
46  friend PDBFileBuilder;
47
48public:
49  // The superblock is overlaid at the beginning of the file (offset 0).
50  // It starts with a magic header and is followed by information which
51  // describes the layout of the file system.
52  struct SuperBlock {
53    char MagicBytes[sizeof(MsfMagic)];
54    // The file system is split into a variable number of fixed size elements.
55    // These elements are referred to as blocks.  The size of a block may vary
56    // from system to system.
57    support::ulittle32_t BlockSize;
58    // This field's purpose is not yet known.
59    support::ulittle32_t Unknown0;
60    // This contains the number of blocks resident in the file system.  In
61    // practice, NumBlocks * BlockSize is equivalent to the size of the PDB
62    // file.
63    support::ulittle32_t NumBlocks;
64    // This contains the number of bytes which make up the directory.
65    support::ulittle32_t NumDirectoryBytes;
66    // This field's purpose is not yet known.
67    support::ulittle32_t Unknown1;
68    // This contains the block # of the block map.
69    support::ulittle32_t BlockMapAddr;
70  };
71
72  explicit PDBFile(std::unique_ptr<codeview::StreamInterface> PdbFileBuffer);
73  ~PDBFile() override;
74
75  uint32_t getUnknown0() const;
76  uint32_t getUnknown1() const;
77
78  uint32_t getBlockSize() const override;
79  uint32_t getBlockCount() const override;
80  uint32_t getNumDirectoryBytes() const;
81  uint32_t getBlockMapIndex() const;
82  uint32_t getNumDirectoryBlocks() const;
83  uint64_t getBlockMapOffset() const;
84
85  uint32_t getNumStreams() const override;
86  uint32_t getStreamByteSize(uint32_t StreamIndex) const override;
87  ArrayRef<support::ulittle32_t>
88  getStreamBlockList(uint32_t StreamIndex) const override;
89  uint32_t getFileSize() const;
90
91  Expected<ArrayRef<uint8_t>> getBlockData(uint32_t BlockIndex,
92                                           uint32_t NumBytes) const override;
93  Error setBlockData(uint32_t BlockIndex, uint32_t Offset,
94                     ArrayRef<uint8_t> Data) const override;
95
96  ArrayRef<support::ulittle32_t> getStreamSizes() const { return StreamSizes; }
97  ArrayRef<ArrayRef<support::ulittle32_t>> getStreamMap() const {
98    return StreamMap;
99  }
100
101  ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const;
102
103  Error parseFileHeaders();
104  Error parseStreamData();
105
106  static uint64_t bytesToBlocks(uint64_t NumBytes, uint64_t BlockSize) {
107    return alignTo(NumBytes, BlockSize) / BlockSize;
108  }
109
110  static uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize) {
111    return BlockNumber * BlockSize;
112  }
113
114  Expected<InfoStream &> getPDBInfoStream();
115  Expected<DbiStream &> getPDBDbiStream();
116  Expected<TpiStream &> getPDBTpiStream();
117  Expected<TpiStream &> getPDBIpiStream();
118  Expected<PublicsStream &> getPDBPublicsStream();
119  Expected<SymbolStream &> getPDBSymbolStream();
120  Expected<NameHashTable &> getStringTable();
121
122  Error commit();
123
124private:
125  Error setSuperBlock(const SuperBlock *Block);
126
127  BumpPtrAllocator Allocator;
128
129  std::unique_ptr<codeview::StreamInterface> Buffer;
130  const PDBFile::SuperBlock *SB;
131  ArrayRef<support::ulittle32_t> StreamSizes;
132  ArrayRef<support::ulittle32_t> DirectoryBlocks;
133  std::vector<ArrayRef<support::ulittle32_t>> StreamMap;
134
135  std::unique_ptr<InfoStream> Info;
136  std::unique_ptr<DbiStream> Dbi;
137  std::unique_ptr<TpiStream> Tpi;
138  std::unique_ptr<TpiStream> Ipi;
139  std::unique_ptr<PublicsStream> Publics;
140  std::unique_ptr<SymbolStream> Symbols;
141  std::unique_ptr<MappedBlockStream> DirectoryStream;
142  std::unique_ptr<MappedBlockStream> StringTableStream;
143  std::unique_ptr<NameHashTable> StringTable;
144};
145}
146}
147
148#endif
149