minidump_common/format.rs
1//! Minidump structure definitions.
2//!
3//! Types defined here should match those defined in [Microsoft's headers][msdn]. Additionally
4//! some [Breakpad][breakpad] and [Crashpad][crashpad] extension types are defined here and should
5//! match the definitions from those projects.
6//!
7//! # Type Layouts
8//!
9//! This library isn't a "proper" minidump-sys library because it doesn't use repr attributes
10//! to force Rust to layout these structs identically to how they're laid out in memory.
11//!
12//! The reasons for this are 3-fold:
13//!
14//! 1. It isn't necessary because we specify how to serialize/deserialize things with `scroll`
15//! via `derive(Pread, Pwrite)` which uses the declared field order and not the in-memory
16//! layout, and assumes everything is packed anyway, which as a rule, minidump types are.
17//! Specifically they're packed to align 4, but Microsoft is mercifully very attentive to
18//! its type layouts so we're not aware of anywhere where packing to align 1 would change
19//! offsets. Packing is mostly just there so 32-bit and 64-bit definitely agree on offsets.
20//!
21//! 2. We would have to mark several types as `repr(packed(4))`, making them dangerous to use
22//! as several of the fields would become misaligned. This would create a bunch of
23//! unnecessary and brittle `unsafe`.
24//!
25//! 3. It's not *actually* that useful to have structs with precise in-memory layouts since
26//! a minidump parser needs to accept both little-endian and big-endian minidumps, and
27//! is therefore swizzling the bytes of all the values anyway. Also it's dangerous to
28//! reinterpret a pile of memory as arbitrary types without validation!
29//!
30//! [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/
31//! [breakpad]: https://chromium.googlesource.com/breakpad/breakpad/
32//! [crashpad]: https://chromium.googlesource.com/crashpad/crashpad/+/master/README.md
33#![allow(non_camel_case_types)]
34#![allow(non_upper_case_globals)]
35
36use std::fmt;
37
38use bitflags::bitflags;
39use num_derive::FromPrimitive;
40use scroll::{Endian, Pread, Pwrite, SizeWith};
41use smart_default::SmartDefault;
42
43/// An offset from the start of the minidump file.
44pub type RVA = u32;
45pub type RVA64 = u64;
46
47/// The 4-byte magic number at the start of a minidump file.
48///
49/// In little endian this spells 'MDMP'.
50pub const MINIDUMP_SIGNATURE: u32 = 0x504d444d;
51
52/// The version of the minidump format.
53pub const MINIDUMP_VERSION: u32 = 42899;
54
55/// The header at the start of a minidump file.
56///
57/// This struct matches the [Microsoft struct][msdn] of the same name.
58///
59/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_header
60#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
61pub struct MINIDUMP_HEADER {
62 /// This should be [`MINIDUMP_SIGNATURE`][signature].
63 ///
64 /// [signature]: constant.MINIDUMP_SIGNATURE.html
65 pub signature: u32,
66 /// This should be [`MINIDUMP_VERSION`][version].
67 ///
68 /// [version]: constant.MINIDUMP_VERSION.html
69 pub version: u32,
70 /// The number of streams contained in the stream directory.
71 pub stream_count: u32,
72 /// The offset to the stream directory within the minidump. This usually points
73 /// to immediately after the header. The stream directory is an array containing
74 /// `stream_count` [`MINIDUMP_DIRECTORY`][dir] entries.
75 ///
76 /// [dir]: struct.MINIDUMP_DIRECTORY.html
77 pub stream_directory_rva: RVA,
78 pub checksum: u32,
79 pub time_date_stamp: u32,
80 pub flags: u64,
81}
82
83/// A location within a minidump file comprised of an offset and a size.
84///
85/// This struct matches the [Microsoft struct][msdn] of the same name.
86///
87/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_location_descriptor
88#[derive(Debug, Copy, Default, Clone, Pread, Pwrite, SizeWith)]
89pub struct MINIDUMP_LOCATION_DESCRIPTOR {
90 /// The size of this data.
91 pub data_size: u32,
92 /// The offset to this data within the minidump file.
93 pub rva: RVA,
94}
95
96impl From<u8> for MINIDUMP_LOCATION_DESCRIPTOR {
97 fn from(_val: u8) -> Self {
98 Self::default()
99 }
100}
101
102/// A range of memory contained within a minidump consisting of a base address and a
103/// location descriptor.
104///
105/// This struct matches the [Microsoft struct][msdn] of the same name.
106///
107/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_memory_descriptor
108#[derive(Debug, Copy, Clone, Default, Pread, Pwrite, SizeWith)]
109pub struct MINIDUMP_MEMORY_DESCRIPTOR {
110 /// The base address of this memory range from the process.
111 pub start_of_memory_range: u64,
112 /// The offset and size of the actual bytes of memory contained in this dump.
113 pub memory: MINIDUMP_LOCATION_DESCRIPTOR,
114}
115
116/// A large range of memory contained within a minidump (usually a full dump)
117/// consisting of a base address and a size.
118///
119/// This struct matches the [Microsoft struct][msdn] of the same name.
120///
121/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_memory_descriptor64
122#[derive(Debug, Copy, Clone, Default, Pread, Pwrite, SizeWith)]
123pub struct MINIDUMP_MEMORY_DESCRIPTOR64 {
124 /// The base address of this memory range from the process.
125 pub start_of_memory_range: u64,
126 /// The size of this data.
127 pub data_size: u64,
128}
129
130/// Information about a data stream contained in a minidump file.
131///
132/// The minidump header contains a pointer to a list of these structs which allows locating
133/// specific streams in the dump.
134/// This struct matches the [Microsoft struct][msdn] of the same name.
135///
136/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_directory
137#[derive(Debug, Clone, Default, Pread, Pwrite, SizeWith)]
138pub struct MINIDUMP_DIRECTORY {
139 /// This is usually one of the values in [`MINIDUMP_STREAM_TYPE`][ty] for known stream types,
140 /// but user streams can have arbitrary values.
141 ///
142 /// [ty]: enum.MINIDUMP_STREAM_TYPE.html
143 pub stream_type: u32,
144 /// The location of the stream contents within the dump.
145 pub location: MINIDUMP_LOCATION_DESCRIPTOR,
146}
147
148/// The types of known minidump data streams.
149///
150/// Most of these values are derived from the [Microsoft enum][msdn] of the same name, but
151/// the values after `LastReservedStream` are Breakpad and Crashpad extensions.
152///
153/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ne-minidumpapiset-minidump_stream_type
154#[repr(u32)]
155#[derive(Copy, Clone, PartialEq, Eq, Debug, FromPrimitive)]
156pub enum MINIDUMP_STREAM_TYPE {
157 /// An unused stream directory entry
158 UnusedStream = 0,
159 ReservedStream0 = 1,
160 ReservedStream1 = 2,
161 /// The list of threads from the process
162 ///
163 /// See [`MINIDUMP_THREAD`].
164 ///
165 /// Microsoft declares a [`MINIDUMP_THREAD_LIST`][list] struct which is the actual format
166 /// of this stream, but it is a variable-length struct so no matching definition is provided
167 /// in this crate.
168 ///
169 /// [list]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_thread_list
170 ThreadListStream = 3,
171 /// The list of executable modules from the process
172 ///
173 /// See [`MINIDUMP_MODULE`].
174 ///
175 /// Microsoft declares a [`MINIDUMP_MODULE_LIST`][list] struct which is the actual format
176 /// of this stream, but it is a variable-length struct so no matching definition is provided
177 /// in this crate.
178 ///
179 /// [list]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_module_list
180 ModuleListStream = 4,
181 /// The list of memory regions from the process contained within this dump
182 ///
183 /// See [`MINIDUMP_MEMORY_DESCRIPTOR`].
184 ///
185 /// Microsoft declares a [`MINIDUMP_MEMORY_LIST`][list] struct which is the actual format
186 /// of this stream, but it is a variable-length struct so no matching definition is provided
187 /// in this crate.
188 ///
189 /// [list]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_memory_list
190 MemoryListStream = 5,
191 /// Information about the exception that caused the process to exit
192 ///
193 /// See [`MINIDUMP_EXCEPTION_STREAM`].
194 ExceptionStream = 6,
195 /// System information
196 ///
197 /// See [`MINIDUMP_SYSTEM_INFO`].
198 SystemInfoStream = 7,
199 ThreadExListStream = 8,
200 /// The list of large memory regions from the process contained within this dump
201 ///
202 /// See [`MINIDUMP_MEMORY_DESCRIPTOR64`].
203 ///
204 /// Microsoft declares a [`MINIDUMP_MEMORY64_LIST`][list] struct which is the actual format
205 /// of this stream, but it is a variable-length struct so no matching definition is provided
206 /// in this crate.
207 ///
208 /// [list]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_memory64_list
209 Memory64ListStream = 9,
210 CommentStreamA = 10,
211 CommentStreamW = 11,
212 /// The list of handles used by the process
213 ///
214 /// See [`MINIDUMP_HANDLE_DATA_STREAM`]
215 HandleDataStream = 12,
216 FunctionTable = 13,
217 /// The list of executable modules from the process that were unloaded by the time of the crash
218 ///
219 /// See [`MINIDUMP_UNLOADED_MODULE`].
220 ///
221 /// Microsoft declares a [`MINIDUMP_UNLOADED_MODULE_LIST`][list] struct which is the actual
222 /// format of this stream, but it is a variable-length struct so no matching definition is
223 /// in this crate.
224 ///
225 /// Note that unlike other lists, this one has the newer "extended" header.
226 ///
227 /// [list]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_unloaded_module_list
228 UnloadedModuleListStream = 14,
229 /// Miscellaneous process and system information
230 ///
231 /// See ['MINIDUMP_MISC_INFO'].
232 MiscInfoStream = 15,
233 /// Information about memory regions from the process
234 ///
235 /// See ['MINIDUMP_MEMORY_INFO_LIST'].
236 MemoryInfoListStream = 16,
237 ThreadInfoListStream = 17,
238 HandleOperationListStream = 18,
239 TokenStream = 19,
240 JavaScriptDataStream = 20,
241 SystemMemoryInfoStream = 21,
242 ProcessVmCountersStream = 22,
243 IptTraceStream = 23,
244 /// Names of threads
245 ///
246 /// See ['MINIDUMP_THREAD_NAME'].
247 ThreadNamesStream = 24,
248 /* Windows CE types, the list is available here https://docs.microsoft.com/en-us/previous-versions/windows/embedded/ms939649(v=msdn.10) */
249 /// Start of the Windows CE enumerated list, unused.
250 ceStreamNull = 0x00008000,
251 /// System-wide information about the device and operating system where the fault occurred. Windows CE-specific.
252 ceStreamSystemInfo = 0x00008001,
253 /// Exception record and context for the exception that caused the dump file creation. Windows CE-specific.
254 ceStreamException = 0x00008002,
255 /// Modules that were active on the device at the time the dump file was created. Windows CE-specific.
256 ceStreamModuleList = 0x00008003,
257 /// Processes that were active on the device at the time the dump file was created. Windows CE-specific.
258 ceStreamProcessList = 0x00008004,
259 /// Threads that were active on the device at the time the dump file was created. Windows CE-specific.
260 ceStreamThreadList = 0x00008005,
261 /// List of thread context records. Windows CE-specific.
262 ceStreamThreadContextList = 0x00008006,
263 /// List of thread callstack records. Windows CE-specific.
264 ceStreamThreadCallStackList = 0x00008007,
265 /// List of virtual memory dumps. Windows CE-specific.
266 ceStreamMemoryVirtualList = 0x00008008,
267 /// List of physical memory dumps. Windows CE-specific.
268 ceStreamMemoryPhysicalList = 0x00008009,
269 /// Bucketing parameters for Watson server. Windows CE-specific.
270 ceStreamBucketParameters = 0x0000800a,
271 /// Undocumented Windows CE-specific stream.
272 ceStreamProcessModuleMap = 0x0000800b,
273 /// Undocumented Windows CE-specific stream.
274 ceStreamDiagnosisList = 0x0000800c,
275 /// Last stream reserved for use by Windows Operating Systems.
276 LastReservedStream = 0x0000ffff,
277 /* Breakpad extension types. 0x4767 = "Gg" */
278 /// Additional process information (Breakpad extension)
279 ///
280 /// See ['MINIDUMP_BREAKPAD_INFO'].
281 BreakpadInfoStream = 0x47670001,
282 /// Assertion information (Breakpad extension)
283 ///
284 /// See ['MINIDUMP_ASSERTION_INFO'].
285 AssertionInfoStream = 0x47670002,
286 /* These are additional minidump stream values which are specific to
287 * the linux breakpad implementation. */
288 /// The contents of /proc/cpuinfo from a Linux system
289 LinuxCpuInfo = 0x47670003,
290 /// The contents of /proc/self/status from a Linux system
291 LinuxProcStatus = 0x47670004,
292 /// The contents of /etc/lsb-release from a Linux system
293 LinuxLsbRelease = 0x47670005,
294 /// The contents of /proc/self/cmdline from a Linux system
295 LinuxCmdLine = 0x47670006,
296 /// The contents of /proc/self/environ from a Linux system
297 LinuxEnviron = 0x47670007,
298 /// The contents of /proc/self/auxv from a Linux system
299 LinuxAuxv = 0x47670008,
300 /// The contents of /proc/self/maps from a Linux system
301 LinuxMaps = 0x47670009,
302 /// Information from the Linux dynamic linker useful for writing core dumps
303 ///
304 /// See ['DSO_DEBUG_64'] and ['DSO_DEBUG_32'].
305 LinuxDsoDebug = 0x4767000A,
306 // Crashpad extension types. 0x4350 = "CP"
307 /// Crashpad-specific information containing annotations.
308 ///
309 /// See [`MINIDUMP_CRASHPAD_INFO`].
310 CrashpadInfoStream = 0x43500001,
311
312 /// Data from the __DATA,__crash_info section of every module which contains
313 /// one that has useful data. Only available on macOS. 0x4D7A = "Mz".
314 ///
315 /// See ['MINIDUMP_MAC_CRASH_INFO'].
316 MozMacosCrashInfoStream = 0x4d7a0001,
317
318 /// The kernel boot args on the machine where the crashed process is
319 /// running. Only available on macOS. 0x4D7A = "Mz".
320 ///
321 /// See ['MINIDUMP_MAC_BOOTARGS']
322 MozMacosBootargsStream = 0x4d7a0002,
323
324 /// The contents of /proc/self/limits from a Linux system
325 MozLinuxLimits = 0x4d7a0003,
326
327 /// Soft errors reported during minidump generation
328 MozSoftErrors = 0x4d7a0004,
329}
330
331impl From<MINIDUMP_STREAM_TYPE> for u32 {
332 fn from(ty: MINIDUMP_STREAM_TYPE) -> Self {
333 ty as u32
334 }
335}
336
337/// The name of a thread, found in the ThreadNamesStream.
338#[derive(Debug, Clone, Default, Pread, Pwrite, SizeWith)]
339pub struct MINIDUMP_THREAD_NAME {
340 /// The id of the thread.
341 pub thread_id: u32,
342 /// Where the name of the thread is stored (yes, the legendary RVA64 is real!!).
343 pub thread_name_rva: RVA64,
344}
345
346/// Information about a single module (executable or shared library) from a minidump
347///
348/// This struct matches the [Microsoft struct][msdn] of the same name.
349///
350/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_module
351#[derive(Debug, Clone, Default, Pread, Pwrite, SizeWith)]
352pub struct MINIDUMP_MODULE {
353 /// The base address of the executable image in memory.
354 pub base_of_image: u64,
355 /// The size of the executable image in memory, in bytes.
356 pub size_of_image: u32,
357 /// The checksum value from the PE headers.
358 pub checksum: u32,
359 /// The timestamp value from the PE headers in `time_t` format.
360 pub time_date_stamp: u32,
361 /// An offset to a length-prefixed UTF-16LE string containing the name of the module.
362 pub module_name_rva: RVA,
363 /// Version information for this module.
364 pub version_info: VS_FIXEDFILEINFO,
365 /// The location of a CodeView record describing debug information for this module.
366 ///
367 /// This should be one of [`CV_INFO_PDB70`][pdb70], [`CV_INFO_PDB20`][pdb20], or
368 /// [`CV_INFO_ELF`][elf]. `PDB70` is the most common in practice, describing a standalone PDB
369 /// file by way of GUID, age, and PDB filename, and `ELF` is a Breakpad extension for
370 /// describing ELF modules with Build IDs.
371 ///
372 /// See [Matching Debug Information][dbg] for more information.
373 ///
374 /// [dbg]: http://web.archive.org/web/20210227224734/https://www.debuginfo.com/articles/debuginfomatch.html
375 /// [pdb70]: struct.CV_INFO_PDB70.html
376 /// [pdb20]: struct.CV_INFO_PDB20.html
377 /// [elf]: struct.CV_INFO_ELF.html
378 pub cv_record: MINIDUMP_LOCATION_DESCRIPTOR,
379 /// The location of an `IMAGE_DEBUG_MISC` record describing debug information for this module.
380 pub misc_record: MINIDUMP_LOCATION_DESCRIPTOR,
381 pub reserved0: [u32; 2],
382 pub reserved1: [u32; 2],
383}
384
385/// Information about a single unloaded module (executable or shared library) from a minidump.
386///
387/// This struct matches the [Microsoft struct][msdn] of the same name.
388///
389/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_unloaded_module
390#[derive(Debug, Clone, Default, Pread, Pwrite, SizeWith)]
391pub struct MINIDUMP_UNLOADED_MODULE {
392 /// The base address of the executable image in memory (when it was loaded).
393 pub base_of_image: u64,
394 /// The size of the executable image in memory, in bytes.
395 pub size_of_image: u32,
396 /// The checksum value from the PE headers.
397 pub checksum: u32,
398 /// The timestamp value from the PE headers in `time_t` format.
399 pub time_date_stamp: u32,
400 /// An offset to a length-prefixed UTF-16LE string containing the name of the module.
401 pub module_name_rva: RVA,
402}
403
404/// Version information for a file
405///
406/// This struct matches the [Microsoft struct][msdn] of the same name.
407///
408/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo
409#[derive(Debug, Clone, Default, Pread, Pwrite, SizeWith)]
410pub struct VS_FIXEDFILEINFO {
411 /// Contains the value of `VS_FFI_SIGNATURE`
412 pub signature: u32,
413 /// Should contain the value of `VS_FFI_STRUCVERSION`
414 pub struct_version: u32,
415 pub file_version_hi: u32,
416 pub file_version_lo: u32,
417 pub product_version_hi: u32,
418 pub product_version_lo: u32,
419 pub file_flags_mask: u32,
420 pub file_flags: u32,
421 pub file_os: u32,
422 pub file_type: u32,
423 pub file_subtype: u32,
424 pub file_date_hi: u32,
425 pub file_date_lo: u32,
426}
427
428/// The expected value of `VS_FIXEDFILEINFO.signature`
429pub const VS_FFI_SIGNATURE: u32 = 0xfeef04bd;
430
431/// The expected value of `VS_FIXEDFILEINFO.struct_version`
432pub const VS_FFI_STRUCVERSION: u32 = 0x00010000;
433
434/// Known values for the `signature` field of CodeView records
435///
436/// In addition to the two CodeView record formats used for linking
437/// to external pdb files it is possible for debugging data to be carried
438/// directly in the CodeView record itself. These signature values will
439/// be found in the first 4 bytes of the CodeView record. Additional values
440/// not commonly experienced in the wild are given by ["Microsoft Symbol and
441/// Type Information"][sym] section 7.2. An in-depth description of the CodeView 4.1 format
442/// is given by ["Undocumented Windows 2000 Secrets"][win2k], Windows 2000 Debugging Support/
443/// Microsoft Symbol File Internals/CodeView Subsections.
444///
445/// [sym]: http://web.archive.org/web/20070915060650/http://www.x86.org/ftp/manuals/tools/sym.pdf
446/// [win2k]: https://dl.acm.org/citation.cfm?id=375734
447#[repr(u32)]
448#[derive(Copy, Clone, PartialEq, Eq, Debug, FromPrimitive)]
449pub enum CvSignature {
450 /// PDB 2.0 CodeView data: 'NB10': [`CV_INFO_PDB20`]
451 Pdb20 = 0x3031424e,
452 /// PDB 7.0 CodeView data: 'RSDS': [`CV_INFO_PDB70`]
453 Pdb70 = 0x53445352,
454 /// ELF Build ID, a Breakpad extension: 'BpEL': [`CV_INFO_ELF`]
455 Elf = 0x4270454c,
456 /// CodeView 4.10: 'NB09'
457 Cv41 = 0x3930424e,
458 /// CodeView 5.0: 'NB11'
459 Cv50 = 0x3131424e,
460}
461
462/// CodeView debug information in the older PDB 2.0 ("NB10") format.
463///
464/// This struct is defined as variable-length in C with a trailing PDB filename member.
465#[derive(Debug, Clone)]
466pub struct CV_INFO_PDB20 {
467 /// This field will always be [`CvSignature::Pdb20`].
468 pub cv_signature: u32,
469 pub cv_offset: u32,
470 pub signature: u32,
471 pub age: u32,
472 /// The PDB filename as a zero-terminated byte string
473 pub pdb_file_name: Vec<u8>,
474}
475
476impl scroll::ctx::TryFromCtx<'_, Endian> for CV_INFO_PDB20 {
477 type Error = scroll::Error;
478
479 fn try_from_ctx(src: &[u8], endian: Endian) -> Result<(Self, usize), Self::Error> {
480 let offset = &mut 0;
481 Ok((
482 CV_INFO_PDB20 {
483 cv_signature: src.gread_with(offset, endian)?,
484 cv_offset: src.gread_with(offset, endian)?,
485 signature: src.gread_with(offset, endian)?,
486 age: src.gread_with(offset, endian)?,
487 pdb_file_name: {
488 let size = src.len() - *offset;
489 src.gread_with::<&[u8]>(offset, size)?.to_owned()
490 },
491 },
492 *offset,
493 ))
494 }
495}
496
497/// CodeView debug information in the current PDB 7.0 ("RSDS") format.
498///
499/// This struct is defined as variable-length in C with a trailing PDB filename member.
500#[derive(Debug, Clone)]
501pub struct CV_INFO_PDB70 {
502 /// This will always be [`CvSignature::Pdb70`]
503 pub cv_signature: u32,
504 /// A unique identifer for a module created on first build.
505 pub signature: GUID,
506 /// A counter, incremented for each rebuild that updates the PDB file.
507 pub age: u32,
508 /// The PDB filename as a zero-terminated byte string
509 pub pdb_file_name: Vec<u8>,
510}
511
512impl scroll::ctx::TryFromCtx<'_, Endian> for CV_INFO_PDB70 {
513 type Error = scroll::Error;
514
515 fn try_from_ctx(src: &[u8], endian: Endian) -> Result<(Self, usize), Self::Error> {
516 let offset = &mut 0;
517 Ok((
518 CV_INFO_PDB70 {
519 cv_signature: src.gread_with(offset, endian)?,
520 signature: src.gread_with(offset, endian)?,
521 age: src.gread_with(offset, endian)?,
522 pdb_file_name: {
523 let size = src.len() - *offset;
524 src.gread_with::<&[u8]>(offset, size)?.to_owned()
525 },
526 },
527 *offset,
528 ))
529 }
530}
531
532/// A GUID as specified in Rpcdce.h
533///
534/// Matches the [Microsoft struct][msdn] of the same name.
535///
536/// # Display
537///
538/// There are two `Display` implementations for GUIDs. The regular formatting is lowercase with
539/// hyphens. The alternate formatting used with `#` is the symbol server format (uppercase without
540/// hyphens).
541///
542/// ```
543/// use minidump_common::format::GUID;
544///
545/// let guid = GUID { data1: 10, data2: 11, data3: 12, data4: [1,2,3,4,5,6,7,8] };
546///
547/// // default formatting
548/// assert_eq!("0000000a-000b-000c-0102-030405060708", guid.to_string());
549///
550/// // symbol server formatting
551/// assert_eq!("0000000A000B000C0102030405060708", format!("{:#}", guid));
552/// ```
553///
554/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid
555#[derive(Clone, Copy, Debug, PartialEq, Eq, Pread, Pwrite, SizeWith)]
556pub struct GUID {
557 pub data1: u32,
558 pub data2: u16,
559 pub data3: u16,
560 pub data4: [u8; 8],
561}
562
563/// Creates a GUID from a raw byte array. It is assumed that the components in
564/// the array are in big-endian order.
565///
566/// ```
567/// use minidump_common::format::GUID;
568///
569/// let mut buf = [0u8; 16];
570/// buf[0..4].copy_from_slice(&0xdeadc0deu32.to_be_bytes());
571/// buf[4..6].copy_from_slice(&0xb105u16.to_be_bytes());
572/// buf[6..8].copy_from_slice(&0xc0deu16.to_be_bytes());
573/// buf[8..].copy_from_slice(&[1, 2, 3, 4, 5, 6, 7, 8]);
574///
575/// let guid: GUID = buf.into();
576///
577/// let expected = GUID { data1: 0xdeadc0de, data2: 0xb105, data3: 0xc0de, data4: [1, 2, 3, 4, 5, 6, 7, 8] };
578///
579/// assert_eq!(guid, expected);
580/// ```
581impl From<[u8; 16]> for GUID {
582 fn from(uuid: [u8; 16]) -> Self {
583 let data1 = (uuid[0] as u32) << 24
584 | (uuid[1] as u32) << 16
585 | (uuid[2] as u32) << 8
586 | uuid[3] as u32;
587 let data2 = (uuid[4] as u16) << 8 | uuid[5] as u16;
588 let data3 = (uuid[6] as u16) << 8 | uuid[7] as u16;
589 let mut data4 = [0u8; 8];
590 data4.copy_from_slice(&uuid[8..]);
591
592 Self {
593 data1,
594 data2,
595 data3,
596 data4,
597 }
598 }
599}
600
601impl fmt::Display for GUID {
602 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
603 // NB: This formatting is not endianness aware. GUIDs read from LE minidumps are printed
604 // with reversed fields.
605 if f.alternate() {
606 write!(
607 f,
608 "{:08X}{:04X}{:04X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}",
609 self.data1,
610 self.data2,
611 self.data3,
612 self.data4[0],
613 self.data4[1],
614 self.data4[2],
615 self.data4[3],
616 self.data4[4],
617 self.data4[5],
618 self.data4[6],
619 self.data4[7],
620 )
621 } else {
622 write!(
623 f,
624 "{:08x}-{:04x}-{:04x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
625 self.data1,
626 self.data2,
627 self.data3,
628 self.data4[0],
629 self.data4[1],
630 self.data4[2],
631 self.data4[3],
632 self.data4[4],
633 self.data4[5],
634 self.data4[6],
635 self.data4[7],
636 )
637 }
638 }
639}
640
641/// An ELF Build ID.
642///
643/// Modern ELF toolchains insert a "[build id][buildid]" into the ELF headers that typically
644/// contains a hash of some ELF headers and sections to uniquely identify a binary. The Build ID
645/// is allowed to be an arbitrary number of bytes however, and [GNU binutils allows creating
646/// ELF binaries with Build IDs of various formats][binutils].
647///
648/// [buildid]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/developer_guide/compiling-build-id
649/// [binutils]: https://sourceware.org/binutils/docs-2.26/ld/Options.html#index-g_t_002d_002dbuild_002did-292
650#[derive(Debug, Clone)]
651pub struct CV_INFO_ELF {
652 /// This will always be [`CvSignature::Elf`]
653 pub cv_signature: u32,
654 /// The build id, a variable number of bytes
655 pub build_id: Vec<u8>,
656}
657
658impl<'a> scroll::ctx::TryFromCtx<'a, Endian> for CV_INFO_ELF {
659 type Error = scroll::Error;
660
661 fn try_from_ctx(src: &'a [u8], endian: Endian) -> Result<(Self, usize), Self::Error> {
662 let offset = &mut 0;
663 Ok((
664 CV_INFO_ELF {
665 cv_signature: src.gread_with(offset, endian)?,
666 build_id: {
667 let size = src.len() - *offset;
668 src.gread_with::<&[u8]>(offset, size)?.to_owned()
669 },
670 },
671 *offset,
672 ))
673 }
674}
675
676/// Obsolete debug record type defined in WinNT.h.
677#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
678pub struct IMAGE_DEBUG_MISC {
679 pub data_type: u32,
680 pub length: u32,
681 pub unicode: u8,
682 pub reserved: [u8; 3],
683 pub data: [u8; 1],
684}
685
686/// Information about a single thread from a minidump
687///
688/// This struct matches the [Microsoft struct][msdn] of the same name.
689///
690/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_thread
691#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
692pub struct MINIDUMP_THREAD {
693 /// The identifier of this thread
694 pub thread_id: u32,
695 /// The suspend count for this thread
696 ///
697 /// If greater than zero, the thread is suspended.
698 pub suspend_count: u32,
699 /// The priority class of the thread
700 ///
701 /// See [Scheduling Priorities][msdn] on MSDN.
702 ///
703 /// [msdn]: https://docs.microsoft.com/en-us/windows/win32/ProcThread/scheduling-priorities
704 pub priority_class: u32,
705 /// The priority level of the thread
706 pub priority: u32,
707 /// The thread environment block
708 pub teb: u64,
709 /// The location and base address of this thread's stack memory
710 pub stack: MINIDUMP_MEMORY_DESCRIPTOR,
711 /// The location of a CPU-specific `CONTEXT_` struct for this thread's CPU context
712 pub thread_context: MINIDUMP_LOCATION_DESCRIPTOR,
713}
714
715/// Information about the exception that caused the process to terminate.
716///
717/// This struct matches the [Microsoft struct][msdn] of the same name.
718///
719/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_exception_stream
720#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
721pub struct MINIDUMP_EXCEPTION_STREAM {
722 /// The identifier of the thread that encountered the exception.
723 pub thread_id: u32,
724 pub __align: u32,
725 /// Detailed information about the exception encountered.
726 pub exception_record: MINIDUMP_EXCEPTION,
727 /// The offset of a CPU context record from the time the thread encountered the exception.
728 ///
729 /// The actual data will be one of the `CONTEXT_*` structs defined here.
730 pub thread_context: MINIDUMP_LOCATION_DESCRIPTOR,
731}
732
733/// Detailed information about an exception.
734///
735/// This struct matches the [Microsoft struct][msdn] of the same name.
736///
737/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_exception
738#[derive(Debug, Clone, Default, Pread, Pwrite, SizeWith)]
739pub struct MINIDUMP_EXCEPTION {
740 /// The reason the exception occurred.
741 ///
742 /// Possible values are in the following enums:
743 ///
744 /// * [`ExceptionCodeWindows`](crate::errors::ExceptionCodeWindows)
745 /// * [`WinErrorWindows`](crate::errors::WinErrorWindows)
746 /// * [`NtStatusWindows`](crate::errors::NtStatusWindows)
747 /// * [`ExceptionCodeLinux`](crate::errors::ExceptionCodeLinux)
748 /// * [`ExceptionCodeMac`](crate::errors::ExceptionCodeMac)
749 pub exception_code: u32,
750 /// Flags related to the exception.
751 ///
752 /// On Windows this is 1 for noncontinuable exceptions and 0 otherwise. For Breakpad-produced
753 /// minidumps on macOS this field is used to store additional exception information.
754 pub exception_flags: u32,
755 /// The address of an associated [`MINIDUMP_EXCEPTION`] for a nested exception.
756 ///
757 /// This address is in the minidump producing host's memory.
758 pub exception_record: u64,
759 /// The address where the exception occurred.
760 ///
761 /// For Breakpad-produced minidumps on macOS this is the exception subcode, which is
762 /// typically the address.
763 pub exception_address: u64,
764 /// The number of valid elements in [`MINIDUMP_EXCEPTION::exception_information`].
765 pub number_parameters: u32,
766 pub __align: u32,
767 /// An array of additional arguments that describe the exception.
768 ///
769 /// For most exception codes the array elements are undefined, but for access violations
770 /// the array will contain two elements: a read/write flag in the first element and
771 /// the virtual address whose access caused the exception in the second element.
772 pub exception_information: [u64; 15], // EXCEPTION_MAXIMUM_PARAMETERS
773}
774
775/// Valid bits in a `context_flags` for [`ContextFlagsCpu`]
776pub const CONTEXT_CPU_MASK: u32 = 0xffffff00;
777/// x86 and x64 contexts have this bit set in their `context_flags` when they have
778/// extra XSTATE beyond the traditional context definition.
779pub const CONTEXT_HAS_XSTATE: u32 = 0x00000040;
780
781bitflags! {
782 /// CPU type values in the `context_flags` member of `CONTEXT_` structs
783 ///
784 /// This applies to the [`CONTEXT_ARM`], [`CONTEXT_PPC`], [`CONTEXT_MIPS`],
785 /// [`CONTEXT_AMD64`], [`CONTEXT_ARM64`], [`CONTEXT_PPC64`], [`CONTEXT_SPARC`] and
786 /// [`CONTEXT_ARM64_OLD`] structs.
787 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
788 pub struct ContextFlagsCpu: u32 {
789 const CONTEXT_IA64 = 0x80000;
790 /// Super-H, includes SH3, from winnt.h in the Windows CE 5.0 SDK
791 const CONTEXT_SHX = 0xc0;
792 /// From winnt.h in the Windows CE 5.0 SDK, no longer used
793 ///
794 /// Originally used by Breakpad but changed after conflicts with other context
795 /// flag bits.
796 const CONTEXT_ARM_OLD = 0x40;
797 /// Alpha, from winnt.h in the Windows CE 5.0 SDK
798 const CONTEXT_ALPHA = 0x20000;
799 const CONTEXT_AMD64 = 0x100000;
800 const CONTEXT_ARM = 0x40000000;
801 const CONTEXT_ARM64 = 0x400000;
802 const CONTEXT_ARM64_OLD = 0x80000000;
803 const CONTEXT_MIPS = 0x40000;
804 const CONTEXT_MIPS64 = 0x80000;
805 const CONTEXT_PPC = 0x20000000;
806 const CONTEXT_PPC64 = 0x1000000;
807 const CONTEXT_SPARC = 0x10000000;
808 const CONTEXT_X86 = 0x10000;
809 }
810}
811
812impl ContextFlagsCpu {
813 /// Populate a [`ContextFlagsCpu`] with valid bits from `flags`
814 pub fn from_flags(flags: u32) -> ContextFlagsCpu {
815 ContextFlagsCpu::from_bits_truncate(flags & CONTEXT_CPU_MASK)
816 }
817}
818
819bitflags! {
820 /// Flags available for use in [`CONTEXT_AMD64.context_flags`]
821 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
822 pub struct ContextFlagsAmd64: u32 {
823 /// SegSs, Rsp, SegCs, Rip, and EFlags
824 const CONTEXT_AMD64_CONTROL = 0x00000001 | ContextFlagsCpu::CONTEXT_AMD64.bits();
825 /// Rax, Rcx, Rdx, Rbx, Rbp, Rsi, Rdi, and R8-R15
826 const CONTEXT_AMD64_INTEGER = 0x00000002 | ContextFlagsCpu::CONTEXT_AMD64.bits();
827 /// SegDs, SegEs, SegFs, and SegGs
828 const CONTEXT_AMD64_SEGMENTS = 0x00000004 | ContextFlagsCpu::CONTEXT_AMD64.bits();
829 /// Xmm0-Xmm15
830 const CONTEXT_AMD64_FLOATING_POINT = 0x00000008 | ContextFlagsCpu::CONTEXT_AMD64.bits();
831 /// Dr0-Dr3 and Dr6-Dr7
832 const CONTEXT_AMD64_DEBUG_REGISTERS = 0x00000010 | ContextFlagsCpu::CONTEXT_AMD64.bits();
833 const CONTEXT_AMD64_XSTATE = 0x00000020 | ContextFlagsCpu::CONTEXT_AMD64.bits();
834 const CONTEXT_AMD64_FULL = Self::CONTEXT_AMD64_CONTROL.bits() | Self::CONTEXT_AMD64_INTEGER.bits() | Self::CONTEXT_AMD64_FLOATING_POINT.bits();
835 const CONTEXT_AMD64_ALL = Self::CONTEXT_AMD64_FULL.bits() | Self::CONTEXT_AMD64_SEGMENTS.bits() | Self::CONTEXT_AMD64_DEBUG_REGISTERS.bits();
836 }
837}
838
839bitflags! {
840 /// Flags available for use in [`CONTEXT_X86.context_flags`]
841 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
842 pub struct ContextFlagsX86: u32 {
843 /// Ebp, Eip, SegCs, EFlags, Esp, SegSs
844 const CONTEXT_X86_CONTROL = 0x00000001 | ContextFlagsCpu::CONTEXT_X86.bits();
845 /// Edi, Esi, Ebx, Edx, Ecx, Eax
846 const CONTEXT_X86_INTEGER = 0x00000002 | ContextFlagsCpu::CONTEXT_X86.bits();
847 /// SegDs, SegEs, SegFs, and SegGs
848 const CONTEXT_X86_SEGMENTS = 0x00000004 | ContextFlagsCpu::CONTEXT_X86.bits();
849 /// Fpcr, Fpsr, Fptag, Fpioff, Fpisel, Fpdoff, Fpdsel, Mxcsr, Mxcsr_mask, Xmm0-Xmm7
850 const CONTEXT_X86_FLOATING_POINT = 0x00000008 | ContextFlagsCpu::CONTEXT_X86.bits();
851 /// Dr0-Dr3 and Dr6-Dr7
852 const CONTEXT_X86_DEBUG_REGISTERS = 0x00000010 | ContextFlagsCpu::CONTEXT_X86.bits();
853 const CONTEXT_X86_EXTENDED_REGISTERS = 0x00000020 | ContextFlagsCpu::CONTEXT_X86.bits();
854 const CONTEXT_X86_XSTATE = 0x00000040 | ContextFlagsCpu::CONTEXT_X86.bits();
855 const CONTEXT_X86_FULL = Self::CONTEXT_X86_CONTROL.bits() | Self::CONTEXT_X86_INTEGER.bits() | Self::CONTEXT_X86_SEGMENTS.bits();
856 const CONTEXT_X86_ALL = Self::CONTEXT_X86_FULL.bits() | Self::CONTEXT_X86_FLOATING_POINT.bits() | Self::CONTEXT_X86_DEBUG_REGISTERS.bits() | Self::CONTEXT_X86_EXTENDED_REGISTERS.bits();
857 }
858}
859
860bitflags! {
861 /// Flags available for use in [`CONTEXT_ARM64.context_flags`]
862 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
863 pub struct ContextFlagsArm64: u32 {
864 /// FP, LR, SP, PC, and CPSR
865 const CONTEXT_ARM64_CONTROL = 0x00000001 | ContextFlagsCpu::CONTEXT_ARM64.bits();
866 /// X0-X28 (but maybe not X18)
867 const CONTEXT_ARM64_INTEGER = 0x00000002 | ContextFlagsCpu::CONTEXT_ARM64.bits();
868 /// Fpcr, Fpsr, D0-D31 (AKA Q0-Q31, AKA S0-S31)
869 const CONTEXT_ARM64_FLOATING_POINT = 0x00000004 | ContextFlagsCpu::CONTEXT_ARM64.bits();
870 /// DBGBVR, DBGBCR, DBGWVR, DBGWCR
871 const CONTEXT_ARM64_DEBUG_REGISTERS = 0x0000008 | ContextFlagsCpu::CONTEXT_ARM64.bits();
872 /// Whether x18 has a valid value, because on Windows it contains the TEB.
873 ///
874 /// NOTE: at this precise moment breakpad doesn't define this, but Microsoft does!
875 const CONTEXT_ARM64_X18 = 0x0000010 | ContextFlagsCpu::CONTEXT_ARM64.bits();
876 const CONTEXT_ARM64_FULL = Self::CONTEXT_ARM64_CONTROL.bits() | Self::CONTEXT_ARM64_INTEGER.bits() | Self::CONTEXT_ARM64_FLOATING_POINT.bits();
877 const CONTEXT_ARM64_ALL = Self::CONTEXT_ARM64_FULL.bits() | Self::CONTEXT_ARM64_DEBUG_REGISTERS.bits() | Self::CONTEXT_ARM64_X18.bits();
878 }
879}
880
881bitflags! {
882 /// Flags available for use in [`CONTEXT_ARM64_OLD.context_flags`]
883 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
884 pub struct ContextFlagsArm64Old: u32 {
885 // Yes, breakpad never defined CONTROL for this context
886
887 /// FP, LR, SP, PC, CPSR, and X0-X28
888 const CONTEXT_ARM64_OLD_INTEGER = 0x00000002 | ContextFlagsCpu::CONTEXT_ARM64_OLD.bits();
889 /// Fpcr, Fpsr, D0-D31 (AKA Q0-Q31, AKA S0-S31)
890 const CONTEXT_ARM64_OLD_FLOATING_POINT = 0x00000004 | ContextFlagsCpu::CONTEXT_ARM64_OLD.bits();
891 const CONTEXT_ARM64_OLD_FULL = Self::CONTEXT_ARM64_OLD_INTEGER.bits() | Self::CONTEXT_ARM64_OLD_FLOATING_POINT.bits();
892 const CONTEXT_ARM64_OLD_ALL = Self::CONTEXT_ARM64_OLD_FULL.bits();
893 }
894}
895
896bitflags! {
897 /// Flags available for use in [`CONTEXT_ARM.context_flags`]
898 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
899 pub struct ContextFlagsArm: u32 {
900 // Yes, breakpad never defined CONTROL for this context
901
902 /// SP, LR, PC, and CPSR
903 const CONTEXT_ARM_CONTROL = 0x00000001 | ContextFlagsCpu::CONTEXT_ARM.bits();
904 /// R0-R12
905 const CONTEXT_ARM_INTEGER = 0x00000002 | ContextFlagsCpu::CONTEXT_ARM.bits();
906 /// Q0-Q15 / D0-D31 / S0-S31
907 const CONTEXT_ARM_FLOATING_POINT = 0x00000004 | ContextFlagsCpu::CONTEXT_ARM.bits();
908 /// DBGBVR, DBGBCR, DBGWVR, DBGWCR
909 const CONTEXT_ARM_DEBUG_REGISTERS = 0x00000008 | ContextFlagsCpu::CONTEXT_ARM.bits();
910 const CONTEXT_ARM_FULL = Self::CONTEXT_ARM_CONTROL.bits() | Self::CONTEXT_ARM_INTEGER.bits() | Self::CONTEXT_ARM_FLOATING_POINT.bits();
911 const CONTEXT_ARM_ALL = Self::CONTEXT_ARM_FULL.bits() | Self::CONTEXT_ARM_DEBUG_REGISTERS.bits();
912 }
913}
914
915/// Possible contents of [`CONTEXT_AMD64::float_save`].
916///
917/// This struct matches the definition of the struct with the same name from WinNT.h.
918#[derive(Debug, SmartDefault, Clone, Pread, Pwrite, SizeWith)]
919pub struct XMM_SAVE_AREA32 {
920 pub control_word: u16,
921 pub status_word: u16,
922 pub tag_word: u8,
923 pub reserved1: u8,
924 pub error_opcode: u16,
925 pub error_offset: u32,
926 pub error_selector: u16,
927 pub reserved2: u16,
928 pub data_offset: u32,
929 pub data_selector: u16,
930 pub reserved3: u16,
931 pub mx_csr: u32,
932 pub mx_csr_mask: u32,
933 #[default([0; 8])]
934 pub float_registers: [u128; 8],
935 #[default([0; 16])]
936 pub xmm_registers: [u128; 16],
937 #[default([0; 96])]
938 pub reserved4: [u8; 96],
939}
940
941/// Possible contents of [`CONTEXT_AMD64::float_save`].
942///
943/// This is defined as an anonymous struct inside an anonymous union in
944/// the x86-64 CONTEXT struct in WinNT.h.
945#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
946pub struct SSE_REGISTERS {
947 pub header: [u128; 2],
948 pub legacy: [u128; 8],
949 pub xmm0: u128,
950 pub xmm1: u128,
951 pub xmm2: u128,
952 pub xmm3: u128,
953 pub xmm4: u128,
954 pub xmm5: u128,
955 pub xmm6: u128,
956 pub xmm7: u128,
957 pub xmm8: u128,
958 pub xmm9: u128,
959 pub xmm10: u128,
960 pub xmm11: u128,
961 pub xmm12: u128,
962 pub xmm13: u128,
963 pub xmm14: u128,
964 pub xmm15: u128,
965}
966
967/// An x86-64 (amd64) CPU context
968///
969/// This struct matches the definition of `CONTEXT` in WinNT.h for x86-64.
970#[derive(Debug, SmartDefault, Clone, Pread, Pwrite, SizeWith)]
971#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
972pub struct CONTEXT_AMD64 {
973 pub p1_home: u64,
974 pub p2_home: u64,
975 pub p3_home: u64,
976 pub p4_home: u64,
977 pub p5_home: u64,
978 pub p6_home: u64,
979 pub context_flags: u32,
980 pub mx_csr: u32,
981 pub cs: u16,
982 pub ds: u16,
983 pub es: u16,
984 pub fs: u16,
985 pub gs: u16,
986 pub ss: u16,
987 pub eflags: u32,
988 pub dr0: u64,
989 pub dr1: u64,
990 pub dr2: u64,
991 pub dr3: u64,
992 pub dr6: u64,
993 pub dr7: u64,
994 pub rax: u64,
995 pub rcx: u64,
996 pub rdx: u64,
997 pub rbx: u64,
998 pub rsp: u64,
999 pub rbp: u64,
1000 pub rsi: u64,
1001 pub rdi: u64,
1002 pub r8: u64,
1003 pub r9: u64,
1004 pub r10: u64,
1005 pub r11: u64,
1006 pub r12: u64,
1007 pub r13: u64,
1008 pub r14: u64,
1009 pub r15: u64,
1010 pub rip: u64,
1011 /// Floating point state
1012 ///
1013 /// This is defined as a union in the C headers, but also
1014 /// ` MAXIMUM_SUPPORTED_EXTENSION` is defined as 512 bytes.
1015 ///
1016 /// Callers that want to access the underlying data can use [`Pread`] to read either
1017 /// an [`XMM_SAVE_AREA32`] or [`SSE_REGISTERS`] struct from this raw data as appropriate.
1018 #[default([0; 512])]
1019 pub float_save: [u8; 512],
1020 #[default([0; 26])]
1021 pub vector_register: [u128; 26],
1022 pub vector_control: u64,
1023 pub debug_control: u64,
1024 pub last_branch_to_rip: u64,
1025 pub last_branch_from_rip: u64,
1026 pub last_exception_to_rip: u64,
1027 pub last_exception_from_rip: u64,
1028}
1029
1030/// ARM floating point state
1031#[derive(Debug, Clone, Default, Pread, Pwrite, SizeWith)]
1032#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1033pub struct FLOATING_SAVE_AREA_ARM {
1034 pub fpscr: u64,
1035 pub regs: [u64; 32],
1036 pub extra: [u32; 8],
1037}
1038
1039/// An ARM CPU context
1040///
1041/// This is a Breakpad extension, and does not match the definition of `CONTEXT` for ARM
1042/// in WinNT.h.
1043#[derive(Debug, Clone, Default, Pread, Pwrite, SizeWith)]
1044#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1045pub struct CONTEXT_ARM {
1046 pub context_flags: u32,
1047 // [r0, r1, ..., r15]
1048 pub iregs: [u32; 16],
1049 pub cpsr: u32,
1050 pub float_save: FLOATING_SAVE_AREA_ARM,
1051}
1052
1053/// Offsets into [`CONTEXT_ARM::iregs`] for registers with a dedicated or conventional purpose
1054#[repr(usize)]
1055#[derive(Copy, Clone, PartialEq, Eq, Debug)]
1056pub enum ArmRegisterNumbers {
1057 IosFramePointer = 7,
1058 FramePointer = 11,
1059 StackPointer = 13,
1060 LinkRegister = 14,
1061 ProgramCounter = 15,
1062}
1063
1064impl ArmRegisterNumbers {
1065 pub const fn name(self) -> &'static str {
1066 match self {
1067 Self::IosFramePointer => "r7",
1068 Self::FramePointer => "r11",
1069 Self::StackPointer => "r13",
1070 Self::LinkRegister => "r14",
1071 Self::ProgramCounter => "r15",
1072 }
1073 }
1074}
1075
1076/// An old (breakpad-style) aarch64 (arm64) CPU context.
1077///
1078/// This is a breakpad extension, but contrary to what the name might suggest,
1079/// it isn't completely out of service. I believe all non-windows platforms
1080/// still prefer emitting this format to avoid needless churn.
1081///
1082/// Semantically this type agrees with the "new" [CONTEXT_ARM64][] and can
1083/// generally be handled with all the same logic. i.e. the general purpose
1084/// `iregs` are the same. It's just that the other fields are shuffled around.
1085///
1086/// As I understand it, this is basically an artifact of breakpad getting to
1087/// arm64 "first" (Android would be first in line for it!) and picking a
1088/// definition they thought was reasonable. Thankfully they picked an
1089/// "out of the way" context id so that when Microsoft came along and picked
1090/// their own definition, there wouldn't be a conflict.
1091///
1092/// Note that we have inlined the fields of the "float save" struct from
1093/// breakpad's definition to be more uniform with [CONTEXT_ARM64][].
1094///
1095/// NOTE: if you ever decide to try to make this repr(C) and get really clever,
1096/// this type is actually non-trivially repr(packed(4)) in the headers!
1097#[derive(Debug, Clone, Copy, Default, Pread, Pwrite, SizeWith)]
1098#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1099pub struct CONTEXT_ARM64_OLD {
1100 pub context_flags: u64,
1101 /// `[x0, x1, ..., x28, fp, lr]`. See [Arm64RegisterNumbers][].
1102 pub iregs: [u64; 31],
1103 pub sp: u64,
1104 pub pc: u64,
1105 pub cpsr: u32,
1106 /// FPU status register.
1107 pub fpsr: u32,
1108 /// FPU control register.
1109 pub fpcr: u32,
1110 /// float/NEON registers `[d0, d1, ..., d31]`
1111 pub float_regs: [u128; 32usize],
1112}
1113
1114/// A (microsoft-style) aarch64 (arm64) CPU context
1115///
1116/// This matches the layout of how Windows defines this type. Breakpad defines
1117/// it in an equivalent but more-quirky way that relies more on packing.
1118///
1119/// For general purpose registers:
1120///
1121/// * microsoft: make iregs have 31 values and have sp and pc as explicit fields.
1122/// * breakpad make iregs have 33 values, no explicit fields.
1123///
1124/// For float registers:
1125///
1126/// * microsoft: inline the fields for float_regs, fpcr, fpsr.
1127/// * breakpad: wrap them in a struct.
1128///
1129/// -----------------
1130///
1131/// Why *we* went with these definitions:
1132///
1133/// * ARM64 actually defines x0..x30 register names, but sp and pc aren't
1134/// "x31" and "x32". Breakpad is effectively punning them as such, and
1135/// that's kinda weird?
1136///
1137/// * Microsft's inlining of the float registers eliminates any need for
1138/// padding on all platforms (note how there's always an even number of
1139/// u32's before a u64, and an even number of u64's before a u128!)
1140///
1141/// NOTE: if you ever decide to try to make this repr(C) and get really clever,
1142/// note that microsoft aligns this to 16 (and as of this writing, rust does
1143/// not consistently aling u128 as such).
1144#[derive(Debug, Default, Clone, Pread, Pwrite, SizeWith)]
1145#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1146pub struct CONTEXT_ARM64 {
1147 pub context_flags: u32,
1148 pub cpsr: u32,
1149 /// `[x0, x1, ..., x28, fp, lr]`. See [Arm64RegisterNumbers][].
1150 pub iregs: [u64; 31],
1151 pub sp: u64,
1152 pub pc: u64,
1153 /// float/NEON registers `[d0, d1, ..., d31]`
1154 pub float_regs: [u128; 32usize],
1155 /// FPU control register.
1156 pub fpcr: u32,
1157 /// FPU status register.
1158 pub fpsr: u32,
1159 pub bcr: [u32; 8],
1160 pub bvr: [u64; 8],
1161 pub wcr: [u32; 2],
1162 pub wvr: [u64; 2],
1163}
1164
1165/// Offsets into [`CONTEXT_ARM64::iregs`] for registers with a dedicated or conventional purpose
1166#[repr(usize)]
1167#[derive(Copy, Clone, PartialEq, Eq, Debug)]
1168pub enum Arm64RegisterNumbers {
1169 FramePointer = 29,
1170 LinkRegister = 30,
1171}
1172
1173impl Arm64RegisterNumbers {
1174 pub const fn name(self) -> &'static str {
1175 match self {
1176 Self::FramePointer => "x29",
1177 Self::LinkRegister => "x30",
1178 }
1179 }
1180}
1181
1182/// MIPS floating point state
1183#[derive(Debug, Default, Clone, Pread, Pwrite, SizeWith)]
1184#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1185pub struct FLOATING_SAVE_AREA_MIPS {
1186 pub regs: [u64; 32],
1187 pub fpcsr: u32,
1188 pub fir: u32,
1189}
1190
1191/// A MIPS CPU context
1192///
1193/// This is a Breakpad extension, as there is no definition of `CONTEXT` for MIPS in WinNT.h.
1194#[derive(Debug, Default, Clone, Pread, Pwrite, SizeWith)]
1195#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1196pub struct CONTEXT_MIPS {
1197 pub context_flags: u32,
1198 pub _pad0: u32,
1199 pub iregs: [u64; 32],
1200 pub mdhi: u64,
1201 pub mdlo: u64,
1202 pub hi: [u32; 3],
1203 pub lo: [u32; 3],
1204 pub dsp_control: u32,
1205 pub _pad1: u32,
1206 pub epc: u64,
1207 pub badvaddr: u64,
1208 pub status: u32,
1209 pub cause: u32,
1210 pub float_save: FLOATING_SAVE_AREA_MIPS,
1211}
1212
1213/// Offsets into [`CONTEXT_MIPS::iregs`] for registers with a dedicated or conventional purpose
1214#[repr(usize)]
1215#[derive(Copy, Clone, PartialEq, Eq, Debug)]
1216pub enum MipsRegisterNumbers {
1217 S0 = 16,
1218 S1 = 17,
1219 S2 = 18,
1220 S3 = 19,
1221 S4 = 20,
1222 S5 = 21,
1223 S6 = 22,
1224 S7 = 23,
1225 GlobalPointer = 28,
1226 StackPointer = 29,
1227 FramePointer = 30,
1228 ReturnAddress = 31,
1229}
1230
1231impl MipsRegisterNumbers {
1232 pub const fn name(self) -> &'static str {
1233 match self {
1234 MipsRegisterNumbers::S0 => "s0",
1235 MipsRegisterNumbers::S1 => "s1",
1236 MipsRegisterNumbers::S2 => "s2",
1237 MipsRegisterNumbers::S3 => "s3",
1238 MipsRegisterNumbers::S4 => "s4",
1239 MipsRegisterNumbers::S5 => "s5",
1240 MipsRegisterNumbers::S6 => "s6",
1241 MipsRegisterNumbers::S7 => "s7",
1242 MipsRegisterNumbers::GlobalPointer => "gp",
1243 MipsRegisterNumbers::StackPointer => "sp",
1244 MipsRegisterNumbers::FramePointer => "fp",
1245 MipsRegisterNumbers::ReturnAddress => "ra",
1246 }
1247 }
1248}
1249
1250/// PPC floating point state
1251#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1252#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1253pub struct FLOATING_SAVE_AREA_PPC {
1254 pub fpregs: [u64; 32],
1255 pub fpscr_pad: u32,
1256 pub fpscr: u32,
1257}
1258
1259/// PPC vector state
1260#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1261#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1262pub struct VECTOR_SAVE_AREA_PPC {
1263 pub save_vr: [u128; 32],
1264 pub save_vscr: u128,
1265 pub save_pad5: [u32; 4],
1266 pub save_vrvalid: u32,
1267 pub save_pad6: [u32; 7],
1268}
1269
1270/// A PPC CPU context
1271///
1272/// This is a Breakpad extension, as there is no definition of `CONTEXT` for PPC in WinNT.h.
1273#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1274#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1275pub struct CONTEXT_PPC {
1276 pub context_flags: u32,
1277 pub srr0: u32,
1278 pub srr1: u32,
1279 pub gpr: [u32; 32],
1280 pub cr: u32,
1281 pub xer: u32,
1282 pub lr: u32,
1283 pub ctr: u32,
1284 pub mq: u32,
1285 pub vrsave: u32,
1286 pub float_save: FLOATING_SAVE_AREA_PPC,
1287 pub vector_save: VECTOR_SAVE_AREA_PPC,
1288}
1289
1290/// Offsets into [`CONTEXT_PPC::gpr`] for registers with a dedicated or conventional purpose
1291#[repr(usize)]
1292#[derive(Copy, Clone, PartialEq, Eq, Debug)]
1293pub enum PpcRegisterNumbers {
1294 StackPointer = 1,
1295}
1296
1297/// A PPC64 CPU context
1298///
1299/// This is a Breakpad extension, as there is no definition of `CONTEXT` for PPC64 in WinNT.h.
1300#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1301#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1302pub struct CONTEXT_PPC64 {
1303 pub context_flags: u64,
1304 pub srr0: u64,
1305 pub srr1: u64,
1306 pub gpr: [u64; 32],
1307 pub cr: u64,
1308 pub xer: u64,
1309 pub lr: u64,
1310 pub ctr: u64,
1311 pub vrsave: u64,
1312 pub float_save: FLOATING_SAVE_AREA_PPC,
1313 pub vector_save: VECTOR_SAVE_AREA_PPC,
1314}
1315
1316/// Offsets into [`CONTEXT_PPC64::gpr`] for registers with a dedicated or conventional purpose
1317#[repr(usize)]
1318#[derive(Copy, Clone, PartialEq, Eq, Debug)]
1319pub enum Ppc64RegisterNumbers {
1320 StackPointer = 1,
1321}
1322
1323/// SPARC floating point state
1324#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1325#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1326pub struct FLOATING_SAVE_AREA_SPARC {
1327 pub regs: [u64; 32],
1328 pub filler: u64,
1329 pub fsr: u64,
1330}
1331
1332/// A SPARC CPU context
1333///
1334/// This is a Breakpad extension, as there is no definition of `CONTEXT` for SPARC in WinNT.h.
1335#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1336#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1337pub struct CONTEXT_SPARC {
1338 pub context_flags: u32,
1339 pub flag_pad: u32,
1340 pub g_r: [u64; 32],
1341 pub ccr: u64,
1342 pub pc: u64,
1343 pub npc: u64,
1344 pub y: u64,
1345 pub asi: u64,
1346 pub fprs: u64,
1347 pub float_save: FLOATING_SAVE_AREA_SPARC,
1348}
1349
1350/// Offsets into [`CONTEXT_SPARC::g_r`] for registers with a dedicated or conventional purpose
1351#[repr(usize)]
1352#[derive(Copy, Clone, PartialEq, Eq, Debug)]
1353pub enum SparcRegisterNumbers {
1354 StackPointer = 14,
1355}
1356
1357/// x86 floating point state
1358///
1359/// This struct matches the definition of the `FLOATING_SAVE_AREA` struct from WinNT.h.
1360#[derive(Debug, Clone, SmartDefault, Pread, Pwrite, SizeWith)]
1361#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1362pub struct FLOATING_SAVE_AREA_X86 {
1363 pub control_word: u32,
1364 pub status_word: u32,
1365 pub tag_word: u32,
1366 pub error_offset: u32,
1367 pub error_selector: u32,
1368 pub data_offset: u32,
1369 pub data_selector: u32,
1370 #[default([0; 80])]
1371 pub register_area: [u8; 80], // SIZE_OF_80387_REGISTERS
1372 pub cr0_npx_state: u32,
1373}
1374
1375/// An x86 CPU context
1376///
1377/// This struct matches the definition of `CONTEXT` in WinNT.h for x86.
1378#[derive(Debug, Clone, SmartDefault, Pread, Pwrite, SizeWith)]
1379#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1380pub struct CONTEXT_X86 {
1381 pub context_flags: u32,
1382 pub dr0: u32,
1383 pub dr1: u32,
1384 pub dr2: u32,
1385 pub dr3: u32,
1386 pub dr6: u32,
1387 pub dr7: u32,
1388 pub float_save: FLOATING_SAVE_AREA_X86,
1389 pub gs: u32,
1390 pub fs: u32,
1391 pub es: u32,
1392 pub ds: u32,
1393 pub edi: u32,
1394 pub esi: u32,
1395 pub ebx: u32,
1396 pub edx: u32,
1397 pub ecx: u32,
1398 pub eax: u32,
1399 pub ebp: u32,
1400 pub eip: u32,
1401 pub cs: u32,
1402 pub eflags: u32,
1403 pub esp: u32,
1404 pub ss: u32,
1405 #[default([0; 512])]
1406 pub extended_registers: [u8; 512], // MAXIMUM_SUPPORTED_EXTENSION
1407}
1408
1409/// CPU information contained within the [`MINIDUMP_SYSTEM_INFO`] struct
1410///
1411/// This struct matches the definition of the `CPU_INFORMATION` union from minidumpapiset.h.
1412#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1413pub struct CPU_INFORMATION {
1414 /// `data` is defined as a union in the Microsoft headers
1415 ///
1416 /// It is the union of [`X86CpuInfo`], [`ARMCpuInfo`] (Breakpad-specific), and
1417 /// [`OtherCpuInfo`] defined below. It does not seem possible to safely derive [`Pread`]
1418 /// on an actual union, so we provide the raw data here and expect callers to use
1419 /// [`Pread`] to derive the specific union representation desired.
1420 pub data: [u8; 24],
1421}
1422
1423/// x86-specific CPU information derived from the `cpuid` instruction
1424///
1425/// This struct matches the definition of the struct of the same name from minidumpapiset.h,
1426/// which is contained within the [`CPU_INFORMATION`] union.
1427#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1428pub struct X86CpuInfo {
1429 pub vendor_id: [u32; 3],
1430 pub version_information: u32,
1431 pub feature_information: u32,
1432 pub amd_extended_cpu_features: u32,
1433}
1434
1435/// Arm-specific CPU information (Breakpad extension)
1436#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1437pub struct ARMCpuInfo {
1438 pub cpuid: u32,
1439 /// Hardware capabilities
1440 ///
1441 /// See [`ArmElfHwCaps`] for possible values.
1442 pub elf_hwcaps: u32,
1443}
1444
1445/// CPU information for non-x86 CPUs
1446///
1447/// This struct matches the definition of the struct of the same name from minidumpapiset.h,
1448/// which is contained within the [`CPU_INFORMATION`] union.
1449#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1450pub struct OtherCpuInfo {
1451 pub processor_features: [u64; 2],
1452}
1453
1454/// Processor and operating system information
1455///
1456/// This struct matches the [Microsoft struct][msdn] of the same name.
1457///
1458/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_system_info
1459#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1460pub struct MINIDUMP_SYSTEM_INFO {
1461 /// The system's processor architecture
1462 ///
1463 /// Known values are defined in [`ProcessorArchitecture`].
1464 pub processor_architecture: u16,
1465 /// x86 (5 = 586, 6 = 686 ...) or ARM (6 = ARMv6, 7 = ARMv7 ...) CPU level
1466 pub processor_level: u16,
1467 /// For x86, 0xMMSS where MM=model, SS=stepping
1468 pub processor_revision: u16,
1469 pub number_of_processors: u8,
1470 pub product_type: u8,
1471 pub major_version: u32,
1472 pub minor_version: u32,
1473 pub build_number: u32,
1474 /// The operating system platform
1475 ///
1476 /// Known values are defined in [`PlatformId`].
1477 pub platform_id: u32,
1478 pub csd_version_rva: RVA,
1479 pub suite_mask: u16,
1480 pub reserved2: u16,
1481 pub cpu: CPU_INFORMATION,
1482}
1483
1484/// Known values of [`MINIDUMP_SYSTEM_INFO::processor_architecture`]
1485///
1486/// Many of these are taken from definitions in WinNT.h, but several of them are
1487/// Breakpad extensions.
1488#[repr(u16)]
1489#[derive(Copy, Clone, PartialEq, Eq, Debug, FromPrimitive)]
1490pub enum ProcessorArchitecture {
1491 PROCESSOR_ARCHITECTURE_INTEL = 0,
1492 PROCESSOR_ARCHITECTURE_MIPS = 1,
1493 PROCESSOR_ARCHITECTURE_ALPHA = 2,
1494 PROCESSOR_ARCHITECTURE_PPC = 3,
1495 PROCESSOR_ARCHITECTURE_SHX = 4,
1496 PROCESSOR_ARCHITECTURE_ARM = 5,
1497 PROCESSOR_ARCHITECTURE_IA64 = 6,
1498 PROCESSOR_ARCHITECTURE_ALPHA64 = 7,
1499 /// Microsoft Intermediate Language
1500 PROCESSOR_ARCHITECTURE_MSIL = 8,
1501 PROCESSOR_ARCHITECTURE_AMD64 = 9,
1502 /// WoW64
1503 PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 = 10,
1504 PROCESSOR_ARCHITECTURE_ARM64 = 12,
1505 /// Breakpad-defined value for SPARC
1506 PROCESSOR_ARCHITECTURE_SPARC = 0x8001,
1507 /// Breakpad-defined value for PPC64
1508 PROCESSOR_ARCHITECTURE_PPC64 = 0x8002,
1509 /// Breakpad-defined value for ARM64
1510 PROCESSOR_ARCHITECTURE_ARM64_OLD = 0x8003,
1511 /// Breakpad-defined value for MIPS64
1512 PROCESSOR_ARCHITECTURE_MIPS64 = 0x8004,
1513 PROCESSOR_ARCHITECTURE_UNKNOWN = 0xffff,
1514}
1515
1516/// Known values of [`MINIDUMP_SYSTEM_INFO::platform_id`]
1517///
1518/// The Windows values here are taken from defines in WinNT.h, but the rest are Breakpad
1519/// extensions.
1520#[repr(u32)]
1521#[derive(Copy, Clone, PartialEq, Eq, Debug, FromPrimitive)]
1522pub enum PlatformId {
1523 /// Windows 3.1
1524 VER_PLATFORM_WIN32s = 1,
1525 /// Windows 95-98-Me
1526 VER_PLATFORM_WIN32_WINDOWS = 2,
1527 /// Windows NT, 2000+
1528 VER_PLATFORM_WIN32_NT = 3,
1529 /// Windows CE, Windows Mobile
1530 VER_PLATFORM_WIN32_CE = 4,
1531 /// Generic Unix-ish (Breakpad extension)
1532 Unix = 0x8000,
1533 /// macOS/Darwin (Breakpad extension)
1534 MacOs = 0x8101,
1535 /// iOS (Breakpad extension)
1536 Ios = 0x8102,
1537 /// Linux (Breakpad extension)
1538 Linux = 0x8201,
1539 /// Solaris (Breakpad extension)
1540 Solaris = 0x8202,
1541 /// Android (Breakpad extension)
1542 Android = 0x8203,
1543 /// PlayStation 3 (Breakpad extension)
1544 Ps3 = 0x8204,
1545 /// Native Client (Breakpad extension)
1546 NaCl = 0x8205,
1547}
1548
1549/// A date and time
1550///
1551/// This struct matches the [Microsoft struct][msdn] of the same name.
1552///
1553/// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724950(v=vs.85).aspx
1554#[derive(Debug, Clone, Default, Pread, Pwrite, SizeWith, PartialEq, Eq)]
1555pub struct SYSTEMTIME {
1556 pub year: u16,
1557 pub month: u16,
1558 pub day_of_week: u16,
1559 pub day: u16,
1560 pub hour: u16,
1561 pub minute: u16,
1562 pub second: u16,
1563 pub milliseconds: u16,
1564}
1565
1566/// Settings for a time zone
1567///
1568/// This struct matches the [Microsoft struct][msdn] of the same name.
1569///
1570/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/timezoneapi/ns-timezoneapi-time_zone_information
1571#[derive(Debug, Clone, Default, Pread, Pwrite, SizeWith)]
1572pub struct TIME_ZONE_INFORMATION {
1573 pub bias: i32,
1574 pub standard_name: [u16; 32],
1575 pub standard_date: SYSTEMTIME,
1576 pub standard_bias: i32,
1577 pub daylight_name: [u16; 32],
1578 pub daylight_date: SYSTEMTIME,
1579 pub daylight_bias: i32,
1580}
1581
1582/*
1583 * There are multiple versions of the misc info struct, and each new version includes all
1584 * fields from the previous versions. We declare them with a macro to avoid repeating
1585 * the fields excessively.
1586 */
1587macro_rules! multi_structs {
1588 // With no trailing struct left, terminate.
1589 (@next { $($prev:tt)* }) => {};
1590 // Declare the next struct, including fields from previous structs.
1591 (@next { $($prev:tt)* } $(#[$attr:meta])* pub struct $name:ident { $($cur:tt)* } $($tail:tt)* ) => {
1592 // Prepend fields from previous structs to this struct.
1593 multi_structs!($(#[$attr])* pub struct $name { $($prev)* $($cur)* } $($tail)*);
1594 };
1595 // Declare a single struct.
1596 ($(#[$attr:meta])* pub struct $name:ident { $( pub $field:ident: $t:tt, )* } $($tail:tt)* ) => {
1597 $(#[$attr])*
1598 #[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1599 pub struct $name {
1600 $( pub $field: $t, )*
1601 }
1602 // Persist its fields down to the following structs.
1603 multi_structs!(@next { $( pub $field: $t, )* } $($tail)*);
1604 };
1605}
1606
1607multi_structs! {
1608 /// Miscellaneous process information
1609 ///
1610 /// This struct matches the [Microsoft struct][msdn] of the same name.
1611 ///
1612 /// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_misc_info
1613 pub struct MINIDUMP_MISC_INFO {
1614 pub size_of_info: u32,
1615 pub flags1: u32,
1616 pub process_id: u32,
1617 pub process_create_time: u32,
1618 pub process_user_time: u32,
1619 pub process_kernel_time: u32,
1620 }
1621 // Includes fields from MINIDUMP_MISC_INFO
1622 /// Miscellaneous process and system information
1623 ///
1624 /// This struct matches the [Microsoft struct][msdn] of the same name.
1625 ///
1626 /// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_misc_info_2
1627 pub struct MINIDUMP_MISC_INFO_2 {
1628 pub processor_max_mhz: u32,
1629 pub processor_current_mhz: u32,
1630 pub processor_mhz_limit: u32,
1631 pub processor_max_idle_state: u32,
1632 pub processor_current_idle_state: u32,
1633 }
1634 // Includes fields from MINIDUMP_MISC_INFO and MINIDUMP_MISC_INFO_2
1635 /// Miscellaneous process and system information
1636 ///
1637 /// This struct matches the struct of the same name from minidumpapiset.h.
1638 pub struct MINIDUMP_MISC_INFO_3 {
1639 pub process_integrity_level: u32,
1640 pub process_execute_flags: u32,
1641 pub protected_process: u32,
1642 pub time_zone_id: u32,
1643 pub time_zone: TIME_ZONE_INFORMATION,
1644 }
1645 // Includes fields from MINIDUMP_MISC_INFO..3
1646 /// Miscellaneous process and system information
1647 ///
1648 /// This struct matches the struct of the same name from minidumpapiset.h.
1649 pub struct MINIDUMP_MISC_INFO_4 {
1650 pub build_string: [u16; 260], // MAX_PATH
1651 pub dbg_bld_str: [u16; 40],
1652 }
1653
1654 // Includes fields from MINIDUMP_MISC_INFO..4
1655 /// Miscellaneous process and system information
1656 ///
1657 /// This struct matches the struct of the same name from minidumpapiset.h.
1658 pub struct MINIDUMP_MISC_INFO_5 {
1659 pub xstate_data: XSTATE_CONFIG_FEATURE_MSC_INFO,
1660 pub process_cookie: u32,
1661 }
1662}
1663
1664/// A descriptor of the XSAVE context, which extends a normal x86/x64 context.
1665///
1666/// The sections of this context are dumps of some of the CPUs registers
1667/// (e.g. one section might contain the contents of the SSE registers).
1668///
1669/// Intel documents its XSAVE entries in Volume 1, Chapter 13 of the
1670/// "Intel 64 and IA-32 Architectures Software Developer’s Manual".
1671///
1672///
1673/// # The XSTATE Format in Minidumps
1674///
1675/// This format is slightly messed up in the context of minidumps because it's
1676/// grafted onto Microsoft's own formats. Here's what's important to know:
1677///
1678/// * The "Cpu Context" and the "XSAVE context" are in fact the same regions
1679/// of memory.
1680///
1681/// * Whether XSTATE is present or not, the classic layouts of CONTEXT_X86
1682/// and [`CONTEXT_AMD64`] both apply -- xstate will only add stuff after *or*
1683/// refine your understanding of memory in the existing layout. So you can
1684/// safely ignore the existence of XSTATE, but you might be missing new info.
1685///
1686/// * AMD64 doesn't have a standard way to save general purpose registers,
1687/// so the first 256 bytes of [`CONTEXT_AMD64`] are just however microsoft
1688/// decided to save the registers, and will not be referred to by the XSTATE.
1689///
1690/// **!!! THIS PART IS IMPORTANT !!!**
1691///
1692/// * As a consequence, all [`XSTATE_FEATURE::offset`] values must have 256
1693/// added to them to get the correct offset for that feature! For example, the
1694/// LEGACY_FLOATING_POINT feature should always have an offset of 0, but it
1695/// is actually at offset 256 in [`CONTEXT_AMD64`] (it corresponds to
1696/// [`CONTEXT_AMD64::float_save`]).
1697///
1698/// * The following features are already contained inside of [`CONTEXT_AMD64`]:
1699/// * LEGACY_FLOATING_POINT
1700/// * LEGACY_SSE
1701/// * GSSE_AND_AVX
1702///
1703/// * If there are XSTATE entries that *actually* map outside of the context's
1704/// normal memory range, then the context's [`context_flags`](`CONTEXT_AMD64::context_flags`)
1705/// will have bit 0x40 set ([`CONTEXT_HAS_XSTATE`]).
1706///
1707/// * [`ContextFlagsCpu::from_flags`] will mask out the [`CONTEXT_HAS_XSTATE`] bit.
1708/// If you want to check for that bit, check the raw value of
1709/// [`context_flags`](`CONTEXT_AMD64::context_flags`).
1710
1711#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1712pub struct XSTATE_CONFIG_FEATURE_MSC_INFO {
1713 /// The size of this struct.
1714 pub size_of_info: u32,
1715 /// The size of the XSAVE context.
1716 pub context_size: u32,
1717 /// The bit `enabled_features[i]` indicates that `features[i]` contains valid data.
1718 pub enabled_features: u64,
1719 /// The offset and size of each XSAVE entry inside the XSAVE context.
1720 pub features: [XSTATE_FEATURE; 64],
1721}
1722
1723impl Default for XSTATE_CONFIG_FEATURE_MSC_INFO {
1724 fn default() -> Self {
1725 Self {
1726 size_of_info: std::mem::size_of::<XSTATE_CONFIG_FEATURE_MSC_INFO>() as u32,
1727 context_size: 0,
1728 enabled_features: 0,
1729 features: [XSTATE_FEATURE::default(); 64],
1730 }
1731 }
1732}
1733
1734impl XSTATE_CONFIG_FEATURE_MSC_INFO {
1735 /// Gets an iterator of all the enabled features.
1736 pub fn iter(&self) -> XstateFeatureIter {
1737 XstateFeatureIter { info: self, idx: 0 }
1738 }
1739}
1740
1741/// An iterator of all the enabled features in an XSTATE_CONFIG_FEATURE_MSC_INFO.
1742#[derive(Debug)]
1743pub struct XstateFeatureIter<'a> {
1744 info: &'a XSTATE_CONFIG_FEATURE_MSC_INFO,
1745 idx: usize,
1746}
1747
1748impl Iterator for XstateFeatureIter<'_> {
1749 type Item = (usize, XSTATE_FEATURE);
1750 fn next(&mut self) -> Option<Self::Item> {
1751 while self.idx < self.info.features.len() {
1752 let cur_idx = self.idx;
1753 self.idx += 1;
1754 if (self.info.enabled_features & (1 << cur_idx)) != 0 {
1755 return Some((cur_idx, self.info.features[cur_idx]));
1756 }
1757 }
1758 None
1759 }
1760}
1761
1762/// Several known entries in `XSTATE_CONFIG_FEATURE_MSC_INFO.features`.
1763#[repr(usize)]
1764#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
1765pub enum XstateFeatureIndex {
1766 LEGACY_FLOATING_POINT = 0,
1767 LEGACY_SSE = 1,
1768 GSSE_AND_AVX = 2,
1769 MPX_BNDREGS = 3,
1770 MPX_BNDCSR = 4,
1771 AVX512_KMASK = 5,
1772 AVX512_ZMM_H = 6,
1773 ACK512_ZMM = 7,
1774 XSTATE_IPT = 8,
1775 XSTATE_LWP = 62,
1776}
1777
1778impl XstateFeatureIndex {
1779 pub fn from_index(idx: usize) -> Option<Self> {
1780 use XstateFeatureIndex::*;
1781 match idx {
1782 0 => Some(LEGACY_FLOATING_POINT),
1783 1 => Some(LEGACY_SSE),
1784 2 => Some(GSSE_AND_AVX),
1785 3 => Some(MPX_BNDREGS),
1786 4 => Some(MPX_BNDCSR),
1787 5 => Some(AVX512_KMASK),
1788 6 => Some(AVX512_ZMM_H),
1789 7 => Some(ACK512_ZMM),
1790 8 => Some(XSTATE_IPT),
1791 62 => Some(XSTATE_LWP),
1792 _ => None,
1793 }
1794 }
1795}
1796
1797/// The offset and size of each XSAVE entry inside the XSAVE context.
1798#[derive(Clone, Copy, Debug, Default, Pread, Pwrite, SizeWith, PartialEq, Eq)]
1799pub struct XSTATE_FEATURE {
1800 /// This entry's offset from the start of the context (in bytes).
1801 ///
1802 /// NOTE: THIS VALUE IS A LIE. At least on AMD64 you need to add 256
1803 /// to this! See the docs of [`XSTATE_CONFIG_FEATURE_MSC_INFO`].
1804 pub offset: u32,
1805 /// This entry's size (in bytes).
1806 pub size: u32,
1807}
1808
1809// For whatever reason Pread array derives use 0u8.into() instead of Default to
1810// create an initial array to write into. Weird.
1811impl From<u8> for XSTATE_FEATURE {
1812 fn from(_input: u8) -> Self {
1813 XSTATE_FEATURE { offset: 0, size: 0 }
1814 }
1815}
1816
1817bitflags! {
1818 /// Known flags for `MINIDUMP_MISC_INFO*.flags1`
1819 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1820 pub struct MiscInfoFlags: u32 {
1821 const MINIDUMP_MISC1_PROCESS_ID = 0x00000001;
1822 const MINIDUMP_MISC1_PROCESS_TIMES = 0x00000002;
1823 const MINIDUMP_MISC1_PROCESSOR_POWER_INFO = 0x00000004;
1824 const MINIDUMP_MISC3_PROCESS_INTEGRITY = 0x00000010;
1825 const MINIDUMP_MISC3_PROCESS_EXECUTE_FLAGS = 0x00000020;
1826 const MINIDUMP_MISC3_TIMEZONE = 0x00000040;
1827 const MINIDUMP_MISC3_PROTECTED_PROCESS = 0x00000080;
1828 const MINIDUMP_MISC4_BUILDSTRING = 0x00000100;
1829 const MINIDUMP_MISC5_PROCESS_COOKIE = 0x00000200;
1830 }
1831}
1832
1833/// A list of memory regions in a minidump
1834///
1835/// This is the format of the [`MINIDUMP_STREAM_TYPE::MemoryInfoListStream`]. The individual
1836/// [`MINIDUMP_MEMORY_INFO`] entries follow this header in the stream.
1837///
1838/// This struct matches the [Microsoft struct][msdn] of the same name.
1839///
1840/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_memory_info_list
1841#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1842pub struct MINIDUMP_MEMORY_INFO_LIST {
1843 /// The size of this header
1844 pub size_of_header: u32,
1845 /// The size of each entry in the list
1846 pub size_of_entry: u32,
1847 /// The number of entries in the list
1848 pub number_of_entries: u64,
1849}
1850
1851/// Information about a memory region in a minidump
1852///
1853/// This struct matches the [Microsoft struct][msdn] of the same name.
1854///
1855/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_memory_info
1856#[derive(Debug, Clone, PartialEq, Eq, Pread, Pwrite, SizeWith)]
1857pub struct MINIDUMP_MEMORY_INFO {
1858 /// The base address of the region of pages
1859 pub base_address: u64,
1860 /// The base address of a range of pages in this region
1861 pub allocation_base: u64,
1862 /// The memory protection when the region was initially allocated
1863 ///
1864 /// See [`MemoryProtection`] for valid values.
1865 pub allocation_protection: u32,
1866 pub __alignment1: u32,
1867 /// The size of the region in which all pages have identical attributes, in bytes
1868 pub region_size: u64,
1869 /// The state of the pages in the region
1870 ///
1871 /// See [`MemoryState`] for valid values.
1872 pub state: u32,
1873 /// The access protection of the pages in the region
1874 ///
1875 /// See [`MemoryProtection`] for valid values.
1876 pub protection: u32,
1877 /// The type of pages in the region
1878 ///
1879 /// See [`MemoryType`] for valid values.
1880 pub _type: u32,
1881 pub __alignment2: u32,
1882}
1883
1884bitflags! {
1885 /// Potential values for [`MINIDUMP_MEMORY_INFO::state`]
1886 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1887 pub struct MemoryState: u32 {
1888 const MEM_COMMIT = 0x01000;
1889 const MEM_FREE = 0x10000;
1890 const MEM_RESERVE = 0x02000;
1891 }
1892}
1893
1894bitflags! {
1895 /// Potential values for [`MINIDUMP_MEMORY_INFO::protection`] and `allocation_protection`
1896 ///
1897 /// See [Microsoft's documentation][msdn] for details.
1898 ///
1899 /// [msdn]: https://docs.microsoft.com/en-us/windows/win32/Memory/memory-protection-constants
1900 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1901 pub struct MemoryProtection: u32 {
1902 const PAGE_NOACCESS = 0x01;
1903 const PAGE_READONLY = 0x02;
1904 const PAGE_READWRITE = 0x04;
1905 const PAGE_WRITECOPY = 0x08;
1906 const PAGE_EXECUTE = 0x10;
1907 const PAGE_EXECUTE_READ = 0x20;
1908 const PAGE_EXECUTE_READWRITE = 0x40;
1909 const PAGE_EXECUTE_WRITECOPY = 0x80;
1910 const ACCESS_MASK = 0xff;
1911 const PAGE_GUARD = 0x100;
1912 const PAGE_NOCACHE = 0x200;
1913 const PAGE_WRITECOMBINE = 0x400;
1914 }
1915}
1916
1917bitflags! {
1918 /// Potential values for [`MINIDUMP_MEMORY_INFO::_type`]
1919 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1920 pub struct MemoryType: u32 {
1921 const MEM_PRIVATE = 0x00020000;
1922 const MEM_MAPPED = 0x00040000;
1923 const MEM_IMAGE = 0x01000000;
1924 }
1925}
1926
1927/// A Breakpad extension containing some additional process information
1928///
1929/// Taken from the definition in Breakpad's [minidump_format.h][fmt].
1930///
1931/// [fmt]: https://chromium.googlesource.com/breakpad/breakpad/+/88d8114fda3e4a7292654bd6ac0c34d6c88a8121/src/google_breakpad/common/minidump_format.h#962
1932#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1933pub struct MINIDUMP_BREAKPAD_INFO {
1934 pub validity: u32,
1935 /// The Thread ID of the handler thread
1936 pub dump_thread_id: u32,
1937 /// The Thread ID of the thread that requested the dump
1938 pub requesting_thread_id: u32,
1939}
1940
1941bitflags! {
1942 /// Potential values for [`MINIDUMP_BREAKPAD_INFO::validity`]
1943 ///
1944 /// Taken from definitions in Breakpad's [minidump_format.h][fmt].
1945 ///
1946 /// [fmt]: https://chromium.googlesource.com/breakpad/breakpad/+/88d8114fda3e4a7292654bd6ac0c34d6c88a8121/src/google_breakpad/common/minidump_format.h#989
1947 pub struct BreakpadInfoValid: u32 {
1948 const DumpThreadId = 1 << 0;
1949 const RequestingThreadId = 1 << 1;
1950 }
1951}
1952
1953/// A Breakpad extension containing information about an assertion that terminated the process
1954///
1955/// Taken from the definition in Breakpad's [minidump_format.h][fmt].
1956///
1957/// [fmt]: https://chromium.googlesource.com/breakpad/breakpad/+/88d8114fda3e4a7292654bd6ac0c34d6c88a8121/src/google_breakpad/common/minidump_format.h#998
1958#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1959pub struct MINIDUMP_ASSERTION_INFO {
1960 /// The assertion that failed, as a 0-terminated UTF16-LE string
1961 pub expression: [u16; 128],
1962 /// The function containing the assertion, as a 0-terminated UTF16-LE string
1963 pub function: [u16; 128],
1964 /// The source file containing the assertion, as a 0-terminated UTF16-LE string
1965 pub file: [u16; 128],
1966 /// The line number in [`file`] containing the assertion
1967 pub line: u32,
1968 /// The assertion type
1969 pub _type: u32,
1970}
1971
1972/// Known values of [`MINIDUMP_ASSERTION_INFO::_type`]
1973/// Taken from the definition in Breakpad's [minidump_format.h][fmt].
1974///
1975/// [fmt]: https://chromium.googlesource.com/breakpad/breakpad/+/88d8114fda3e4a7292654bd6ac0c34d6c88a8121/src/google_breakpad/common/minidump_format.h#1011
1976#[repr(u32)]
1977#[derive(Copy, Clone, PartialEq, Eq, Debug, FromPrimitive)]
1978pub enum AssertionType {
1979 Unknown = 0,
1980 InvalidParameter = 1,
1981 PureVirtualCall = 2,
1982}
1983
1984/// Dynamic linker information for a shared library on 32-bit Linux
1985///
1986/// This is functionally equivalent to the data in `struct link_map` defined in <link.h>.
1987#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
1988pub struct LINK_MAP_32 {
1989 pub addr: u32,
1990 /// The offset of a string containing the filename of this shared library
1991 pub name: RVA,
1992 pub ld: u32,
1993}
1994
1995/// DSO debug data for 32-bit Linux minidumps
1996///
1997/// Used when converting minidumps to coredumps. This is functionally equivalent to the data
1998/// in `struct r_debug` defined in <link.h>.
1999#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
2000pub struct DSO_DEBUG_32 {
2001 /// The version number of this protocol, from `r_debug.r_version`
2002 pub version: u32,
2003 /// The offset of an array of [`LINK_MAP_32`] structs
2004 pub map: RVA,
2005 /// The number of [`LINK_MAP_32`] entries pointed to by `map`
2006 pub dso_count: u32,
2007 /// The address of a function internal to the run-time linker used by debuggers to
2008 /// set a breakpoint.
2009 pub brk: u32,
2010 /// Base address the linker is loaded at
2011 pub ldbase: u32,
2012 /// The address of the "dynamic structure"
2013 pub dynamic: u32,
2014}
2015
2016/// Dynamic linker information for a shared library on 64-bit Linux
2017///
2018/// This is functionally equivalent to the data in `struct link_map` defined in <link.h>.
2019#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
2020pub struct LINK_MAP_64 {
2021 pub addr: u64,
2022 /// The offset of a string containing the filename of this shared library
2023 pub name: RVA,
2024 pub ld: u64,
2025}
2026
2027/// DSO debug data for 64-bit Linux minidumps
2028///
2029/// Used when converting minidumps to coredumps. This is functionally equivalent to the data
2030/// in `struct r_debug` defined in <link.h>.
2031#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
2032pub struct DSO_DEBUG_64 {
2033 /// The version number of this protocol, from `r_debug.r_version`
2034 pub version: u32,
2035 /// The offset of an array of [`LINK_MAP_64`] structs
2036 pub map: RVA,
2037 /// The number of [`LINK_MAP_64`] entries pointed to by `map`
2038 pub dso_count: u32,
2039 /// The address of a function internal to the run-time linker used by debuggers to
2040 /// set a breakpoint.
2041 pub brk: u64,
2042 /// Base address the linker is loaded at
2043 pub ldbase: u64,
2044 /// The address of the "dynamic structure"
2045 pub dynamic: u64,
2046}
2047
2048/// A variable-length UTF-8-encoded string carried within a minidump file.
2049///
2050/// See <https://crashpad.chromium.org/doxygen/structcrashpad_1_1MinidumpUTF8String.html>
2051#[derive(Debug, Clone)]
2052pub struct MINIDUMP_UTF8_STRING {
2053 /// The length of the #Buffer field in bytes, not including the `NUL` terminator.
2054 ///
2055 /// This field is interpreted as a byte count, not a count of Unicode code points.
2056 pub length: u32,
2057 /// The string, encoded in UTF-8, and terminated with a `NUL` byte.
2058 pub buffer: Vec<u8>,
2059}
2060
2061impl scroll::ctx::TryFromCtx<'_, Endian> for MINIDUMP_UTF8_STRING {
2062 type Error = scroll::Error;
2063
2064 fn try_from_ctx(src: &[u8], endian: Endian) -> Result<(Self, usize), Self::Error> {
2065 let offset = &mut 0;
2066 let length: u32 = src.gread_with(offset, endian)?;
2067 let data: &[u8] = src.gread_with(offset, length as usize + 1)?; // +1 for NUL
2068
2069 if !data.ends_with(&[0]) {
2070 return Err(scroll::Error::Custom(
2071 "Minidump String does not end with NUL byte".to_owned(),
2072 ));
2073 }
2074
2075 let buffer = data.to_vec();
2076 Ok((Self { length, buffer }, *offset))
2077 }
2078}
2079
2080/// A key-value pair.
2081///
2082/// See <https://crashpad.chromium.org/doxygen/structcrashpad_1_1MinidumpSimpleStringDictionaryEntry.html>
2083#[derive(Clone, Debug, Pread, Pwrite, SizeWith)]
2084pub struct MINIDUMP_SIMPLE_STRING_DICTIONARY_ENTRY {
2085 /// RVA of a MinidumpUTF8String containing the key of a key-value pair.
2086 pub key: RVA,
2087 /// RVA of a MinidumpUTF8String containing the value of a key-value pair.
2088 pub value: RVA,
2089}
2090
2091/// A list of key-value pairs.
2092///
2093/// See <https://crashpad.chromium.org/doxygen/structcrashpad_1_1MinidumpSimpleStringDictionary.html>
2094#[derive(Clone, Debug, Pread, Pwrite, SizeWith)]
2095pub struct MINIDUMP_SIMPLE_STRING_DICTIONARY {
2096 /// The number of key-value pairs present.
2097 pub count: u32,
2098}
2099
2100/// A list of RVA pointers.
2101///
2102/// See <https://crashpad.chromium.org/doxygen/structcrashpad_1_1MinidumpRVAList.html>
2103#[derive(Clone, Debug, Pread, Pwrite, SizeWith)]
2104pub struct MINIDUMP_RVA_LIST {
2105 /// The number of pointers present.
2106 pub count: u32,
2107}
2108
2109/// A typed annotation object.
2110///
2111/// See <https://crashpad.chromium.org/doxygen/structcrashpad_1_1MinidumpAnnotation.html>
2112#[derive(Clone, Debug, Pread, Pwrite, SizeWith)]
2113pub struct MINIDUMP_ANNOTATION {
2114 /// RVA of a MinidumpUTF8String containing the name of the annotation.
2115 pub name: RVA,
2116 /// The type of data stored in the `value` of the annotation. This may correspond to an \a
2117 /// `MINIDUMP_ANNOTATION_TYPE` or it may be user-defined.
2118 pub ty: u16,
2119 /// This field is always `0`.
2120 pub _reserved: u16,
2121 /// RVA of a `MinidumpByteArray` to the data for the annotation.
2122 pub value: RVA,
2123}
2124
2125impl MINIDUMP_ANNOTATION {
2126 /// An invalid annotation. Reserved for internal use.
2127 ///
2128 /// See <https://crashpad.chromium.org/doxygen/classcrashpad_1_1Annotation.html#a734ee64cd20afdb78acb8656ed867d34>
2129 pub const TYPE_INVALID: u16 = 0;
2130 /// A `NUL`-terminated C-string.
2131 ///
2132 /// See <https://crashpad.chromium.org/doxygen/classcrashpad_1_1Annotation.html#a734ee64cd20afdb78acb8656ed867d34>
2133 pub const TYPE_STRING: u16 = 1;
2134 /// Clients may declare their own custom types by using values greater than this.
2135 ///
2136 /// See <https://crashpad.chromium.org/doxygen/classcrashpad_1_1Annotation.html#a734ee64cd20afdb78acb8656ed867d34>
2137 pub const TYPE_USER_DEFINED: u16 = 0x8000;
2138}
2139
2140/// Additional Crashpad-specific information about a module carried within a minidump file.
2141///
2142/// This structure augments the information provided by MINIDUMP_MODULE. The minidump file must
2143/// contain a module list stream (::kMinidumpStreamTypeModuleList) in order for this structure to
2144/// appear.
2145///
2146/// This structure is versioned. When changing this structure, leave the existing structure intact
2147/// so that earlier parsers will be able to understand the fields they are aware of, and make
2148/// additions at the end of the structure. Revise #kVersion and document each field’s validity based
2149/// on #version, so that newer parsers will be able to determine whether the added fields are valid
2150/// or not.
2151///
2152/// See <https://crashpad.chromium.org/doxygen/structcrashpad_1_1MinidumpModuleCrashpadInfo.html>
2153#[derive(Clone, Debug, Pread, Pwrite, SizeWith)]
2154pub struct MINIDUMP_MODULE_CRASHPAD_INFO {
2155 /// The structure’s version number.
2156 ///
2157 /// Readers can use this field to determine which other fields in the structure are valid. Upon
2158 /// encountering a value greater than `VERSION`, a reader should assume that the structure’s
2159 /// layout is compatible with the structure defined as having value #kVersion.
2160 ///
2161 /// Writers may produce values less than `VERSION` in this field if there is no need for any
2162 /// fields present in later versions.
2163 pub version: u32,
2164 /// A `MinidumpRVAList` pointing to MinidumpUTF8String objects. The module controls the data
2165 /// that appears here.
2166 ///
2167 /// These strings correspond to `ModuleSnapshot::AnnotationsVector()` and do not duplicate
2168 /// anything in `simple_annotations` or `annotation_objects`.
2169 pub list_annotations: MINIDUMP_LOCATION_DESCRIPTOR,
2170 /// A `MinidumpSimpleStringDictionary` pointing to strings interpreted as key-value pairs. The
2171 /// module controls the data that appears here.
2172 ///
2173 /// These key-value pairs correspond to `ModuleSnapshot::AnnotationsSimpleMap()` and do not
2174 /// duplicate anything in `list_annotations` or `annotation_objects`.
2175 pub simple_annotations: MINIDUMP_LOCATION_DESCRIPTOR,
2176 /// A `MinidumpAnnotationList` object containing the annotation objects stored within the
2177 /// module. The module controls the data that appears here.
2178 ///
2179 /// These key-value pairs correspond to `ModuleSnapshot::AnnotationObjects()` and do not
2180 /// duplicate anything in `list_annotations` or `simple_annotations`.
2181 pub annotation_objects: MINIDUMP_LOCATION_DESCRIPTOR,
2182}
2183
2184impl MINIDUMP_MODULE_CRASHPAD_INFO {
2185 /// The structure’s version number.
2186 ///
2187 /// Readers can use this field to determine which other fields in the structure are valid. Upon
2188 /// encountering a value greater than `VERSION`, a reader should assume that the structure’s
2189 /// layout is compatible with the structure defined as having value #kVersion.
2190 ///
2191 /// Writers may produce values less than `VERSION` in this field if there is no need for any
2192 /// fields present in later versions.
2193 pub const VERSION: u32 = 1;
2194}
2195
2196/// A link between a `MINIDUMP_MODULE` structure and additional Crashpad-specific information about a
2197/// module carried within a minidump file.
2198///
2199/// See <https://crashpad.chromium.org/doxygen/structcrashpad_1_1MinidumpModuleCrashpadInfoLink.html>
2200#[derive(Clone, Debug, Pread, Pwrite, SizeWith)]
2201pub struct MINIDUMP_MODULE_CRASHPAD_INFO_LINK {
2202 /// A link to a MINIDUMP_MODULE structure in the module list stream.
2203 ///
2204 /// This field is an index into `MINIDUMP_MODULE_LIST::Modules`. This field’s value must be in
2205 /// the range of `MINIDUMP_MODULE_LIST::NumberOfEntries`.
2206 pub minidump_module_list_index: u32,
2207
2208 /// A link to a MinidumpModuleCrashpadInfo structure.
2209 ///
2210 /// MinidumpModuleCrashpadInfo structures are accessed indirectly through
2211 /// `MINIDUMP_LOCATION_DESCRIPTOR` pointers to allow for future growth of the
2212 /// `MinidumpModuleCrashpadInfo` structure.
2213 pub location: MINIDUMP_LOCATION_DESCRIPTOR,
2214}
2215
2216/// Additional Crashpad-specific information about modules carried within a minidump file.
2217///
2218/// This structure augments the information provided by `MINIDUMP_MODULE_LIST`. The minidump file
2219/// must contain a module list stream (::kMinidumpStreamTypeModuleList) in order for this structure
2220/// to appear.
2221///
2222/// `MinidumpModuleCrashpadInfoList::count` may be less than the value of
2223/// `MINIDUMP_MODULE_LIST::NumberOfModules` because not every `MINIDUMP_MODULE` structure carried
2224/// within the minidump file will necessarily have Crashpad-specific information provided by a
2225/// `MinidumpModuleCrashpadInfo` structure.
2226///
2227/// See <https://crashpad.chromium.org/doxygen/structcrashpad_1_1MinidumpModuleCrashpadInfoList.html>
2228#[derive(Clone, Debug, Pread, Pwrite, SizeWith)]
2229pub struct MINIDUMP_MODULE_CRASHPAD_INFO_LIST {
2230 /// The number of key-value pairs present.
2231 pub count: u32,
2232}
2233
2234/// Additional Crashpad-specific information carried within a minidump file.
2235///
2236/// This structure is versioned. When changing this structure, leave the existing structure intact
2237/// so that earlier parsers will be able to understand the fields they are aware of, and make
2238/// additions at the end of the structure. Revise #kVersion and document each field’s validity based
2239/// on `version`, so that newer parsers will be able to determine whether the added fields are valid
2240/// or not.
2241///
2242/// See <https://crashpad.chromium.org/doxygen/structcrashpad_1_1MinidumpCrashpadInfo.html>
2243#[derive(Clone, Debug, Pread, Pwrite, SizeWith)]
2244pub struct MINIDUMP_CRASHPAD_INFO {
2245 /// The structure’s version number.
2246 ///
2247 /// Readers can use this field to determine which other fields in the structure are valid. Upon
2248 /// encountering a value greater than `VERSION`, a reader should assume that the structure’s
2249 /// layout is compatible with the structure defined as having value #kVersion.
2250 ///
2251 /// Writers may produce values less than `VERSION` in this field if there is no need for any
2252 /// fields present in later versions.
2253 pub version: u32,
2254 /// A `Uuid` identifying an individual crash report.
2255 ///
2256 /// This provides a stable identifier for a crash even as the report is converted to different
2257 /// formats, provided that all formats support storing a crash report ID.
2258 ///
2259 /// If no identifier is available, this field will contain zeroes.
2260 pub report_id: GUID,
2261 /// A `Uuid` identifying the client that crashed.
2262 ///
2263 /// Client identification is within the scope of the application, but it is expected that the
2264 /// identifier will be unique for an instance of Crashpad monitoring an application or set of
2265 /// applications for a user. The identifier shall remain stable over time.
2266 ///
2267 /// If no identifier is available, this field will contain zeroes.
2268 pub client_id: GUID,
2269 /// A MinidumpSimpleStringDictionary pointing to strings interpreted as key-value pairs.
2270 ///
2271 /// These key-value pairs correspond to Crashpad's `ProcessSnapshot::AnnotationsSimpleMap()`.
2272 pub simple_annotations: MINIDUMP_LOCATION_DESCRIPTOR,
2273 /// A pointer to a MinidumpModuleCrashpadInfoList structure.
2274 pub module_list: MINIDUMP_LOCATION_DESCRIPTOR,
2275}
2276
2277impl MINIDUMP_CRASHPAD_INFO {
2278 /// The structure’s currently-defined version number.
2279 pub const VERSION: u32 = 1;
2280}
2281
2282/// MacOS __DATA,__crash_info data.
2283///
2284/// This is the format of the [`MINIDUMP_STREAM_TYPE::MozMacosCrashInfoStream`]. The individual
2285/// [`MINIDUMP_MAC_CRASH_INFO_RECORD`] entries follow this header in the stream.
2286#[derive(Debug, Pread, Pwrite, SizeWith)]
2287pub struct MINIDUMP_MAC_CRASH_INFO {
2288 pub stream_type: u32,
2289 /// The number of [`MINIDUMP_MAC_CRASH_INFO_RECORD`]s.
2290 pub record_count: u32,
2291 /// The size of the "fixed-size" part of MINIDUMP_MAC_CRASH_INFO_RECORD.
2292 /// Used to offset to the variable-length portion of the struct, where
2293 /// C-strings are stored. This allows us to access all the fields we know
2294 /// about, even when newer versions of this format introduce new ones.
2295 pub record_start_size: u32,
2296 pub records: [MINIDUMP_LOCATION_DESCRIPTOR; 20],
2297}
2298
2299// MozMacosCrashInfoStream is a versioned format where new fields are added to
2300// the end of the struct, but there are also variable-length c-string fields
2301// that follow the "fixed-size" fields. As such, the versioned strings are separated
2302// out into their own separate struct with the same version. So e.g.
2303//
2304// MINIDUMP_MAC_CRASH_INFO_RECORD_4 should be paired with MINIDUMP_MAC_CRASH_INFO_RECORD_STRINGS_4
2305
2306multi_structs! {
2307 /// Contents of MacOS's `<CrashReporterClient.h>`'s `crashreporter_annotations_t`,
2308 /// but with the by-reference C-strings hoisted out to the end of the struct
2309 /// and inlined (so this is a variable-length struct).
2310 ///
2311 /// The variable-length strings are listed in [`MINIDUMP_MAC_CRASH_INFO_RECORD_STRINGS`].
2312 /// Use [`MINIDUMP_MAC_CRASH_INFO::record_start_size`] to access them.
2313 pub struct MINIDUMP_MAC_CRASH_INFO_RECORD {
2314 pub stream_type: u64,
2315 // Version of this format, currently at 5.
2316 //
2317 // Although theoretically this field being here means we can support multiple
2318 // versions of this struct in one [`MINIDUMP_MAC_CRASH_INFO`] stream, our reliance on
2319 // [`MINIDUMP_MAC_CRASH_INFO::record_start_size`] means we can't actually handle
2320 // such a heterogeneous situation. So all records should have the same version value.
2321 pub version: u64,
2322 }
2323 // Includes fields from MINIDUMP_MAC_CRASH_INFO_RECORD
2324 /// Contents of MacOS's `<CrashReporterClient.h>`'s `crashreporter_annotations_t`,
2325 /// but with the by-reference C-strings hoisted out to the end of the struct
2326 /// and inlined (so this is a variable-length struct).
2327 ///
2328 /// The variable-length strings are listed in [`MINIDUMP_MAC_CRASH_INFO_RECORD_STRINGS_4`].
2329 /// Use [`MINIDUMP_MAC_CRASH_INFO::record_start_size`] to access them.
2330 pub struct MINIDUMP_MAC_CRASH_INFO_RECORD_4 {
2331 pub thread: u64,
2332 pub dialog_mode: u64,
2333 }
2334 // Includes fields from MINIDUMP_MAC_CRASH_INFO_RECORD and MINIDUMP_MAC_CRASH_INFO_RECORD_4
2335 /// Contents of MacOS's `<CrashReporterClient.h>`'s `crashreporter_annotations_t`,
2336 /// but with the by-reference C-strings hoisted out to the end of the struct
2337 /// and inlined (so this is a variable-length struct).
2338 ///
2339 /// The variable-length strings are listed in [`MINIDUMP_MAC_CRASH_INFO_RECORD_STRINGS_5`].
2340 /// Use [`MINIDUMP_MAC_CRASH_INFO::record_start_size`] to access them.
2341 pub struct MINIDUMP_MAC_CRASH_INFO_RECORD_5 {
2342 pub abort_cause: u64,
2343 }
2344}
2345
2346macro_rules! replace_expr {
2347 ($_t:tt $sub:expr) => {
2348 $sub
2349 };
2350}
2351
2352macro_rules! count_tts {
2353 ($($tts:tt)*) => {0usize $(+ replace_expr!($tts 1usize))*};
2354}
2355
2356// Like multi_structs but specialized for a struct of strings that can be set by index.
2357macro_rules! multi_strings {
2358 // With no trailing struct left, terminate.
2359 (@next { $($prev:tt)* }) => {};
2360 // Declare the next struct, including fields from previous structs.
2361 (@next { $($prev:tt)* } $(#[$attr:meta])* pub struct $name:ident { $($cur:tt)* } $($tail:tt)* ) => {
2362 // Prepend fields from previous structs to this struct.
2363 multi_strings!($(#[$attr])* pub struct $name { $($prev)* $($cur)* } $($tail)*);
2364 };
2365 // Declare a single struct.
2366 ($(#[$attr:meta])* pub struct $name:ident { $( pub $field:ident: $t:tt, )* } $($tail:tt)* ) => {
2367 $(#[$attr])*
2368 #[derive(Default, Debug, Clone)]
2369 pub struct $name {
2370 $( pub $field: $t, )*
2371 }
2372
2373 impl $name {
2374 pub fn num_strings() -> usize {
2375 count_tts!($($t)*)
2376 }
2377
2378 #[allow(unused_variables, unused_mut)]
2379 pub fn set_string(&mut self, idx: usize, string: String) {
2380 let mut cur_idx = 0;
2381 $(if cur_idx == idx {
2382 self.$field = string;
2383 return;
2384 }
2385 cur_idx += 1;
2386 )*
2387 panic!("string index out of bounds {} >= {}", idx, cur_idx);
2388 }
2389 }
2390
2391 // Persist its fields down to the following structs.
2392 multi_strings!(@next { $( pub $field: $t, )* } $($tail)*);
2393 };
2394}
2395
2396multi_strings! {
2397 /// Variable-length data for [`MINIDUMP_MAC_CRASH_INFO_RECORD`].
2398 pub struct MINIDUMP_MAC_CRASH_INFO_RECORD_STRINGS {
2399 // No strings in the base version
2400 }
2401
2402 // Includes fields from [`MINIDUMP_MAC_CRASH_INFO_RECORD_STRINGS`]
2403 /// Variable-length data for [`MINIDUMP_MAC_CRASH_INFO_RECORD_4`].
2404 pub struct MINIDUMP_MAC_CRASH_INFO_RECORD_STRINGS_4 {
2405 pub module_path: String,
2406 pub message: String,
2407 pub signature_string: String,
2408 pub backtrace: String,
2409 pub message2: String,
2410 }
2411
2412 // Includes fields from [`MINIDUMP_MAC_CRASH_INFO_RECORD_STRINGS_4`]
2413 /// Variable-length data for [`MINIDUMP_MAC_CRASH_INFO_RECORD_5`].
2414 pub struct MINIDUMP_MAC_CRASH_INFO_RECORD_STRINGS_5 {
2415 // No new strings
2416 }
2417}
2418
2419/// The maximum supported size of a C-string in [`MINIDUMP_MAC_CRASH_INFO_RECORD`].
2420///
2421/// Assume the stream is corrupted if a string is longer than this.
2422pub const MAC_CRASH_INFO_STRING_MAX_SIZE: usize = 8192;
2423
2424/// The maximum supported count of [`MINIDUMP_MAC_CRASH_INFO_RECORD`]s.
2425///
2426/// In principle there should only be one or two non-empty __DATA,__crash_info
2427/// sections per process. But the __crash_info section is almost entirely
2428/// undocumented, so just in case we set a large maximum.
2429pub const MAC_CRASH_INFOS_MAX: usize = 20;
2430
2431/// MacOS kernel boot args
2432#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
2433pub struct MINIDUMP_MAC_BOOTARGS {
2434 pub stream_type: u32,
2435 pub bootargs: RVA64,
2436}
2437
2438bitflags! {
2439 /// Possible values of [`ARMCpuInfo::elf_hwcaps`]
2440 ///
2441 /// This matches the Linux kernel definitions from [<asm/hwcaps.h>][hwcap].
2442 ///
2443 /// [hwcap]: https://elixir.bootlin.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h
2444 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
2445 pub struct ArmElfHwCaps: u32 {
2446 const HWCAP_SWP = (1 << 0);
2447 const HWCAP_HALF = (1 << 1);
2448 const HWCAP_THUMB = (1 << 2);
2449 const HWCAP_26BIT = (1 << 3);
2450 const HWCAP_FAST_MULT = (1 << 4);
2451 const HWCAP_FPA = (1 << 5);
2452 const HWCAP_VFP = (1 << 6);
2453 const HWCAP_EDSP = (1 << 7);
2454 const HWCAP_JAVA = (1 << 8);
2455 const HWCAP_IWMMXT = (1 << 9);
2456 const HWCAP_CRUNCH = (1 << 10);
2457 const HWCAP_THUMBEE = (1 << 11);
2458 const HWCAP_NEON = (1 << 12);
2459 const HWCAP_VFPv3 = (1 << 13);
2460 const HWCAP_VFPv3D16 = (1 << 14);
2461 const HWCAP_TLS = (1 << 15);
2462 const HWCAP_VFPv4 = (1 << 16);
2463 const HWCAP_IDIVA = (1 << 17);
2464 const HWCAP_IDIVT = (1 << 18);
2465 const HWCAP_VFPD32 = (1 << 19);
2466 const HWCAP_IDIV = ArmElfHwCaps::HWCAP_IDIVA.bits() | Self::HWCAP_IDIVT.bits();
2467 const HWCAP_LPAE = (1 << 20);
2468 const HWCAP_EVTSTRM = (1 << 21);
2469 }
2470}
2471
2472#[repr(u32)]
2473#[derive(Copy, Clone, PartialEq, Eq, Debug, FromPrimitive)]
2474pub enum MINIDUMP_HANDLE_OBJECT_INFORMATION_TYPE {
2475 MiniHandleObjectInformationNone,
2476 MiniThreadInformation1,
2477 MiniMutantInformation1,
2478 MiniMutantInformation2,
2479 MiniProcessInformation1,
2480 MiniProcessInformation2,
2481 MiniEventInformation1,
2482 MiniSectionInformation1,
2483 MiniSemaphoreInformation1,
2484 MiniHandleObjectInformationTypeMax,
2485}
2486
2487/// OS-specific handle object information. Microsoft headers state that it can
2488/// change based on the target platform. The object is larger than this structure
2489/// (as specified by `size_of_info`) and the remaining data is stored after the
2490/// `size_of_info` field. The format of this information is not specified.
2491#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
2492pub struct MINIDUMP_HANDLE_OBJECT_INFORMATION {
2493 /// RVA pointing to the next handle object information. Elements of this type
2494 /// are chained and the last one has this field set to 0.
2495 pub next_info_rva: RVA,
2496 /// Type of this handle object information element, see [`MINIDUMP_HANDLE_OBJECT_INFORMATION_TYPE`]
2497 pub info_type: u32,
2498 /// Size of this element, this must be larger than `size_of::<MINIDUMP_HANDLE_OBJECT_INFORMATION>()`
2499 pub size_of_info: u32,
2500}
2501
2502#[derive(Debug, Default, Clone, Pread, Pwrite, SizeWith)]
2503pub struct MINIDUMP_HANDLE_DESCRIPTOR {
2504 /// The operating system handle value. A HANDLE on Windows and file descriptor number on Linux.
2505 pub handle: u64,
2506 /// An RVA to a `MINIDUMP_STRING` structure that specifies the object type of the handle.
2507 /// This member can be zero.
2508 pub type_name_rva: RVA,
2509 /// An RVA to a `MINIDUMP_STRING` structure that specifies the object name of the handle.
2510 /// This member can be zero.
2511 pub object_name_rva: RVA,
2512 /// The meaning of this member depends on the handle type and the operating system.
2513 pub attributes: u32,
2514 /// The meaning of this member depends on the handle type and the operating system.
2515 pub granted_access: u32,
2516 /// The meaning of this member depends on the handle type and the operating system.
2517 pub handle_count: u32,
2518 /// The meaning of this member depends on the handle type and the operating system.
2519 pub pointer_count: u32,
2520}
2521
2522#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
2523pub struct MINIDUMP_HANDLE_DESCRIPTOR_2 {
2524 /// The operating system handle value. A HANDLE on Windows and file descriptor number on Linux.
2525 pub handle: u64,
2526 /// An RVA to a `MINIDUMP_STRING` structure that specifies the object type of the handle.
2527 /// This member can be zero.
2528 pub type_name_rva: RVA,
2529 /// An RVA to a `MINIDUMP_STRING` structure that specifies the object name of the handle.
2530 /// This member can be zero.
2531 pub object_name_rva: RVA,
2532 /// The meaning of this member depends on the handle type and the operating system.
2533 pub attributes: u32,
2534 /// The meaning of this member depends on the handle type and the operating system.
2535 pub granted_access: u32,
2536 /// The meaning of this member depends on the handle type and the operating system.
2537 pub handle_count: u32,
2538 /// The meaning of this member depends on the handle type and the operating system.
2539 pub pointer_count: u32,
2540 /// An RVA to a [`MINIDUMP_HANDLE_OBJECT_INFORMATION`] structure that specifies object-specific information.
2541 /// This member can be 0 if there is no extra information.
2542 pub object_info_rva: RVA,
2543 /// Reserved for future use; must be zero.
2544 reserved0: u32,
2545}
2546
2547#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
2548pub struct MINIDUMP_HANDLE_DATA_STREAM {
2549 /// The size of this header, in bytes.
2550 pub size_of_header: u32,
2551 /// The size of each descriptor in the stream, in bytes.
2552 pub size_of_descriptor: u32,
2553 /// The number of descriptors in the stream.
2554 pub number_of_descriptors: u32,
2555 /// Reserved for future use; must be zero.
2556 pub reserved: u32,
2557}
2558
2559#[derive(Debug, Clone, Pread, Pwrite, SizeWith)]
2560pub struct MINIDUMP_THREAD_INFO {
2561 /// Thread identifier
2562 pub thread_id: u32,
2563 /// Thread state flags
2564 pub dump_flags: u32,
2565 /// HRESULT value of dump status
2566 pub dump_error: u32,
2567 /// The thread's exit code
2568 pub exit_status: u32,
2569 /// UTC time the thread was created
2570 pub create_time: u64,
2571 /// UTC time the thread exited
2572 pub exit_time: u64,
2573 /// Time executed in kernel mode
2574 pub kernel_time: u64,
2575 /// Time executed in user mode
2576 pub user_time: u64,
2577 /// Start address of the thread
2578 pub start_address: u64,
2579 /// Processor affinity mask
2580 pub affinity: u64,
2581}