Home | History | Annotate | Line # | Download | only in BinaryFormat
      1 //===- Minidump.h - Minidump constants and structures -----------*- 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 // This header constants and data structures pertaining to the Windows Minidump
     10 // core file format.
     11 //
     12 // Reference:
     13 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms679293(v=vs.85).aspx
     14 // https://chromium.googlesource.com/breakpad/breakpad/
     15 //
     16 //===----------------------------------------------------------------------===//
     17 
     18 #ifndef LLVM_BINARYFORMAT_MINIDUMP_H
     19 #define LLVM_BINARYFORMAT_MINIDUMP_H
     20 
     21 #include "llvm/ADT/BitmaskEnum.h"
     22 #include "llvm/ADT/DenseMapInfo.h"
     23 #include "llvm/Support/Endian.h"
     24 
     25 namespace llvm {
     26 namespace minidump {
     27 
     28 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
     29 
     30 /// The minidump header is the first part of a minidump file. It identifies the
     31 /// file as a minidump file, and gives the location of the stream directory.
     32 struct Header {
     33   static constexpr uint32_t MagicSignature = 0x504d444d; // PMDM
     34   static constexpr uint16_t MagicVersion = 0xa793;
     35 
     36   support::ulittle32_t Signature;
     37   // The high 16 bits of version field are implementation specific. The low 16
     38   // bits should be MagicVersion.
     39   support::ulittle32_t Version;
     40   support::ulittle32_t NumberOfStreams;
     41   support::ulittle32_t StreamDirectoryRVA;
     42   support::ulittle32_t Checksum;
     43   support::ulittle32_t TimeDateStamp;
     44   support::ulittle64_t Flags;
     45 };
     46 static_assert(sizeof(Header) == 32, "");
     47 
     48 /// The type of a minidump stream identifies its contents. Streams numbers after
     49 /// LastReserved are for application-defined data streams.
     50 enum class StreamType : uint32_t {
     51 #define HANDLE_MDMP_STREAM_TYPE(CODE, NAME) NAME = CODE,
     52 #include "llvm/BinaryFormat/MinidumpConstants.def"
     53   Unused = 0,
     54   LastReserved = 0x0000ffff,
     55 };
     56 
     57 /// Specifies the location (and size) of various objects in the minidump file.
     58 /// The location is relative to the start of the file.
     59 struct LocationDescriptor {
     60   support::ulittle32_t DataSize;
     61   support::ulittle32_t RVA;
     62 };
     63 static_assert(sizeof(LocationDescriptor) == 8, "");
     64 
     65 /// Describes a single memory range (both its VM address and where to find it in
     66 /// the file) of the process from which this minidump file was generated.
     67 struct MemoryDescriptor {
     68   support::ulittle64_t StartOfMemoryRange;
     69   LocationDescriptor Memory;
     70 };
     71 static_assert(sizeof(MemoryDescriptor) == 16, "");
     72 
     73 struct MemoryInfoListHeader {
     74   support::ulittle32_t SizeOfHeader;
     75   support::ulittle32_t SizeOfEntry;
     76   support::ulittle64_t NumberOfEntries;
     77 
     78   MemoryInfoListHeader() = default;
     79   MemoryInfoListHeader(uint32_t SizeOfHeader, uint32_t SizeOfEntry,
     80                        uint64_t NumberOfEntries)
     81       : SizeOfHeader(SizeOfHeader), SizeOfEntry(SizeOfEntry),
     82         NumberOfEntries(NumberOfEntries) {}
     83 };
     84 static_assert(sizeof(MemoryInfoListHeader) == 16, "");
     85 
     86 enum class MemoryProtection : uint32_t {
     87 #define HANDLE_MDMP_PROTECT(CODE, NAME, NATIVENAME) NAME = CODE,
     88 #include "llvm/BinaryFormat/MinidumpConstants.def"
     89   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/0xffffffffu),
     90 };
     91 
     92 enum class MemoryState : uint32_t {
     93 #define HANDLE_MDMP_MEMSTATE(CODE, NAME, NATIVENAME) NAME = CODE,
     94 #include "llvm/BinaryFormat/MinidumpConstants.def"
     95   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/0xffffffffu),
     96 };
     97 
     98 enum class MemoryType : uint32_t {
     99 #define HANDLE_MDMP_MEMTYPE(CODE, NAME, NATIVENAME) NAME = CODE,
    100 #include "llvm/BinaryFormat/MinidumpConstants.def"
    101   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/0xffffffffu),
    102 };
    103 
    104 struct MemoryInfo {
    105   support::ulittle64_t BaseAddress;
    106   support::ulittle64_t AllocationBase;
    107   support::little_t<MemoryProtection> AllocationProtect;
    108   support::ulittle32_t Reserved0;
    109   support::ulittle64_t RegionSize;
    110   support::little_t<MemoryState> State;
    111   support::little_t<MemoryProtection> Protect;
    112   support::little_t<MemoryType> Type;
    113   support::ulittle32_t Reserved1;
    114 };
    115 static_assert(sizeof(MemoryInfo) == 48, "");
    116 
    117 /// Specifies the location and type of a single stream in the minidump file. The
    118 /// minidump stream directory is an array of entries of this type, with its size
    119 /// given by Header.NumberOfStreams.
    120 struct Directory {
    121   support::little_t<StreamType> Type;
    122   LocationDescriptor Location;
    123 };
    124 static_assert(sizeof(Directory) == 12, "");
    125 
    126 /// The processor architecture of the system that generated this minidump. Used
    127 /// in the ProcessorArch field of the SystemInfo stream.
    128 enum class ProcessorArchitecture : uint16_t {
    129 #define HANDLE_MDMP_ARCH(CODE, NAME) NAME = CODE,
    130 #include "llvm/BinaryFormat/MinidumpConstants.def"
    131 };
    132 
    133 /// The OS Platform of the system that generated this minidump. Used in the
    134 /// PlatformId field of the SystemInfo stream.
    135 enum class OSPlatform : uint32_t {
    136 #define HANDLE_MDMP_PLATFORM(CODE, NAME) NAME = CODE,
    137 #include "llvm/BinaryFormat/MinidumpConstants.def"
    138 };
    139 
    140 /// Detailed information about the processor of the system that generated this
    141 /// minidump. Its interpretation depends on the ProcessorArchitecture enum.
    142 union CPUInfo {
    143   struct X86Info {
    144     char VendorID[12];                        // cpuid 0: ebx, edx, ecx
    145     support::ulittle32_t VersionInfo;         // cpuid 1: eax
    146     support::ulittle32_t FeatureInfo;         // cpuid 1: edx
    147     support::ulittle32_t AMDExtendedFeatures; // cpuid 0x80000001, ebx
    148   } X86;
    149   struct ArmInfo {
    150     support::ulittle32_t CPUID;
    151     support::ulittle32_t ElfHWCaps; // linux specific, 0 otherwise
    152   } Arm;
    153   struct OtherInfo {
    154     uint8_t ProcessorFeatures[16];
    155   } Other;
    156 };
    157 static_assert(sizeof(CPUInfo) == 24, "");
    158 
    159 /// The SystemInfo stream, containing various information about the system where
    160 /// this minidump was generated.
    161 struct SystemInfo {
    162   support::little_t<ProcessorArchitecture> ProcessorArch;
    163   support::ulittle16_t ProcessorLevel;
    164   support::ulittle16_t ProcessorRevision;
    165 
    166   uint8_t NumberOfProcessors;
    167   uint8_t ProductType;
    168 
    169   support::ulittle32_t MajorVersion;
    170   support::ulittle32_t MinorVersion;
    171   support::ulittle32_t BuildNumber;
    172   support::little_t<OSPlatform> PlatformId;
    173   support::ulittle32_t CSDVersionRVA;
    174 
    175   support::ulittle16_t SuiteMask;
    176   support::ulittle16_t Reserved;
    177 
    178   CPUInfo CPU;
    179 };
    180 static_assert(sizeof(SystemInfo) == 56, "");
    181 
    182 struct VSFixedFileInfo {
    183   support::ulittle32_t Signature;
    184   support::ulittle32_t StructVersion;
    185   support::ulittle32_t FileVersionHigh;
    186   support::ulittle32_t FileVersionLow;
    187   support::ulittle32_t ProductVersionHigh;
    188   support::ulittle32_t ProductVersionLow;
    189   support::ulittle32_t FileFlagsMask;
    190   support::ulittle32_t FileFlags;
    191   support::ulittle32_t FileOS;
    192   support::ulittle32_t FileType;
    193   support::ulittle32_t FileSubtype;
    194   support::ulittle32_t FileDateHigh;
    195   support::ulittle32_t FileDateLow;
    196 };
    197 static_assert(sizeof(VSFixedFileInfo) == 52, "");
    198 
    199 inline bool operator==(const VSFixedFileInfo &LHS, const VSFixedFileInfo &RHS) {
    200   return memcmp(&LHS, &RHS, sizeof(VSFixedFileInfo)) == 0;
    201 }
    202 
    203 struct Module {
    204   support::ulittle64_t BaseOfImage;
    205   support::ulittle32_t SizeOfImage;
    206   support::ulittle32_t Checksum;
    207   support::ulittle32_t TimeDateStamp;
    208   support::ulittle32_t ModuleNameRVA;
    209   VSFixedFileInfo VersionInfo;
    210   LocationDescriptor CvRecord;
    211   LocationDescriptor MiscRecord;
    212   support::ulittle64_t Reserved0;
    213   support::ulittle64_t Reserved1;
    214 };
    215 static_assert(sizeof(Module) == 108, "");
    216 
    217 /// Describes a single thread in the minidump file. Part of the ThreadList
    218 /// stream.
    219 struct Thread {
    220   support::ulittle32_t ThreadId;
    221   support::ulittle32_t SuspendCount;
    222   support::ulittle32_t PriorityClass;
    223   support::ulittle32_t Priority;
    224   support::ulittle64_t EnvironmentBlock;
    225   MemoryDescriptor Stack;
    226   LocationDescriptor Context;
    227 };
    228 static_assert(sizeof(Thread) == 48, "");
    229 
    230 struct Exception {
    231   static constexpr size_t MaxParameters = 15;
    232 
    233   support::ulittle32_t ExceptionCode;
    234   support::ulittle32_t ExceptionFlags;
    235   support::ulittle64_t ExceptionRecord;
    236   support::ulittle64_t ExceptionAddress;
    237   support::ulittle32_t NumberParameters;
    238   support::ulittle32_t UnusedAlignment;
    239   support::ulittle64_t ExceptionInformation[MaxParameters];
    240 };
    241 static_assert(sizeof(Exception) == 152, "");
    242 
    243 struct ExceptionStream {
    244   support::ulittle32_t ThreadId;
    245   support::ulittle32_t UnusedAlignment;
    246   Exception ExceptionRecord;
    247   LocationDescriptor ThreadContext;
    248 };
    249 static_assert(sizeof(ExceptionStream) == 168, "");
    250 
    251 } // namespace minidump
    252 
    253 template <> struct DenseMapInfo<minidump::StreamType> {
    254   static minidump::StreamType getEmptyKey() { return minidump::StreamType(-1); }
    255 
    256   static minidump::StreamType getTombstoneKey() {
    257     return minidump::StreamType(-2);
    258   }
    259 
    260   static unsigned getHashValue(minidump::StreamType Val) {
    261     return DenseMapInfo<uint32_t>::getHashValue(static_cast<uint32_t>(Val));
    262   }
    263 
    264   static bool isEqual(minidump::StreamType LHS, minidump::StreamType RHS) {
    265     return LHS == RHS;
    266   }
    267 };
    268 
    269 } // namespace llvm
    270 
    271 #endif // LLVM_BINARYFORMAT_MINIDUMP_H
    272