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_NATIVE_RAWTYPES_H
10 #define LLVM_DEBUGINFO_PDB_NATIVE_RAWTYPES_H
11 
12 #include "llvm/DebugInfo/CodeView/GUID.h"
13 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
14 #include "llvm/Support/Endian.h"
15 
16 namespace llvm {
17 namespace pdb {
18 // This struct is defined as "SO" in langapi/include/pdb.h.
19 struct 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
28 struct 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.
40 struct 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
46 struct 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
59 struct 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.
66 struct 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.
74 struct 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.
94 struct 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 
105 struct 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.
119 struct 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 };
177 static_assert(sizeof(DbiStreamHeader) == 64, "Invalid DbiStreamHeader size!");
178 
179 /// The header preceding the File Info Substream of the DBI stream.
180 struct 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 
199 struct 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.
212 struct 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
264 struct 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.
277 struct 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 
300 const uint32_t MinTpiHashBuckets = 0x1000;
301 const uint32_t MaxTpiHashBuckets = 0x40000;
302 
303 /// The header preceding the global PDB Stream (Stream 1)
304 struct 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.
312 struct 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 
318 const uint32_t PDBStringTableSignature = 0xEFFEEFFE;
319 
320 /// The header preceding the /src/headerblock stream.
321 struct 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 };
328 static_assert(sizeof(SrcHeaderBlockHeader) == 64, "Incorrect struct size!");
329 
330 /// A single file record entry within the /src/headerblock stream.
331 struct 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 };
344 static_assert(sizeof(SrcHeaderBlockEntry) == 40, "Incorrect struct size!");
345 
346 } // namespace pdb
347 } // namespace llvm
348 
349 #endif
350