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