1 #[repr(C)]
2 #[derive(Debug, Default, PartialEq)]
3 pub struct MDGUID {
4     data1: u32,
5     data2: u16,
6     data3: u16,
7     data4: [u8; 8],
8 }
9 
10 #[repr(C)]
11 #[derive(Debug, Default, PartialEq, Clone, Copy)]
12 pub struct MDVSFixedFileInfo {
13     pub signature: u32,
14     pub struct_version: u32,
15     pub file_version_hi: u32,
16     pub file_version_lo: u32,
17     pub product_version_hi: u32,
18     pub product_version_lo: u32,
19     pub file_flags_mask: u32, /* Identifies valid bits in fileFlags */
20     pub file_flags: u32,
21     pub file_os: u32,
22     pub file_type: u32,
23     pub file_subtype: u32,
24     pub file_date_hi: u32,
25     pub file_date_lo: u32,
26 }
27 
28 /* An MDRVA is an offset into the minidump file.  The beginning of the
29  * MDRawHeader is at offset 0. */
30 pub type MDRVA = u32;
31 
32 #[repr(C)]
33 #[derive(Debug, Default, Clone, Copy, PartialEq)]
34 pub struct MDLocationDescriptor {
35     pub data_size: u32,
36     pub rva: MDRVA,
37 }
38 
39 #[repr(C)]
40 #[derive(Debug, Default, Clone, PartialEq)]
41 pub struct MDMemoryDescriptor {
42     /* The base address of the memory range on the host that produced the
43      * minidump. */
44     pub start_of_memory_range: u64,
45     pub memory: MDLocationDescriptor,
46 }
47 
48 #[repr(C)]
49 #[derive(Debug, Default, PartialEq)]
50 pub struct MDRawHeader {
51     pub signature: u32,
52     pub version: u32,
53     pub stream_count: u32,
54     pub stream_directory_rva: MDRVA, /* A |stream_count|-sized array of
55                                       * MDRawDirectory structures. */
56     pub checksum: u32,        /* Can be 0.  In fact, that's all that's
57                                * been found in minidump files. */
58     pub time_date_stamp: u32, /* time_t */
59     pub flags: u64,
60 }
61 
62 /* For (MDRawHeader).signature and (MDRawHeader).version.  Note that only the
63  * low 16 bits of (MDRawHeader).version are MD_HEADER_VERSION.  Per the
64  * documentation, the high 16 bits are implementation-specific. */
65 pub const MD_HEADER_SIGNATURE: u32 = 0x504d444d; /* 'PMDM' */
66 /* MINIDUMP_SIGNATURE */
67 pub const MD_HEADER_VERSION: u32 = 0x0000a793; /* 42899 */
68 /* MINIDUMP_VERSION */
69 
70 /// The name of a thread, found in the ThreadNamesStream.
71 #[repr(C, packed)]
72 #[derive(Clone, Copy, Debug, Default, PartialEq)]
73 pub struct MDRawThreadName {
74     /// The id of the thread.
75     pub thread_id: u32,
76     /// Where the name of the thread is stored (yes, the legendary RVA64 is real!!).
77     pub thread_name_rva: u64,
78 }
79 
80 #[repr(C)]
81 #[derive(Debug, Default, PartialEq)]
82 pub struct MDRawThread {
83     pub thread_id: u32,
84     pub suspend_count: u32,
85     pub priority_class: u32,
86     pub priority: u32,
87     pub teb: u64, /* Thread environment block */
88     pub stack: MDMemoryDescriptor,
89     pub thread_context: MDLocationDescriptor, /* MDRawContext[CPU] */
90 }
91 
92 pub type MDRawThreadList = Vec<MDRawThread>;
93 
94 /* The inclusion of a 64-bit type in MINIDUMP_MODULE forces the struct to
95  * be tail-padded out to a multiple of 64 bits under some ABIs (such as PPC).
96  * This doesn't occur on systems that don't tail-pad in this manner.  Define
97  * this macro to be the usable size of the MDRawModule struct, and use it in
98  * place of sizeof(MDRawModule). */
99 // pub const MD_MODULE_SIZE: usize = 108;
100 // NOTE: We use "packed" here instead, to size_of::<MDRawModule>() == 108
101 //       "packed" should be safe here, as we don't address reserved{0,1} at all
102 //       and padding should happen only at the tail
103 #[repr(C, packed)]
104 #[derive(Clone, Copy, Debug, Default, PartialEq)]
105 pub struct MDRawModule {
106     pub base_of_image: u64,
107     pub size_of_image: u32,
108     pub checksum: u32,          /* 0 if unknown */
109     pub time_date_stamp: u32,   /* time_t */
110     pub module_name_rva: MDRVA, /* MDString, pathname or filename */
111     pub version_info: MDVSFixedFileInfo,
112 
113     /* The next field stores a CodeView record and is populated when a module's
114      * debug information resides in a PDB file.  It identifies the PDB file. */
115     pub cv_record: MDLocationDescriptor,
116 
117     /* The next field is populated when a module's debug information resides
118      * in a DBG file.  It identifies the DBG file.  This field is effectively
119      * obsolete with modules built by recent toolchains. */
120     pub misc_record: MDLocationDescriptor,
121 
122     /* Alignment problem: reserved0 and reserved1 are defined by the platform
123      * SDK as 64-bit quantities.  However, that results in a structure whose
124      * alignment is unpredictable on different CPUs and ABIs.  If the ABI
125      * specifies full alignment of 64-bit quantities in structures (as ppc
126      * does), there will be padding between miscRecord and reserved0.  If
127      * 64-bit quantities can be aligned on 32-bit boundaries (as on x86),
128      * this padding will not exist.  (Note that the structure up to this point
129      * contains 1 64-bit member followed by 21 32-bit members.)
130      * As a workaround, reserved0 and reserved1 are instead defined here as
131      * four 32-bit quantities.  This should be harmless, as there are
132      * currently no known uses for these fields. */
133     pub reserved0: [u32; 2],
134     pub reserved1: [u32; 2],
135 }
136 
137 #[repr(C)]
138 #[derive(Debug, Default, PartialEq, Clone)]
139 pub struct MDRawDirectory {
140     pub stream_type: u32,
141     pub location: MDLocationDescriptor,
142 }
143 
144 #[repr(C)]
145 #[derive(Debug, Default, PartialEq)]
146 pub struct MDException {
147     pub exception_code: u32, /* Windows: MDExceptionCodeWin,
148                               * Mac OS X: MDExceptionMac,
149                               * Linux: MDExceptionCodeLinux. */
150     pub exception_flags: u32, /* Windows: 1 if noncontinuable,
151                               Mac OS X: MDExceptionCodeMac. */
152     pub exception_record: u64, /* Address (in the minidump-producing host's
153                                 * memory) of another MDException, for
154                                 * nested exceptions. */
155     pub exception_address: u64, /* The address that caused the exception.
156                                  * Mac OS X: exception subcode (which is
157                                  *           typically the address). */
158     pub number_parameters: u32, /* Number of valid elements in
159                                  * exception_information. */
160     pub __align: u32,
161     pub exception_information: [u64; 15],
162 }
163 
164 #[repr(C)]
165 #[derive(Debug, Default, PartialEq)]
166 pub struct MDRawExceptionStream {
167     pub thread_id: u32, /* Thread in which the exception
168                          * occurred.  Corresponds to
169                          * (MDRawThread).thread_id. */
170     pub __align: u32,
171     pub exception_record: MDException,
172     pub thread_context: MDLocationDescriptor, /* MDRawContext[CPU] */
173 }
174 
175 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
176 #[repr(C)]
177 #[derive(Debug, Default, PartialEq)]
178 pub struct MDCPUInformation {
179     pub vendor_id: [u32; 3],            /* cpuid 0: ebx, edx, ecx */
180     pub version_information: u32,       /* cpuid 1: eax */
181     pub feature_information: u32,       /* cpuid 1: edx */
182     pub amd_extended_cpu_features: u32, /* cpuid 0x80000001, ebx */
183 }
184 
185 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
186 #[repr(C)]
187 #[derive(Debug, Default, PartialEq)]
188 pub struct MDCPUInformation {
189     pub cpuid: u32,
190     pub elf_hwcaps: u32, /* linux specific, 0 otherwise */
191     _padding: [u32; 4],
192 }
193 
194 #[cfg(target_arch = "mips")]
195 #[repr(C)]
196 #[derive(Debug, Default, PartialEq)]
197 pub struct MDCPUInformation {
198     pub cpuid: [u64; 2],
199     _padding: [u32; 2],
200 }
201 
202 /* For (MDCPUInformation).arm_cpu_info.elf_hwcaps.
203  * This matches the Linux kernel definitions from <asm/hwcaps.h> */
204 #[repr(u32)]
205 pub enum MDCPUInformationARMElfHwCaps {
206     Swp = 1 << 0,
207     Half = 1 << 1,
208     Thumb = 1 << 2,
209     Bit26 = 1 << 3,
210     FastMult = 1 << 4,
211     Fpa = 1 << 5,
212     Vfp = 1 << 6,
213     Edsp = 1 << 7,
214     Java = 1 << 8,
215     Iwmmxt = 1 << 9,
216     Crunch = 1 << 10,
217     Thumbee = 1 << 11,
218     Neon = 1 << 12,
219     Vfpv3 = 1 << 13,
220     Vfpv3d16 = 1 << 14,
221     Tls = 1 << 15,
222     Vfpv4 = 1 << 16,
223     Idiva = 1 << 17,
224     Idivt = 1 << 18,
225 }
226 
227 #[repr(C)]
228 #[derive(Debug, Default, PartialEq)]
229 pub struct MDRawSystemInfo {
230     /* The next 3 fields and numberOfProcessors are from the SYSTEM_INFO
231      * structure as returned by GetSystemInfo */
232     pub processor_architecture: u16,
233     pub processor_level: u16, /* x86: 5 = 586, 6 = 686, ... */
234     /* ARM: 6 = ARMv6, 7 = ARMv7 ... */
235     pub processor_revision: u16, /* x86: 0xMMSS, where MM=model,
236                                   *      SS=stepping */
237     /* ARM: 0 */
238     pub number_of_processors: u8,
239     pub product_type: u8, /* Windows: VER_NT_* from WinNT.h */
240 
241     /* The next 5 fields are from the OSVERSIONINFO structure as returned
242      * by GetVersionEx */
243     pub major_version: u32,
244     pub minor_version: u32,
245     pub build_number: u32,
246     pub platform_id: u32,
247     pub csd_version_rva: MDRVA, /* MDString further identifying the
248                                  * host OS.
249                                  * Windows: name of the installed OS
250                                  *          service pack.
251                                  * Mac OS X: the Apple OS build number
252                                  *           (sw_vers -buildVersion).
253                                  * Linux: uname -srvmo */
254 
255     pub suite_mask: u16, /* Windows: VER_SUITE_* from WinNT.h */
256     pub reserved2: u16,
257 
258     pub cpu: MDCPUInformation,
259 }
260 
261 #[cfg(target_pointer_width = "64")]
262 #[derive(Debug, Default, PartialEq)]
263 pub struct MDRawLinkMap {
264     pub addr: u64,
265     pub name: MDRVA,
266     pub ld: u64,
267 }
268 
269 #[cfg(target_pointer_width = "64")]
270 #[derive(Debug, Default, PartialEq)]
271 pub struct MDRawDebug {
272     pub version: u32,
273     pub map: MDRVA, /* array of MDRawLinkMap64 */
274     pub dso_count: u32,
275     pub brk: u64,
276     pub ldbase: u64,
277     pub dynamic: u64,
278 }
279 
280 #[cfg(target_pointer_width = "32")]
281 #[derive(Debug, Default, PartialEq)]
282 pub struct MDRawLinkMap {
283     pub addr: u32,
284     pub name: MDRVA,
285     pub ld: u32,
286 }
287 
288 #[cfg(target_pointer_width = "32")]
289 #[derive(Debug, Default, PartialEq)]
290 pub struct MDRawDebug {
291     pub version: u32,
292     pub map: MDRVA, /* array of MDRawLinkMap32 */
293     pub dso_count: u32,
294     pub brk: u32,
295     pub ldbase: u32,
296     pub dynamic: u32,
297 }
298 
299 /* For (MDRawSystemInfo).processor_architecture: */
300 #[repr(u16)]
301 pub enum MDCPUArchitecture {
302     X86 = 0,   /* PROCESSOR_ARCHITECTURE_INTEL */
303     Mips = 1,  /* PROCESSOR_ARCHITECTURE_MIPS */
304     Alpha = 2, /* PROCESSOR_ARCHITECTURE_ALPHA */
305     Ppc = 3,   /* PROCESSOR_ARCHITECTURE_PPC */
306     Shx = 4,   /* PROCESSOR_ARCHITECTURE_SHX
307                 * (Super-H) */
308     Arm = 5,     /* PROCESSOR_ARCHITECTURE_ARM */
309     Ia64 = 6,    /* PROCESSOR_ARCHITECTURE_IA64 */
310     Alpha64 = 7, /* PROCESSOR_ARCHITECTURE_ALPHA64 */
311     Msil = 8,    /* PROCESSOR_ARCHITECTURE_MSIL
312                   * (Microsoft Intermediate Language) */
313     Amd64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */
314     X86Win64 = 10,
315     /* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */
316     Arm64 = 12,        /* PROCESSOR_ARCHITECTURE_ARM64 */
317     Sparc = 0x8001,    /* Breakpad-defined value for SPARC */
318     Ppc64 = 0x8002,    /* Breakpad-defined value for PPC64 */
319     Arm64Old = 0x8003, /* Breakpad-defined value for ARM64 */
320     Mips64 = 0x8004,   /* Breakpad-defined value for MIPS64 */
321     Unknown = 0xffff,  /* PROCESSOR_ARCHITECTURE_UNKNOWN */
322 }
323 
324 /* For (MDRawSystemInfo).platform_id: */
325 #[repr(u32)]
326 pub enum MDOSPlatform {
327     Win32s = 0,       /* VER_PLATFORM_WIN32s (Windows 3.1) */
328     Win32Windows = 1, /* VER_PLATFORM_WIN32_WINDOWS (Windows 95-98-Me) */
329     Win32Nt = 2,      /* VER_PLATFORM_WIN32_NT (Windows NT, 2000+) */
330     Win32Ce = 3,      /* VER_PLATFORM_WIN32_CE, VER_PLATFORM_WIN32_HH
331                        * (Windows CE, Windows Mobile, "Handheld") */
332     /* The following values are Breakpad-defined. */
333     Unix = 0x8000,    /* Generic Unix-ish */
334     MacOsX = 0x8101,  /* Mac OS X/Darwin */
335     Ios = 0x8102,     /* iOS */
336     Linux = 0x8201,   /* Linux */
337     Solaris = 0x8202, /* Solaris */
338     Android = 0x8203, /* Android */
339     Ps3 = 0x8204,     /* PS3 */
340     Nacl = 0x8205,    /* Native Client (NaCl) */
341     Fuchsia = 0x8206, /* Fuchsia */
342 }
343 
344 /*
345  * Modern ELF toolchains insert a "build id" into the ELF headers that
346  * usually contains a hash of some ELF headers + sections to uniquely
347  * identify a binary.
348  *
349  * https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Developer_Guide/compiling-build-id.html
350  * https://sourceware.org/binutils/docs-2.26/ld/Options.html#index-g_t_002d_002dbuild_002did-292
351  */
352 pub const MD_CVINFOELF_SIGNATURE: u32 = 0x4270454c; /* cvSignature = 'BpEL' */
353 /* Signature is followed by the bytes of the
354  * build id from GNU_BUILD_ID ELF note.
355  * This is variable-length, but usually 20 bytes
356  * as the binutils ld default is a SHA-1 hash. */
357 
358 /* For (MDRawHeader).flags: */
359 pub enum MDType {
360     /* MD_NORMAL is the standard type of minidump.  It includes full
361      * streams for the thread list, module list, exception, system info,
362      * and miscellaneous info.  A memory list stream is also present,
363      * pointing to the same stack memory contained in the thread list,
364      * as well as a 256-byte region around the instruction address that
365      * was executing when the exception occurred.  Stack memory is from
366      * 4 bytes below a thread's stack pointer up to the top of the
367      * memory region encompassing the stack. */
368     Normal = 0x00000000,
369     WithDataSegs = 0x00000001,
370     WithFullMemory = 0x00000002,
371     WithHandleData = 0x00000004,
372     FilterMemory = 0x00000008,
373     ScanMemory = 0x00000010,
374     WithUnloadedModules = 0x00000020,
375     WithIndirectlyReferencedMemory = 0x00000040,
376     FilterModulePaths = 0x00000080,
377     WithProcessThreadData = 0x00000100,
378     WithPrivateReadWriteMemory = 0x00000200,
379     WithoutOptionalData = 0x00000400,
380     WithFullMemoryInfo = 0x00000800,
381     WithThreadInfo = 0x00001000,
382     WithCodeSegs = 0x00002000,
383     WithoutAuxilliarySegs = 0x00004000,
384     WithFullAuxilliaryState = 0x00008000,
385     WithPrivateWriteCopyMemory = 0x00010000,
386     IgnoreInaccessibleMemory = 0x00020000,
387     WithTokenInformation = 0x00040000,
388 }
389 
390 /* For (MDRawDirectory).stream_type */
391 #[repr(u32)]
392 pub enum MDStreamType {
393     UnusedStream = 0,
394     ReservedStream0 = 1,
395     ReservedStream1 = 2,
396     ThreadListStream = 3, /* MDRawThreadList */
397     ModuleListStream = 4, /* MDRawModuleList */
398     MemoryListStream = 5, /* MDRawMemoryList */
399     ExceptionStream = 6,  /* MDRawExceptionStream */
400     SystemInfoStream = 7, /* MDRawSystemInfo */
401     ThreadExListStream = 8,
402     Memory64ListStream = 9,
403     CommentStreamA = 10,
404     CommentStreamW = 11,
405     HandleDataStream = 12,
406     FunctionTableStream = 13,
407     UnloadedModuleListStream = 14,
408     MiscInfoStream = 15,       /* MDRawMiscInfo */
409     MemoryInfoListStream = 16, /* MDRawMemoryInfoList */
410     ThreadInfoListStream = 17,
411     HandleOperationListStream = 18,
412     TokenStream = 19,
413     JavascriptDataStream = 20,
414     SystemMemoryInfoStream = 21,
415     ProcessVmCountersStream = 22,
416     IptTraceStream = 23,
417     ThreadNamesStream = 24,
418     LastReservedStream = 0x0000ffff,
419 
420     /* Breakpad extension types.  0x4767 = "Gg" */
421     BreakpadInfoStream = 0x47670001,  /* MDRawBreakpadInfo  */
422     AssertionInfoStream = 0x47670002, /* MDRawAssertionInfo */
423     /* These are additional minidump stream values which are specific to
424      * the linux breakpad implementation. */
425     LinuxCpuInfo = 0x47670003,    /* /proc/cpuinfo      */
426     LinuxProcStatus = 0x47670004, /* /proc/$x/status    */
427     LinuxLsbRelease = 0x47670005, /* /etc/lsb-release   */
428     LinuxCmdLine = 0x47670006,    /* /proc/$x/cmdline   */
429     LinuxEnviron = 0x47670007,    /* /proc/$x/environ   */
430     LinuxAuxv = 0x47670008,       /* /proc/$x/auxv      */
431     LinuxMaps = 0x47670009,       /* /proc/$x/maps      */
432     LinuxDsoDebug = 0x4767000A,   /* MDRawDebug{32,64}  */
433 
434     /* Crashpad extension types. 0x4350 = "CP"
435      * See Crashpad's minidump/minidump_extensions.h. */
436     CrashpadInfoStream = 0x43500001, /* MDRawCrashpadInfo  */
437 }
438