1317017Sdim//===- RawTypes.h -----------------------------------------------*- C++ -*-===//
2317017Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6317017Sdim//
7317017Sdim//===----------------------------------------------------------------------===//
8317017Sdim
9317017Sdim#ifndef LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H
10317017Sdim#define LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H
11317017Sdim
12321238Sdim#include "llvm/DebugInfo/CodeView/GUID.h"
13317017Sdim#include "llvm/DebugInfo/CodeView/TypeRecord.h"
14317017Sdim#include "llvm/Support/Endian.h"
15317017Sdim
16317017Sdimnamespace llvm {
17317017Sdimnamespace pdb {
18317017Sdim// This struct is defined as "SO" in langapi/include/pdb.h.
19317017Sdimstruct SectionOffset {
20317017Sdim  support::ulittle32_t Off;
21317017Sdim  support::ulittle16_t Isect;
22317017Sdim  char Padding[2];
23317017Sdim};
24317017Sdim
25327952Sdim/// Header of the hash tables found in the globals and publics sections.
26327952Sdim/// Based on GSIHashHdr in
27327952Sdim/// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
28327952Sdimstruct GSIHashHeader {
29327952Sdim  enum : unsigned {
30327952Sdim    HdrSignature = ~0U,
31327952Sdim    HdrVersion = 0xeffe0000 + 19990810,
32327952Sdim  };
33327952Sdim  support::ulittle32_t VerSignature;
34327952Sdim  support::ulittle32_t VerHdr;
35327952Sdim  support::ulittle32_t HrSize;
36327952Sdim  support::ulittle32_t NumBuckets;
37327952Sdim};
38327952Sdim
39317017Sdim// This is HRFile.
40317017Sdimstruct PSHashRecord {
41317017Sdim  support::ulittle32_t Off; // Offset in the symbol record stream
42317017Sdim  support::ulittle32_t CRef;
43317017Sdim};
44317017Sdim
45317017Sdim// This struct is defined as `SC` in include/dbicommon.h
46317017Sdimstruct SectionContrib {
47317017Sdim  support::ulittle16_t ISect;
48317017Sdim  char Padding[2];
49317017Sdim  support::little32_t Off;
50317017Sdim  support::little32_t Size;
51317017Sdim  support::ulittle32_t Characteristics;
52317017Sdim  support::ulittle16_t Imod;
53317017Sdim  char Padding2[2];
54317017Sdim  support::ulittle32_t DataCrc;
55317017Sdim  support::ulittle32_t RelocCrc;
56317017Sdim};
57317017Sdim
58317017Sdim// This struct is defined as `SC2` in include/dbicommon.h
59317017Sdimstruct SectionContrib2 {
60317017Sdim  // To guarantee SectionContrib2 is standard layout, we cannot use inheritance.
61317017Sdim  SectionContrib Base;
62317017Sdim  support::ulittle32_t ISectCoff;
63317017Sdim};
64317017Sdim
65317017Sdim// This corresponds to the `OMFSegMap` structure.
66317017Sdimstruct SecMapHeader {
67317017Sdim  support::ulittle16_t SecCount;    // Number of segment descriptors in table
68317017Sdim  support::ulittle16_t SecCountLog; // Number of logical segment descriptors
69317017Sdim};
70317017Sdim
71317017Sdim// This corresponds to the `OMFSegMapDesc` structure.  The definition is not
72317017Sdim// present in the reference implementation, but the layout is derived from
73317017Sdim// code that accesses the fields.
74317017Sdimstruct SecMapEntry {
75317017Sdim  support::ulittle16_t Flags; // Descriptor flags.  See OMFSegDescFlags
76317017Sdim  support::ulittle16_t Ovl;   // Logical overlay number.
77317017Sdim  support::ulittle16_t Group; // Group index into descriptor array.
78317017Sdim  support::ulittle16_t Frame;
79317017Sdim  support::ulittle16_t SecName;       // Byte index of the segment or group name
80317017Sdim                                      // in the sstSegName table, or 0xFFFF.
81317017Sdim  support::ulittle16_t ClassName;     // Byte index of the class name in the
82317017Sdim                                      // sstSegName table, or 0xFFFF.
83317017Sdim  support::ulittle32_t Offset;        // Byte offset of the logical segment
84317017Sdim                                      // within the specified physical segment.
85317017Sdim                                      // If group is set in flags, offset is the
86317017Sdim                                      // offset of the group.
87317017Sdim  support::ulittle32_t SecByteLength; // Byte count of the segment or group.
88317017Sdim};
89317017Sdim
90317017Sdim/// Some of the values are stored in bitfields.  Since this needs to be portable
91317017Sdim/// across compilers and architectures (big / little endian in particular) we
92317017Sdim/// can't use the actual structures below, but must instead do the shifting
93317017Sdim/// and masking ourselves.  The struct definitions are provided for reference.
94317017Sdimstruct DbiFlags {
95317017Sdim  ///  uint16_t IncrementalLinking : 1; // True if linked incrementally
96317017Sdim  ///  uint16_t IsStripped : 1;         // True if private symbols were
97317017Sdim  ///  stripped.
98317017Sdim  ///  uint16_t HasCTypes : 1;          // True if linked with /debug:ctypes.
99317017Sdim  ///  uint16_t Reserved : 13;
100317017Sdim  static const uint16_t FlagIncrementalMask = 0x0001;
101317017Sdim  static const uint16_t FlagStrippedMask = 0x0002;
102317017Sdim  static const uint16_t FlagHasCTypesMask = 0x0004;
103317017Sdim};
104317017Sdim
105317017Sdimstruct DbiBuildNo {
106317017Sdim  ///  uint16_t MinorVersion : 8;
107317017Sdim  ///  uint16_t MajorVersion : 7;
108317017Sdim  ///  uint16_t NewVersionFormat : 1;
109317017Sdim  static const uint16_t BuildMinorMask = 0x00FF;
110317017Sdim  static const uint16_t BuildMinorShift = 0;
111317017Sdim
112317017Sdim  static const uint16_t BuildMajorMask = 0x7F00;
113317017Sdim  static const uint16_t BuildMajorShift = 8;
114341825Sdim
115341825Sdim  static const uint16_t NewVersionFormatMask = 0x8000;
116317017Sdim};
117317017Sdim
118317017Sdim/// The fixed size header that appears at the beginning of the DBI Stream.
119317017Sdimstruct DbiStreamHeader {
120317017Sdim  support::little32_t VersionSignature;
121317017Sdim  support::ulittle32_t VersionHeader;
122317017Sdim
123317017Sdim  /// How "old" is this DBI Stream. Should match the age of the PDB InfoStream.
124317017Sdim  support::ulittle32_t Age;
125317017Sdim
126317017Sdim  /// Global symbol stream #
127317017Sdim  support::ulittle16_t GlobalSymbolStreamIndex;
128317017Sdim
129317017Sdim  /// See DbiBuildNo structure.
130317017Sdim  support::ulittle16_t BuildNumber;
131317017Sdim
132317017Sdim  /// Public symbols stream #
133317017Sdim  support::ulittle16_t PublicSymbolStreamIndex;
134317017Sdim
135317017Sdim  /// version of mspdbNNN.dll
136317017Sdim  support::ulittle16_t PdbDllVersion;
137317017Sdim
138317017Sdim  /// Symbol records stream #
139317017Sdim  support::ulittle16_t SymRecordStreamIndex;
140317017Sdim
141317017Sdim  /// rbld number of mspdbNNN.dll
142317017Sdim  support::ulittle16_t PdbDllRbld;
143317017Sdim
144317017Sdim  /// Size of module info stream
145317017Sdim  support::little32_t ModiSubstreamSize;
146317017Sdim
147317017Sdim  /// Size of sec. contrib stream
148317017Sdim  support::little32_t SecContrSubstreamSize;
149317017Sdim
150317017Sdim  /// Size of sec. map substream
151317017Sdim  support::little32_t SectionMapSize;
152317017Sdim
153317017Sdim  /// Size of file info substream
154317017Sdim  support::little32_t FileInfoSize;
155317017Sdim
156317017Sdim  /// Size of type server map
157317017Sdim  support::little32_t TypeServerSize;
158317017Sdim
159317017Sdim  /// Index of MFC Type Server
160317017Sdim  support::ulittle32_t MFCTypeServerIndex;
161317017Sdim
162317017Sdim  /// Size of DbgHeader info
163317017Sdim  support::little32_t OptionalDbgHdrSize;
164317017Sdim
165317017Sdim  /// Size of EC stream (what is EC?)
166317017Sdim  support::little32_t ECSubstreamSize;
167317017Sdim
168317017Sdim  /// See DbiFlags enum.
169317017Sdim  support::ulittle16_t Flags;
170317017Sdim
171317017Sdim  /// See PDB_MachineType enum.
172317017Sdim  support::ulittle16_t MachineType;
173317017Sdim
174317017Sdim  /// Pad to 64 bytes
175317017Sdim  support::ulittle32_t Reserved;
176317017Sdim};
177317017Sdimstatic_assert(sizeof(DbiStreamHeader) == 64, "Invalid DbiStreamHeader size!");
178317017Sdim
179353358Sdim/// The header preceding the File Info Substream of the DBI stream.
180317017Sdimstruct FileInfoSubstreamHeader {
181317017Sdim  /// Total # of modules, should match number of records in the ModuleInfo
182317017Sdim  /// substream.
183317017Sdim  support::ulittle16_t NumModules;
184317017Sdim
185317017Sdim  /// Total # of source files. This value is not accurate because PDB actually
186317017Sdim  /// supports more than 64k source files, so we ignore it and compute the value
187317017Sdim  /// from other stream fields.
188317017Sdim  support::ulittle16_t NumSourceFiles;
189317017Sdim
190317017Sdim  /// Following this header the File Info Substream is laid out as follows:
191317017Sdim  ///   ulittle16_t ModIndices[NumModules];
192317017Sdim  ///   ulittle16_t ModFileCounts[NumModules];
193317017Sdim  ///   ulittle32_t FileNameOffsets[NumSourceFiles];
194317017Sdim  ///   char Names[][NumSourceFiles];
195317017Sdim  /// with the caveat that `NumSourceFiles` cannot be trusted, so
196317017Sdim  /// it is computed by summing the `ModFileCounts` array.
197317017Sdim};
198317017Sdim
199317017Sdimstruct ModInfoFlags {
200317778Sdim  ///  uint16_t fWritten : 1;   // True if DbiModuleDescriptor is dirty
201317017Sdim  ///  uint16_t fECEnabled : 1; // Is EC symbolic info present?  (What is EC?)
202317017Sdim  ///  uint16_t unused : 6;     // Reserved
203317017Sdim  ///  uint16_t iTSM : 8;       // Type Server Index for this module
204317017Sdim  static const uint16_t HasECFlagMask = 0x2;
205317017Sdim
206317017Sdim  static const uint16_t TypeServerIndexMask = 0xFF00;
207317017Sdim  static const uint16_t TypeServerIndexShift = 8;
208317017Sdim};
209317017Sdim
210353358Sdim/// The header preceding each entry in the Module Info substream of the DBI
211317969Sdim/// stream.  Corresponds to the type MODI in the reference implementation.
212317017Sdimstruct ModuleInfoHeader {
213317017Sdim  /// Currently opened module. This field is a pointer in the reference
214317017Sdim  /// implementation, but that won't work on 64-bit systems, and anyway it
215317017Sdim  /// doesn't make sense to read a pointer from a file. For now it is unused,
216317017Sdim  /// so just ignore it.
217317017Sdim  support::ulittle32_t Mod;
218317017Sdim
219317017Sdim  /// First section contribution of this module.
220341825Sdim  SectionContrib SC;
221317017Sdim
222317017Sdim  /// See ModInfoFlags definition.
223317017Sdim  support::ulittle16_t Flags;
224317017Sdim
225317017Sdim  /// Stream Number of module debug info
226317017Sdim  support::ulittle16_t ModDiStream;
227317017Sdim
228317017Sdim  /// Size of local symbol debug info in above stream
229317017Sdim  support::ulittle32_t SymBytes;
230317017Sdim
231317778Sdim  /// Size of C11 line number info in above stream
232317778Sdim  support::ulittle32_t C11Bytes;
233317017Sdim
234317017Sdim  /// Size of C13 line number info in above stream
235317017Sdim  support::ulittle32_t C13Bytes;
236317017Sdim
237317017Sdim  /// Number of files contributing to this module
238317017Sdim  support::ulittle16_t NumFiles;
239317017Sdim
240317017Sdim  /// Padding so the next field is 4-byte aligned.
241317017Sdim  char Padding1[2];
242317017Sdim
243317969Sdim  /// Array of [0..NumFiles) DBI name buffer offsets.  In the reference
244317969Sdim  /// implementation this field is a pointer.  But since you can't portably
245317969Sdim  /// serialize a pointer, on 64-bit platforms they copy all the values except
246317969Sdim  /// this one into the 32-bit version of the struct and use that for
247317969Sdim  /// serialization.  Regardless, this field is unused, it is only there to
248317969Sdim  /// store a pointer that can be accessed at runtime.
249317017Sdim  support::ulittle32_t FileNameOffs;
250317017Sdim
251317017Sdim  /// Name Index for src file name
252317017Sdim  support::ulittle32_t SrcFileNameNI;
253317017Sdim
254317017Sdim  /// Name Index for path to compiler PDB
255317017Sdim  support::ulittle32_t PdbFilePathNI;
256317017Sdim
257317017Sdim  /// Following this header are two zero terminated strings.
258317017Sdim  /// char ModuleName[];
259317017Sdim  /// char ObjFileName[];
260317017Sdim};
261317017Sdim
262320970Sdim// This is PSGSIHDR struct defined in
263320970Sdim// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
264320970Sdimstruct PublicsStreamHeader {
265320970Sdim  support::ulittle32_t SymHash;
266320970Sdim  support::ulittle32_t AddrMap;
267320970Sdim  support::ulittle32_t NumThunks;
268320970Sdim  support::ulittle32_t SizeOfThunk;
269320970Sdim  support::ulittle16_t ISectThunkTable;
270320970Sdim  char Padding[2];
271320970Sdim  support::ulittle32_t OffThunkTable;
272320970Sdim  support::ulittle32_t NumSections;
273320970Sdim};
274320970Sdim
275353358Sdim// The header preceding the global TPI stream.
276317017Sdim// This corresponds to `HDR` in PDB/dbi/tpi.h.
277317017Sdimstruct TpiStreamHeader {
278317017Sdim  struct EmbeddedBuf {
279317017Sdim    support::little32_t Off;
280317017Sdim    support::ulittle32_t Length;
281317017Sdim  };
282317017Sdim
283317017Sdim  support::ulittle32_t Version;
284317017Sdim  support::ulittle32_t HeaderSize;
285317017Sdim  support::ulittle32_t TypeIndexBegin;
286317017Sdim  support::ulittle32_t TypeIndexEnd;
287317017Sdim  support::ulittle32_t TypeRecordBytes;
288317017Sdim
289317017Sdim  // The following members correspond to `TpiHash` in PDB/dbi/tpi.h.
290317017Sdim  support::ulittle16_t HashStreamIndex;
291317017Sdim  support::ulittle16_t HashAuxStreamIndex;
292317017Sdim  support::ulittle32_t HashKeySize;
293317017Sdim  support::ulittle32_t NumHashBuckets;
294317017Sdim
295317017Sdim  EmbeddedBuf HashValueBuffer;
296317017Sdim  EmbeddedBuf IndexOffsetBuffer;
297317017Sdim  EmbeddedBuf HashAdjBuffer;
298317017Sdim};
299317017Sdim
300317017Sdimconst uint32_t MinTpiHashBuckets = 0x1000;
301317017Sdimconst uint32_t MaxTpiHashBuckets = 0x40000;
302317017Sdim
303353358Sdim/// The header preceding the global PDB Stream (Stream 1)
304317017Sdimstruct InfoStreamHeader {
305317017Sdim  support::ulittle32_t Version;
306317017Sdim  support::ulittle32_t Signature;
307317017Sdim  support::ulittle32_t Age;
308321238Sdim  codeview::GUID Guid;
309317017Sdim};
310317017Sdim
311353358Sdim/// The header preceding the /names stream.
312317778Sdimstruct PDBStringTableHeader {
313317778Sdim  support::ulittle32_t Signature;   // PDBStringTableSignature
314317778Sdim  support::ulittle32_t HashVersion; // 1 or 2
315317778Sdim  support::ulittle32_t ByteSize;    // Number of bytes of names buffer.
316317017Sdim};
317317017Sdim
318317778Sdimconst uint32_t PDBStringTableSignature = 0xEFFEEFFE;
319317017Sdim
320341825Sdim/// The header preceding the /src/headerblock stream.
321341825Sdimstruct SrcHeaderBlockHeader {
322341825Sdim  support::ulittle32_t Version; // PdbRaw_SrcHeaderBlockVer enumeration.
323341825Sdim  support::ulittle32_t Size;    // Size of entire stream.
324341825Sdim  uint64_t FileTime;            // Time stamp (Windows FILETIME format).
325341825Sdim  support::ulittle32_t Age;     // Age
326341825Sdim  uint8_t Padding[44];          // Pad to 64 bytes.
327341825Sdim};
328341825Sdimstatic_assert(sizeof(SrcHeaderBlockHeader) == 64, "Incorrect struct size!");
329341825Sdim
330341825Sdim/// A single file record entry within the /src/headerblock stream.
331341825Sdimstruct SrcHeaderBlockEntry {
332341825Sdim  support::ulittle32_t Size;     // Record Length.
333341825Sdim  support::ulittle32_t Version;  // PdbRaw_SrcHeaderBlockVer enumeration.
334341825Sdim  support::ulittle32_t CRC;      // CRC of the original file contents.
335341825Sdim  support::ulittle32_t FileSize; // Size of original source file.
336341825Sdim  support::ulittle32_t FileNI;   // String table index of file name.
337341825Sdim  support::ulittle32_t ObjNI;    // String table index of object name.
338341825Sdim  support::ulittle32_t VFileNI;  // String table index of virtual file name.
339341825Sdim  uint8_t Compression;           // PDB_SourceCompression enumeration.
340341825Sdim  uint8_t IsVirtual;             // Is this a virtual file (injected)?
341341825Sdim  short Padding;                 // Pad to 4 bytes.
342341825Sdim  char Reserved[8];
343341825Sdim};
344341825Sdimstatic_assert(sizeof(SrcHeaderBlockEntry) == 40, "Incorrect struct size!");
345341825Sdim
346317017Sdim} // namespace pdb
347317017Sdim} // namespace llvm
348317017Sdim
349317017Sdim#endif
350