1//===- RawTypes.h -----------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H
10#define LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H
11
12#include "llvm/DebugInfo/CodeView/GUID.h"
13#include "llvm/DebugInfo/CodeView/TypeRecord.h"
14#include "llvm/Support/Endian.h"
15
16namespace llvm {
17namespace pdb {
18// This struct is defined as "SO" in langapi/include/pdb.h.
19struct SectionOffset {
20  support::ulittle32_t Off;
21  support::ulittle16_t Isect;
22  char Padding[2];
23};
24
25/// Header of the hash tables found in the globals and publics sections.
26/// Based on GSIHashHdr in
27/// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
28struct GSIHashHeader {
29  enum : unsigned {
30    HdrSignature = ~0U,
31    HdrVersion = 0xeffe0000 + 19990810,
32  };
33  support::ulittle32_t VerSignature;
34  support::ulittle32_t VerHdr;
35  support::ulittle32_t HrSize;
36  support::ulittle32_t NumBuckets;
37};
38
39// This is HRFile.
40struct PSHashRecord {
41  support::ulittle32_t Off; // Offset in the symbol record stream
42  support::ulittle32_t CRef;
43};
44
45// This struct is defined as `SC` in include/dbicommon.h
46struct SectionContrib {
47  support::ulittle16_t ISect;
48  char Padding[2];
49  support::little32_t Off;
50  support::little32_t Size;
51  support::ulittle32_t Characteristics;
52  support::ulittle16_t Imod;
53  char Padding2[2];
54  support::ulittle32_t DataCrc;
55  support::ulittle32_t RelocCrc;
56};
57
58// This struct is defined as `SC2` in include/dbicommon.h
59struct SectionContrib2 {
60  // To guarantee SectionContrib2 is standard layout, we cannot use inheritance.
61  SectionContrib Base;
62  support::ulittle32_t ISectCoff;
63};
64
65// This corresponds to the `OMFSegMap` structure.
66struct SecMapHeader {
67  support::ulittle16_t SecCount;    // Number of segment descriptors in table
68  support::ulittle16_t SecCountLog; // Number of logical segment descriptors
69};
70
71// This corresponds to the `OMFSegMapDesc` structure.  The definition is not
72// present in the reference implementation, but the layout is derived from
73// code that accesses the fields.
74struct SecMapEntry {
75  support::ulittle16_t Flags; // Descriptor flags.  See OMFSegDescFlags
76  support::ulittle16_t Ovl;   // Logical overlay number.
77  support::ulittle16_t Group; // Group index into descriptor array.
78  support::ulittle16_t Frame;
79  support::ulittle16_t SecName;       // Byte index of the segment or group name
80                                      // in the sstSegName table, or 0xFFFF.
81  support::ulittle16_t ClassName;     // Byte index of the class name in the
82                                      // sstSegName table, or 0xFFFF.
83  support::ulittle32_t Offset;        // Byte offset of the logical segment
84                                      // within the specified physical segment.
85                                      // If group is set in flags, offset is the
86                                      // offset of the group.
87  support::ulittle32_t SecByteLength; // Byte count of the segment or group.
88};
89
90/// Some of the values are stored in bitfields.  Since this needs to be portable
91/// across compilers and architectures (big / little endian in particular) we
92/// can't use the actual structures below, but must instead do the shifting
93/// and masking ourselves.  The struct definitions are provided for reference.
94struct DbiFlags {
95  ///  uint16_t IncrementalLinking : 1; // True if linked incrementally
96  ///  uint16_t IsStripped : 1;         // True if private symbols were
97  ///  stripped.
98  ///  uint16_t HasCTypes : 1;          // True if linked with /debug:ctypes.
99  ///  uint16_t Reserved : 13;
100  static const uint16_t FlagIncrementalMask = 0x0001;
101  static const uint16_t FlagStrippedMask = 0x0002;
102  static const uint16_t FlagHasCTypesMask = 0x0004;
103};
104
105struct DbiBuildNo {
106  ///  uint16_t MinorVersion : 8;
107  ///  uint16_t MajorVersion : 7;
108  ///  uint16_t NewVersionFormat : 1;
109  static const uint16_t BuildMinorMask = 0x00FF;
110  static const uint16_t BuildMinorShift = 0;
111
112  static const uint16_t BuildMajorMask = 0x7F00;
113  static const uint16_t BuildMajorShift = 8;
114
115  static const uint16_t NewVersionFormatMask = 0x8000;
116};
117
118/// The fixed size header that appears at the beginning of the DBI Stream.
119struct DbiStreamHeader {
120  support::little32_t VersionSignature;
121  support::ulittle32_t VersionHeader;
122
123  /// How "old" is this DBI Stream. Should match the age of the PDB InfoStream.
124  support::ulittle32_t Age;
125
126  /// Global symbol stream #
127  support::ulittle16_t GlobalSymbolStreamIndex;
128
129  /// See DbiBuildNo structure.
130  support::ulittle16_t BuildNumber;
131
132  /// Public symbols stream #
133  support::ulittle16_t PublicSymbolStreamIndex;
134
135  /// version of mspdbNNN.dll
136  support::ulittle16_t PdbDllVersion;
137
138  /// Symbol records stream #
139  support::ulittle16_t SymRecordStreamIndex;
140
141  /// rbld number of mspdbNNN.dll
142  support::ulittle16_t PdbDllRbld;
143
144  /// Size of module info stream
145  support::little32_t ModiSubstreamSize;
146
147  /// Size of sec. contrib stream
148  support::little32_t SecContrSubstreamSize;
149
150  /// Size of sec. map substream
151  support::little32_t SectionMapSize;
152
153  /// Size of file info substream
154  support::little32_t FileInfoSize;
155
156  /// Size of type server map
157  support::little32_t TypeServerSize;
158
159  /// Index of MFC Type Server
160  support::ulittle32_t MFCTypeServerIndex;
161
162  /// Size of DbgHeader info
163  support::little32_t OptionalDbgHdrSize;
164
165  /// Size of EC stream (what is EC?)
166  support::little32_t ECSubstreamSize;
167
168  /// See DbiFlags enum.
169  support::ulittle16_t Flags;
170
171  /// See PDB_MachineType enum.
172  support::ulittle16_t MachineType;
173
174  /// Pad to 64 bytes
175  support::ulittle32_t Reserved;
176};
177static_assert(sizeof(DbiStreamHeader) == 64, "Invalid DbiStreamHeader size!");
178
179/// The header preceding the File Info Substream of the DBI stream.
180struct FileInfoSubstreamHeader {
181  /// Total # of modules, should match number of records in the ModuleInfo
182  /// substream.
183  support::ulittle16_t NumModules;
184
185  /// Total # of source files. This value is not accurate because PDB actually
186  /// supports more than 64k source files, so we ignore it and compute the value
187  /// from other stream fields.
188  support::ulittle16_t NumSourceFiles;
189
190  /// Following this header the File Info Substream is laid out as follows:
191  ///   ulittle16_t ModIndices[NumModules];
192  ///   ulittle16_t ModFileCounts[NumModules];
193  ///   ulittle32_t FileNameOffsets[NumSourceFiles];
194  ///   char Names[][NumSourceFiles];
195  /// with the caveat that `NumSourceFiles` cannot be trusted, so
196  /// it is computed by summing the `ModFileCounts` array.
197};
198
199struct ModInfoFlags {
200  ///  uint16_t fWritten : 1;   // True if DbiModuleDescriptor is dirty
201  ///  uint16_t fECEnabled : 1; // Is EC symbolic info present?  (What is EC?)
202  ///  uint16_t unused : 6;     // Reserved
203  ///  uint16_t iTSM : 8;       // Type Server Index for this module
204  static const uint16_t HasECFlagMask = 0x2;
205
206  static const uint16_t TypeServerIndexMask = 0xFF00;
207  static const uint16_t TypeServerIndexShift = 8;
208};
209
210/// The header preceding each entry in the Module Info substream of the DBI
211/// stream.  Corresponds to the type MODI in the reference implementation.
212struct ModuleInfoHeader {
213  /// Currently opened module. This field is a pointer in the reference
214  /// implementation, but that won't work on 64-bit systems, and anyway it
215  /// doesn't make sense to read a pointer from a file. For now it is unused,
216  /// so just ignore it.
217  support::ulittle32_t Mod;
218
219  /// First section contribution of this module.
220  SectionContrib SC;
221
222  /// See ModInfoFlags definition.
223  support::ulittle16_t Flags;
224
225  /// Stream Number of module debug info
226  support::ulittle16_t ModDiStream;
227
228  /// Size of local symbol debug info in above stream
229  support::ulittle32_t SymBytes;
230
231  /// Size of C11 line number info in above stream
232  support::ulittle32_t C11Bytes;
233
234  /// Size of C13 line number info in above stream
235  support::ulittle32_t C13Bytes;
236
237  /// Number of files contributing to this module
238  support::ulittle16_t NumFiles;
239
240  /// Padding so the next field is 4-byte aligned.
241  char Padding1[2];
242
243  /// Array of [0..NumFiles) DBI name buffer offsets.  In the reference
244  /// implementation this field is a pointer.  But since you can't portably
245  /// serialize a pointer, on 64-bit platforms they copy all the values except
246  /// this one into the 32-bit version of the struct and use that for
247  /// serialization.  Regardless, this field is unused, it is only there to
248  /// store a pointer that can be accessed at runtime.
249  support::ulittle32_t FileNameOffs;
250
251  /// Name Index for src file name
252  support::ulittle32_t SrcFileNameNI;
253
254  /// Name Index for path to compiler PDB
255  support::ulittle32_t PdbFilePathNI;
256
257  /// Following this header are two zero terminated strings.
258  /// char ModuleName[];
259  /// char ObjFileName[];
260};
261
262// This is PSGSIHDR struct defined in
263// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
264struct PublicsStreamHeader {
265  support::ulittle32_t SymHash;
266  support::ulittle32_t AddrMap;
267  support::ulittle32_t NumThunks;
268  support::ulittle32_t SizeOfThunk;
269  support::ulittle16_t ISectThunkTable;
270  char Padding[2];
271  support::ulittle32_t OffThunkTable;
272  support::ulittle32_t NumSections;
273};
274
275// The header preceding the global TPI stream.
276// This corresponds to `HDR` in PDB/dbi/tpi.h.
277struct TpiStreamHeader {
278  struct EmbeddedBuf {
279    support::little32_t Off;
280    support::ulittle32_t Length;
281  };
282
283  support::ulittle32_t Version;
284  support::ulittle32_t HeaderSize;
285  support::ulittle32_t TypeIndexBegin;
286  support::ulittle32_t TypeIndexEnd;
287  support::ulittle32_t TypeRecordBytes;
288
289  // The following members correspond to `TpiHash` in PDB/dbi/tpi.h.
290  support::ulittle16_t HashStreamIndex;
291  support::ulittle16_t HashAuxStreamIndex;
292  support::ulittle32_t HashKeySize;
293  support::ulittle32_t NumHashBuckets;
294
295  EmbeddedBuf HashValueBuffer;
296  EmbeddedBuf IndexOffsetBuffer;
297  EmbeddedBuf HashAdjBuffer;
298};
299
300const uint32_t MinTpiHashBuckets = 0x1000;
301const uint32_t MaxTpiHashBuckets = 0x40000;
302
303/// The header preceding the global PDB Stream (Stream 1)
304struct InfoStreamHeader {
305  support::ulittle32_t Version;
306  support::ulittle32_t Signature;
307  support::ulittle32_t Age;
308  codeview::GUID Guid;
309};
310
311/// The header preceding the /names stream.
312struct PDBStringTableHeader {
313  support::ulittle32_t Signature;   // PDBStringTableSignature
314  support::ulittle32_t HashVersion; // 1 or 2
315  support::ulittle32_t ByteSize;    // Number of bytes of names buffer.
316};
317
318const uint32_t PDBStringTableSignature = 0xEFFEEFFE;
319
320/// The header preceding the /src/headerblock stream.
321struct SrcHeaderBlockHeader {
322  support::ulittle32_t Version; // PdbRaw_SrcHeaderBlockVer enumeration.
323  support::ulittle32_t Size;    // Size of entire stream.
324  uint64_t FileTime;            // Time stamp (Windows FILETIME format).
325  support::ulittle32_t Age;     // Age
326  uint8_t Padding[44];          // Pad to 64 bytes.
327};
328static_assert(sizeof(SrcHeaderBlockHeader) == 64, "Incorrect struct size!");
329
330/// A single file record entry within the /src/headerblock stream.
331struct SrcHeaderBlockEntry {
332  support::ulittle32_t Size;     // Record Length.
333  support::ulittle32_t Version;  // PdbRaw_SrcHeaderBlockVer enumeration.
334  support::ulittle32_t CRC;      // CRC of the original file contents.
335  support::ulittle32_t FileSize; // Size of original source file.
336  support::ulittle32_t FileNI;   // String table index of file name.
337  support::ulittle32_t ObjNI;    // String table index of object name.
338  support::ulittle32_t VFileNI;  // String table index of virtual file name.
339  uint8_t Compression;           // PDB_SourceCompression enumeration.
340  uint8_t IsVirtual;             // Is this a virtual file (injected)?
341  short Padding;                 // Pad to 4 bytes.
342  char Reserved[8];
343};
344static_assert(sizeof(SrcHeaderBlockEntry) == 40, "Incorrect struct size!");
345
346} // namespace pdb
347} // namespace llvm
348
349#endif
350