//===- RawTypes.h -----------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_PDB_NATIVE_RAWTYPES_H
#define LLVM_DEBUGINFO_PDB_NATIVE_RAWTYPES_H
#include "llvm/DebugInfo/CodeView/GUID.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/Endian.h"
namespace llvm {
namespace pdb {
// This struct is defined as "SO" in langapi/include/pdb.h.
struct SectionOffset {
support::ulittle32_t Off;
support::ulittle16_t Isect;
char Padding[2];
};
/// Header of the hash tables found in the globals and publics sections.
/// Based on GSIHashHdr in
/// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
struct GSIHashHeader {
enum : unsigned {
HdrSignature = ~0U,
HdrVersion = 0xeffe0000 + 19990810,
};
support::ulittle32_t VerSignature;
support::ulittle32_t VerHdr;
support::ulittle32_t HrSize;
support::ulittle32_t NumBuckets;
};
// This is HRFile.
struct PSHashRecord {
support::ulittle32_t Off; // Offset in the symbol record stream
support::ulittle32_t CRef;
};
// This struct is defined as `SC` in include/dbicommon.h
struct SectionContrib {
support::ulittle16_t ISect;
char Padding[2];
support::little32_t Off;
support::little32_t Size;
support::ulittle32_t Characteristics;
support::ulittle16_t Imod;
char Padding2[2];
support::ulittle32_t DataCrc;
support::ulittle32_t RelocCrc;
};
// This struct is defined as `SC2` in include/dbicommon.h
struct SectionContrib2 {
// To guarantee SectionContrib2 is standard layout, we cannot use inheritance.
SectionContrib Base;
support::ulittle32_t ISectCoff;
};
// This corresponds to the `OMFSegMap` structure.
struct SecMapHeader {
support::ulittle16_t SecCount; // Number of segment descriptors in table
support::ulittle16_t SecCountLog; // Number of logical segment descriptors
};
// This corresponds to the `OMFSegMapDesc` structure. The definition is not
// present in the reference implementation, but the layout is derived from
// code that accesses the fields.
struct SecMapEntry {
support::ulittle16_t Flags; // Descriptor flags. See OMFSegDescFlags
support::ulittle16_t Ovl; // Logical overlay number.
support::ulittle16_t Group; // Group index into descriptor array.
support::ulittle16_t Frame;
support::ulittle16_t SecName; // Byte index of the segment or group name
// in the sstSegName table, or 0xFFFF.
support::ulittle16_t ClassName; // Byte index of the class name in the
// sstSegName table, or 0xFFFF.
support::ulittle32_t Offset; // Byte offset of the logical segment
// within the specified physical segment.
// If group is set in flags, offset is the
// offset of the group.
support::ulittle32_t SecByteLength; // Byte count of the segment or group.
};
/// Some of the values are stored in bitfields. Since this needs to be portable
/// across compilers and architectures (big / little endian in particular) we
/// can't use the actual structures below, but must instead do the shifting
/// and masking ourselves. The struct definitions are provided for reference.
struct DbiFlags {
/// uint16_t IncrementalLinking : 1; // True if linked incrementally
/// uint16_t IsStripped : 1; // True if private symbols were
/// stripped.
/// uint16_t HasCTypes : 1; // True if linked with /debug:ctypes.
/// uint16_t Reserved : 13;
static const uint16_t FlagIncrementalMask = 0x0001;
static const uint16_t FlagStrippedMask = 0x0002;
static const uint16_t FlagHasCTypesMask = 0x0004;
};
struct DbiBuildNo {
/// uint16_t MinorVersion : 8;
/// uint16_t MajorVersion : 7;
/// uint16_t NewVersionFormat : 1;
static const uint16_t BuildMinorMask = 0x00FF;
static const uint16_t BuildMinorShift = 0;
static const uint16_t BuildMajorMask = 0x7F00;
static const uint16_t BuildMajorShift = 8;
static const uint16_t NewVersionFormatMask = 0x8000;
};
/// The fixed size header that appears at the beginning of the DBI Stream.
struct DbiStreamHeader {
support::little32_t VersionSignature;
support::ulittle32_t VersionHeader;
/// How "old" is this DBI Stream. Should match the age of the PDB InfoStream.
support::ulittle32_t Age;
/// Global symbol stream #
support::ulittle16_t GlobalSymbolStreamIndex;
/// See DbiBuildNo structure.
support::ulittle16_t BuildNumber;
/// Public symbols stream #
support::ulittle16_t PublicSymbolStreamIndex;
/// version of mspdbNNN.dll
support::ulittle16_t PdbDllVersion;
/// Symbol records stream #
support::ulittle16_t SymRecordStreamIndex;
/// rbld number of mspdbNNN.dll
support::ulittle16_t PdbDllRbld;
/// Size of module info stream
support::little32_t ModiSubstreamSize;
/// Size of sec. contrib stream
support::little32_t SecContrSubstreamSize;
/// Size of sec. map substream
support::little32_t SectionMapSize;
/// Size of file info substream
support::little32_t FileInfoSize;
/// Size of type server map
support::little32_t TypeServerSize;
/// Index of MFC Type Server
support::ulittle32_t MFCTypeServerIndex;
/// Size of DbgHeader info
support::little32_t OptionalDbgHdrSize;
/// Size of EC stream (what is EC?)
support::little32_t ECSubstreamSize;
/// See DbiFlags enum.
support::ulittle16_t Flags;
/// See PDB_MachineType enum.
support::ulittle16_t MachineType;
/// Pad to 64 bytes
support::ulittle32_t Reserved;
};
static_assert(sizeof(DbiStreamHeader) == 64, "Invalid DbiStreamHeader size!");
/// The header preceding the File Info Substream of the DBI stream.
struct FileInfoSubstreamHeader {
/// Total # of modules, should match number of records in the ModuleInfo
/// substream.
support::ulittle16_t NumModules;
/// Total # of source files. This value is not accurate because PDB actually
/// supports more than 64k source files, so we ignore it and compute the value
/// from other stream fields.
support::ulittle16_t NumSourceFiles;
/// Following this header the File Info Substream is laid out as follows:
/// ulittle16_t ModIndices[NumModules];
/// ulittle16_t ModFileCounts[NumModules];
/// ulittle32_t FileNameOffsets[NumSourceFiles];
/// char Names[][NumSourceFiles];
/// with the caveat that `NumSourceFiles` cannot be trusted, so
/// it is computed by summing the `ModFileCounts` array.
};
struct ModInfoFlags {
/// uint16_t fWritten : 1; // True if DbiModuleDescriptor is dirty
/// uint16_t fECEnabled : 1; // Is EC symbolic info present? (What is EC?)
/// uint16_t unused : 6; // Reserved
/// uint16_t iTSM : 8; // Type Server Index for this module
static const uint16_t HasECFlagMask = 0x2;
static const uint16_t TypeServerIndexMask = 0xFF00;
static const uint16_t TypeServerIndexShift = 8;
};
/// The header preceding each entry in the Module Info substream of the DBI
/// stream. Corresponds to the type MODI in the reference implementation.
struct ModuleInfoHeader {
/// Currently opened module. This field is a pointer in the reference
/// implementation, but that won't work on 64-bit systems, and anyway it
/// doesn't make sense to read a pointer from a file. For now it is unused,
/// so just ignore it.
support::ulittle32_t Mod;
/// First section contribution of this module.
SectionContrib SC;
/// See ModInfoFlags definition.
support::ulittle16_t Flags;
/// Stream Number of module debug info
support::ulittle16_t ModDiStream;
/// Size of local symbol debug info in above stream
support::ulittle32_t SymBytes;
/// Size of C11 line number info in above stream
support::ulittle32_t C11Bytes;
/// Size of C13 line number info in above stream
support::ulittle32_t C13Bytes;
/// Number of files contributing to this module
support::ulittle16_t NumFiles;
/// Padding so the next field is 4-byte aligned.
char Padding1[2];
/// Array of [0..NumFiles) DBI name buffer offsets. In the reference
/// implementation this field is a pointer. But since you can't portably
/// serialize a pointer, on 64-bit platforms they copy all the values except
/// this one into the 32-bit version of the struct and use that for
/// serialization. Regardless, this field is unused, it is only there to
/// store a pointer that can be accessed at runtime.
support::ulittle32_t FileNameOffs;
/// Name Index for src file name
support::ulittle32_t SrcFileNameNI;
/// Name Index for path to compiler PDB
support::ulittle32_t PdbFilePathNI;
/// Following this header are two zero terminated strings.
/// char ModuleName[];
/// char ObjFileName[];
};
// This is PSGSIHDR struct defined in
// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
struct PublicsStreamHeader {
support::ulittle32_t SymHash;
support::ulittle32_t AddrMap;
support::ulittle32_t NumThunks;
support::ulittle32_t SizeOfThunk;
support::ulittle16_t ISectThunkTable;
char Padding[2];
support::ulittle32_t OffThunkTable;
support::ulittle32_t NumSections;
};
// The header preceding the global TPI stream.
// This corresponds to `HDR` in PDB/dbi/tpi.h.
struct TpiStreamHeader {
struct EmbeddedBuf {
support::little32_t Off;
support::ulittle32_t Length;
};
support::ulittle32_t Version;
support::ulittle32_t HeaderSize;
support::ulittle32_t TypeIndexBegin;
support::ulittle32_t TypeIndexEnd;
support::ulittle32_t TypeRecordBytes;
// The following members correspond to `TpiHash` in PDB/dbi/tpi.h.
support::ulittle16_t HashStreamIndex;
support::ulittle16_t HashAuxStreamIndex;
support::ulittle32_t HashKeySize;
support::ulittle32_t NumHashBuckets;
EmbeddedBuf HashValueBuffer;
EmbeddedBuf IndexOffsetBuffer;
EmbeddedBuf HashAdjBuffer;
};
const uint32_t MinTpiHashBuckets = 0x1000;
const uint32_t MaxTpiHashBuckets = 0x40000;
/// The header preceding the global PDB Stream (Stream 1)
struct InfoStreamHeader {
support::ulittle32_t Version;
support::ulittle32_t Signature;
support::ulittle32_t Age;
codeview::GUID Guid;
};
/// The header preceding the /names stream.
struct PDBStringTableHeader {
support::ulittle32_t Signature; // PDBStringTableSignature
support::ulittle32_t HashVersion; // 1 or 2
support::ulittle32_t ByteSize; // Number of bytes of names buffer.
};
const uint32_t PDBStringTableSignature = 0xEFFEEFFE;
/// The header preceding the /src/headerblock stream.
struct SrcHeaderBlockHeader {
support::ulittle32_t Version; // PdbRaw_SrcHeaderBlockVer enumeration.
support::ulittle32_t Size; // Size of entire stream.
uint64_t FileTime; // Time stamp (Windows FILETIME format).
support::ulittle32_t Age; // Age
uint8_t Padding[44]; // Pad to 64 bytes.
};
static_assert(sizeof(SrcHeaderBlockHeader) == 64, "Incorrect struct size!");
/// A single file record entry within the /src/headerblock stream.
struct SrcHeaderBlockEntry {
support::ulittle32_t Size; // Record Length.
support::ulittle32_t Version; // PdbRaw_SrcHeaderBlockVer enumeration.
support::ulittle32_t CRC; // CRC of the original file contents.
support::ulittle32_t FileSize; // Size of original source file.
support::ulittle32_t FileNI; // String table index of file name.
support::ulittle32_t ObjNI; // String table index of object name.
support::ulittle32_t VFileNI; // String table index of virtual file name.
uint8_t Compression; // PDB_SourceCompression enumeration.
uint8_t IsVirtual; // Is this a virtual file (injected)?
short Padding; // Pad to 4 bytes.
char Reserved[8];
};
static_assert(sizeof(SrcHeaderBlockEntry) == 40, "Incorrect struct size!");
} // namespace pdb
} // namespace llvm
#endif