kdmp_parser/
structs.rs

1// Axel '0vercl0k' Souchet - February 25 2024
2//! This has all the raw structures that makes up Windows kernel crash-dumps.
3use std::collections::BTreeMap;
4use std::fmt::Debug;
5
6use crate::error::{Error, Result};
7use crate::gxa::Gpa;
8
9/// We use this `Pod` trait to implement / constraint the `*read_struct`
10/// functions. For the functions to work as expected and be safe, here is the
11/// rule that a type `T` needs to follow to be `Pod`:
12///   - `T` should not contain a field / type that have invalid bit patterns (no
13///     `char`, no `bool`, no pointers). We will read bytes from a file and
14///     basically `transmute` those bytes to `T` so all possible bit patterns
15///     should be 'fine'.
16///
17/// # Safety
18///
19/// Implementing this trait for a type `T` requires that `T` is safe to
20/// initialize from any arbitrary bit pattern. This means:
21/// - `T` must not contain types with invalid bit patterns (e.g., `bool`,
22///   `char`, references, pointers)
23/// - All possible byte patterns must represent valid values of `T`
24/// - This is required because bytes are read from a file and transmuted to `T`
25pub unsafe trait Pod {}
26
27unsafe impl Pod for u64 {}
28unsafe impl Pod for u32 {}
29unsafe impl Pod for u16 {}
30
31/// The different kind of physical pages.
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub enum PageKind {
34    /// A normal 4kb page.
35    Normal,
36    /// A large 2mb page.
37    Large,
38    /// A huge 1gb page.
39    Huge,
40}
41
42impl PageKind {
43    /// Size in bytes of the page.
44    #[must_use]
45    pub fn size(&self) -> u64 {
46        match self {
47            Self::Normal => 4 * 1_024,
48            Self::Large => 2 * 1_024 * 1_024,
49            Self::Huge => 1_024 * 1_024 * 1_024,
50        }
51    }
52
53    /// Extract the page offset of `addr`.
54    #[must_use]
55    pub fn page_offset(&self, addr: u64) -> u64 {
56        let mask = self.size() - 1;
57
58        addr & mask
59    }
60}
61
62/// Types of kernel crash dump.
63#[derive(Debug, Clone, Copy, PartialEq)]
64#[repr(u32)]
65pub enum DumpType {
66    // Old dump types from `dbgeng.dll`.
67    Full = 0x1,
68    Bmp = 0x5,
69    /// Produced by `.dump /m`.
70    // Mini = 0x4,
71    /// (22H2+) Produced by `TaskMgr > System > Create live kernel Memory Dump`.
72    LiveKernelMemory = 0x6,
73    /// Produced by `.dump /k`.
74    KernelMemory = 0x8,
75    /// Produced by `.dump /ka`.
76    KernelAndUserMemory = 0x9,
77    /// Produced by `.dump /f`.
78    CompleteMemory = 0xa,
79}
80
81/// The physical memory map maps a physical address to a file offset.
82pub type PhysmemMap = BTreeMap<Gpa, u64>;
83
84impl TryFrom<u32> for DumpType {
85    type Error = Error;
86
87    fn try_from(value: u32) -> Result<Self> {
88        match value {
89            x if x == DumpType::Full as u32 => Ok(DumpType::Full),
90            x if x == DumpType::Bmp as u32 => Ok(DumpType::Bmp),
91            x if x == DumpType::KernelMemory as u32 => Ok(DumpType::KernelMemory),
92            x if x == DumpType::KernelAndUserMemory as u32 => Ok(DumpType::KernelAndUserMemory),
93            x if x == DumpType::CompleteMemory as u32 => Ok(DumpType::CompleteMemory),
94            x if x == DumpType::LiveKernelMemory as u32 => Ok(DumpType::LiveKernelMemory),
95            _ => Err(Error::UnknownDumpType(value)),
96        }
97    }
98}
99
100#[repr(C)]
101#[derive(Debug, Default)]
102pub struct ExceptionRecord64 {
103    pub exception_code: u32,
104    pub exception_flags: u32,
105    pub exception_record: u64,
106    pub exception_address: u64,
107    pub number_parameters: u32,
108    unused_alignment1: u32,
109    pub exception_information: [u64; 15],
110}
111
112pub const DUMP_HEADER64_EXPECTED_SIGNATURE: u32 = 0x45_47_41_50; // 'EGAP'
113pub const DUMP_HEADER64_EXPECTED_VALID_DUMP: u32 = 0x34_36_55_44; // '46UD'
114
115/// Adjusted C struct for `DUMP_HEADERS64` from MS Rust docs. Padding
116/// adjustment added from reversing `nt!IoFillDumpHeader`.
117// https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/System/Diagnostics/Debug/struct.DUMP_HEADER64.html#structfield.DumpType
118#[repr(C)]
119pub struct Header64 {
120    pub signature: u32,
121    pub valid_dump: u32,
122    pub major_version: u32,
123    pub minor_version: u32,
124    pub directory_table_base: u64,
125    pub pfn_database: u64,
126    pub ps_loaded_module_list: u64,
127    pub ps_active_process_head: u64,
128    pub machine_image_type: u32,
129    pub number_processors: u32,
130    pub bug_check_code: u32,
131    padding1: u32,
132    pub bug_check_code_parameters: [u64; 4],
133    pub version_user: [u8; 32],
134    pub kd_debugger_data_block: u64,
135    pub physical_memory_block_buffer: [u8; 700],
136    padding2: u32,
137    pub context_record_buffer: [u8; 3_000],
138    pub exception: ExceptionRecord64,
139    pub dump_type: u32,
140    padding3: u32,
141    pub required_dump_space: i64,
142    pub system_time: i64,
143    pub comment: [u8; 128],
144    pub system_up_time: i64,
145    pub minidump_fields: u32,
146    pub secondary_data_state: u32,
147    pub product_type: u32,
148    pub suite_mask: u32,
149    pub writer_status: u32,
150    unused1: u8,
151    pub kd_secondary_version: u8,
152    unused2: [u8; 2],
153    pub attributes: u32,
154    pub boot_id: u32,
155    reserved1: [u8; 4008],
156}
157
158unsafe impl Pod for Header64 {}
159
160impl Debug for Header64 {
161    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162        f.debug_struct("Header64")
163            .field("signature", &self.signature)
164            .field("valid_dump", &self.valid_dump)
165            .field("major_version", &self.major_version)
166            .field("minor_version", &self.minor_version)
167            .field("directory_table_base", &self.directory_table_base)
168            .field("pfn_database", &self.pfn_database)
169            .field("ps_loaded_module_list", &self.ps_loaded_module_list)
170            .field("ps_active_process_head", &self.ps_active_process_head)
171            .field("machine_image_type", &self.machine_image_type)
172            .field("number_processors", &self.number_processors)
173            .field("bug_check_code", &self.bug_check_code)
174            .field("bug_check_code_parameters", &self.bug_check_code_parameters)
175            .field("version_user", &self.version_user)
176            .field("kd_debugger_data_block", &self.kd_debugger_data_block)
177            .field("exception", &self.exception)
178            .field("dump_type", &self.dump_type)
179            .field("required_dump_space", &self.required_dump_space)
180            .field("system_time", &self.system_time)
181            .field("comment", &self.comment)
182            .field("system_up_time", &self.system_up_time)
183            .field("minidump_fields", &self.minidump_fields)
184            .field("secondary_data_state", &self.secondary_data_state)
185            .field("product_type", &self.product_type)
186            .field("suite_mask", &self.suite_mask)
187            .field("writer_status", &self.writer_status)
188            .field("kd_secondary_version", &self.kd_secondary_version)
189            .field("attributes", &self.attributes)
190            .field("boot_id", &self.boot_id)
191            .finish_non_exhaustive()
192    }
193}
194
195const BMPHEADER64_EXPECTED_SIGNATURE: u32 = 0x50_4D_44_53; // 'PMDS'
196const BMPHEADER64_EXPECTED_SIGNATURE2: u32 = 0x50_4D_44_46; // 'PMDF'
197const BMPHEADER64_EXPECTED_VALID_DUMP: u32 = 0x50_4D_55_44; // 'PMUD'
198
199#[derive(Debug, Default)]
200#[repr(C)]
201pub struct BmpHeader64 {
202    pub signature: u32,
203    pub valid_dump: u32,
204    // According to rekall there's a gap there:
205    // 'ValidDump': [0x4, ['String', dict(
206    //    length=4,
207    //    term=None,
208    //    )]],
209    // # The offset of the first page in the file.
210    // 'FirstPage': [0x20, ['unsigned long long']],
211    padding1: [u8; 0x20 - (0x4 + size_of::<u32>())],
212    /// The offset of the first page in the file.
213    pub first_page: u64,
214    /// Total number of pages present in the bitmap.
215    pub total_present_pages: u64,
216    /// Total number of pages in image. This dictates the total size of the
217    /// bitmap. This is not the same as the `TotalPresentPages` which is only
218    /// the sum of the bits set to 1.
219    pub pages: u64,
220    // Bitmap follows
221}
222
223unsafe impl Pod for BmpHeader64 {}
224
225impl BmpHeader64 {
226    #[must_use]
227    pub fn looks_good(&self) -> bool {
228        (self.signature == BMPHEADER64_EXPECTED_SIGNATURE
229            || self.signature == BMPHEADER64_EXPECTED_SIGNATURE2)
230            && self.valid_dump == BMPHEADER64_EXPECTED_VALID_DUMP
231    }
232}
233
234#[derive(Debug, Default)]
235#[repr(C)]
236pub struct PhysmemRun {
237    pub base_page: u64,
238    pub page_count: u64,
239}
240
241unsafe impl Pod for PhysmemRun {}
242
243impl PhysmemRun {
244    /// Calculate a physical address from a run and an index.
245    ///
246    /// The formulae is: (`base_page` + `page_idx`) * `PageKind::Normal.size()`.
247    pub fn phys_addr(&self, page_idx: u64) -> Option<Gpa> {
248        debug_assert!(page_idx < self.page_count);
249
250        self.base_page
251            .checked_add(page_idx)?
252            .checked_mul(PageKind::Normal.size())
253            .map(Gpa::new)
254    }
255}
256
257#[derive(Debug, Default)]
258#[repr(C)]
259pub struct PhysmemDesc {
260    pub number_of_runs: u32,
261    padding1: u32,
262    pub number_of_pages: u64,
263    // PHYSMEM_RUN Run[1]; follows
264}
265
266unsafe impl Pod for PhysmemDesc {}
267
268impl TryFrom<&[u8]> for PhysmemDesc {
269    type Error = Error;
270
271    fn try_from(slice: &[u8]) -> Result<Self> {
272        let expected_len = size_of::<Self>();
273        if slice.len() < expected_len {
274            return Err(Error::InvalidData("physmem desc is too small"));
275        }
276
277        let number_of_runs = u32::from_le_bytes((&slice[0..4]).try_into().unwrap());
278        let number_of_pages = u64::from_le_bytes((&slice[4..12]).try_into().unwrap());
279
280        Ok(Self {
281            number_of_runs,
282            number_of_pages,
283            ..Default::default()
284        })
285    }
286}
287
288#[derive(PartialEq)]
289#[repr(C)]
290pub struct Context {
291    pub p1_home: u64,
292    pub p2_home: u64,
293    pub p3_home: u64,
294    pub p4_home: u64,
295    pub p5_home: u64,
296    pub p6_home: u64,
297    pub context_flags: u32,
298    pub mxcsr: u32,
299    pub seg_cs: u16,
300    pub seg_ds: u16,
301    pub seg_es: u16,
302    pub seg_fs: u16,
303    pub seg_gs: u16,
304    pub seg_ss: u16,
305    pub eflags: u32,
306    pub dr0: u64,
307    pub dr1: u64,
308    pub dr2: u64,
309    pub dr3: u64,
310    pub dr6: u64,
311    pub dr7: u64,
312    pub rax: u64,
313    pub rcx: u64,
314    pub rdx: u64,
315    pub rbx: u64,
316    pub rsp: u64,
317    pub rbp: u64,
318    pub rsi: u64,
319    pub rdi: u64,
320    pub r8: u64,
321    pub r9: u64,
322    pub r10: u64,
323    pub r11: u64,
324    pub r12: u64,
325    pub r13: u64,
326    pub r14: u64,
327    pub r15: u64,
328    pub rip: u64,
329    pub control_word: u16,
330    pub status_word: u16,
331    pub tag_word: u8,
332    reserved1: u8,
333    pub error_opcode: u16,
334    pub error_offset: u32,
335    pub error_selector: u16,
336    reserved2: u16,
337    pub data_offset: u32,
338    pub data_selector: u16,
339    reserved3: u16,
340    pub mxcsr2: u32,
341    pub mxcsr_mask: u32,
342    pub float_registers: [u128; 8],
343    pub xmm_registers: [u128; 16],
344    reserved4: [u8; 96],
345    pub vector_register: [u128; 26],
346    pub vector_control: u64,
347    pub debug_control: u64,
348    pub last_branch_to_rip: u64,
349    pub last_branch_from_rip: u64,
350    pub last_exception_to_rip: u64,
351    pub last_exception_from_rip: u64,
352}
353
354unsafe impl Pod for Context {}
355
356impl Debug for Context {
357    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
358        f.debug_struct("Context")
359            .field("p1_home", &self.p1_home)
360            .field("p2_home", &self.p2_home)
361            .field("p3_home", &self.p3_home)
362            .field("p4_home", &self.p4_home)
363            .field("p5_home", &self.p5_home)
364            .field("p6_home", &self.p6_home)
365            .field("context_flags", &self.context_flags)
366            .field("mxcsr", &self.mxcsr)
367            .field("seg_cs", &self.seg_cs)
368            .field("seg_ds", &self.seg_ds)
369            .field("seg_es", &self.seg_es)
370            .field("seg_fs", &self.seg_fs)
371            .field("seg_gs", &self.seg_gs)
372            .field("seg_ss", &self.seg_ss)
373            .field("eflags", &self.eflags)
374            .field("dr0", &self.dr0)
375            .field("dr1", &self.dr1)
376            .field("dr2", &self.dr2)
377            .field("dr3", &self.dr3)
378            .field("dr6", &self.dr6)
379            .field("dr7", &self.dr7)
380            .field("rax", &self.rax)
381            .field("rcx", &self.rcx)
382            .field("rdx", &self.rdx)
383            .field("rbx", &self.rbx)
384            .field("rsp", &self.rsp)
385            .field("rbp", &self.rbp)
386            .field("rsi", &self.rsi)
387            .field("rdi", &self.rdi)
388            .field("r8", &self.r8)
389            .field("r9", &self.r9)
390            .field("r10", &self.r10)
391            .field("r11", &self.r11)
392            .field("r12", &self.r12)
393            .field("r13", &self.r13)
394            .field("r14", &self.r14)
395            .field("r15", &self.r15)
396            .field("rip", &self.rip)
397            .field("control_word", &self.control_word)
398            .field("status_word", &self.status_word)
399            .field("tag_word", &self.tag_word)
400            .field("error_opcode", &self.error_opcode)
401            .field("error_offset", &self.error_offset)
402            .field("error_selector", &self.error_selector)
403            .field("data_offset", &self.data_offset)
404            .field("data_selector", &self.data_selector)
405            .field("mxcsr2", &self.mxcsr2)
406            .field("mxcsr_mask", &self.mxcsr_mask)
407            .field("float_registers", &self.float_registers)
408            .field("xmm_registers", &self.xmm_registers)
409            .field("vector_register", &self.vector_register)
410            .field("vector_control", &self.vector_control)
411            .field("debug_control", &self.debug_control)
412            .field("last_branch_to_rip", &self.last_branch_to_rip)
413            .field("last_branch_from_rip", &self.last_branch_from_rip)
414            .field("last_exception_to_rip", &self.last_exception_to_rip)
415            .field("last_exception_from_rip", &self.last_exception_from_rip)
416            .finish_non_exhaustive()
417    }
418}
419
420const RDMP_HEADER64_EXPECTED_MARKER: u32 = 0x40;
421const RDMP_HEADER64_EXPECTED_SIGNATURE: u32 = 0x50_4D_44_52; // 'PMDR'
422const RDMP_HEADER64_EXPECTED_VALID_DUMP: u32 = 0x50_4D_55_44; // 'PMUD'
423
424#[repr(C)]
425#[derive(Debug, Default)]
426pub struct RdmpHeader64 {
427    pub marker: u32,
428    pub signature: u32,
429    pub valid_dump: u32,
430    reserved1: u32,
431    pub metadata_size: u64,
432    pub first_page_offset: u64,
433    // Bitmap follows
434}
435
436impl RdmpHeader64 {
437    #[must_use]
438    pub fn looks_good(&self) -> bool {
439        if self.marker != RDMP_HEADER64_EXPECTED_MARKER {
440            return false;
441        }
442
443        if self.signature != RDMP_HEADER64_EXPECTED_SIGNATURE {
444            return false;
445        }
446
447        if self.valid_dump != RDMP_HEADER64_EXPECTED_VALID_DUMP {
448            return false;
449        }
450
451        if self.metadata_size - 0x20 != self.first_page_offset - 0x20_40 {
452            return false;
453        }
454
455        true
456    }
457}
458
459#[repr(C)]
460#[derive(Debug, Default)]
461pub struct KernelRdmpHeader64 {
462    pub hdr: RdmpHeader64,
463    unknown1: u64,
464    unknown2: u64,
465    // Bitmap follows
466}
467
468unsafe impl Pod for KernelRdmpHeader64 {}
469
470#[repr(C)]
471#[derive(Debug, Default)]
472pub struct FullRdmpHeader64 {
473    pub hdr: RdmpHeader64,
474    pub number_of_ranges: u32,
475    reserved1: u16,
476    reserved2: u16,
477    pub total_number_of_pages: u64,
478    // Bitmap follows
479}
480
481unsafe impl Pod for FullRdmpHeader64 {}
482
483#[repr(C)]
484#[derive(Debug, Default)]
485pub struct PfnRange {
486    pub page_file_number: u64,
487    pub number_of_pages: u64,
488}
489
490unsafe impl Pod for PfnRange {}
491
492#[repr(C)]
493#[derive(Debug, Default)]
494pub struct ListEntry<P: Pod> {
495    pub flink: P,
496    pub blink: P,
497}
498
499unsafe impl<P: Pod> Pod for ListEntry<P> {}
500
501#[repr(C)]
502#[derive(Debug, Default)]
503pub struct UnicodeString<P: Pod> {
504    pub length: u16,
505    pub maximum_length: u16,
506    pub buffer: P,
507}
508
509unsafe impl<P: Pod> Pod for UnicodeString<P> {}
510
511#[derive(Debug, Default)]
512#[repr(C)]
513pub struct LdrDataTableEntry<P: Pod> {
514    pub in_load_order_links: ListEntry<P>,
515    pub in_memory_order_links: ListEntry<P>,
516    pub in_initialization_order_links: ListEntry<P>,
517    pub dll_base: P,
518    pub entry_point: P,
519    pub size_of_image: u32,
520    pub full_dll_name: UnicodeString<P>,
521    pub base_dll_name: UnicodeString<P>,
522}
523
524unsafe impl<P: Pod> Pod for LdrDataTableEntry<P> {}
525
526// Copied from `WDBGEXTS.H`.
527#[repr(C)]
528#[derive(Debug, Default)]
529pub struct DbgKdDebugDataHeader64 {
530    /// Link to other blocks
531    pub list: ListEntry<u64>,
532    /// This is a unique tag to identify the owner of the block.
533    /// If your component only uses one pool tag, use it for this, too.
534    pub owner_tag: u32,
535    /// This must be initialized to the size of the data block,
536    /// including this structure.
537    pub size: u32,
538}
539
540unsafe impl Pod for DbgKdDebugDataHeader64 {}
541
542// https://github.com/tpn/winsdk-10/blob/9b69fd26ac0c7d0b83d378dba01080e93349c2ed/Include/10.0.14393.0/um/WDBGEXTS.H#L1206C16-L1206C34
543#[repr(C)]
544#[derive(Debug, Default)]
545pub struct KdDebuggerData64 {
546    pub header: DbgKdDebugDataHeader64,
547    /// Base address of kernel image
548    pub kern_base: u64,
549    /// `DbgBreakPointWithStatus` is a function which takes an argument
550    /// and hits a breakpoint. This field contains the address of the
551    /// breakpoint instruction. When the debugger sees a breakpoint
552    /// at this address, it may retrieve the argument from the first
553    /// argument register, or on x86 the eax register.
554    pub breakpoint_with_status: u64,
555    /// Address of the saved context record during a bugcheck
556    /// N.B. This is an automatic in `KeBugcheckEx`'s frame, and
557    /// is only valid after a bugcheck.
558    pub saved_context: u64,
559    /// The address of the thread structure is provided in the
560    /// `WAIT_STATE_CHANGE` packet.  This is the offset from the base of
561    /// the thread structure to the pointer to the kernel stack frame
562    /// for the currently active usermode callback.
563    pub th_callback_stack: u16,
564    //// saved pointer to next callback frame
565    pub next_callback: u16,
566    /// saved frame pointer
567    pub frame_pointer: u16,
568    /// pad to a quad boundary
569    pub pae_enabled: u16,
570    /// Address of the kernel callout routine.
571    pub ki_call_user_mode: u64,
572    /// Address of the usermode entry point for callbacks (in ntdll).
573    pub ke_user_callback_dispatcher: u64,
574    pub ps_loaded_module_list: u64,
575    pub ps_active_process_head: u64,
576    pub psp_cid_table: u64,
577    pub exp_system_resources_list: u64,
578    pub exp_paged_pool_descriptor: u64,
579    pub exp_number_of_paged_pools: u64,
580    pub ke_time_increment: u64,
581    pub ke_bug_check_callback_list_head: u64,
582    pub ki_bugcheck_data: u64,
583    pub iop_error_log_list_head: u64,
584    pub obp_root_directory_object: u64,
585    pub obp_type_object_type: u64,
586    pub mm_system_cache_start: u64,
587    pub mm_system_cache_end: u64,
588    pub mm_system_cache_ws: u64,
589    pub mm_pfn_database: u64,
590    pub mm_system_ptes_start: u64,
591    pub mm_system_ptes_end: u64,
592    pub mm_subsection_base: u64,
593    pub mm_number_of_paging_files: u64,
594    pub mm_lowest_physical_page: u64,
595    pub mm_highest_physical_page: u64,
596    pub mm_number_of_physical_pages: u64,
597    pub mm_maximum_non_paged_pool_in_bytes: u64,
598    pub mm_non_paged_system_start: u64,
599    pub mm_non_paged_pool_start: u64,
600    pub mm_non_paged_pool_end: u64,
601    pub mm_paged_pool_start: u64,
602    pub mm_paged_pool_end: u64,
603    pub mm_paged_pool_information: u64,
604    pub mm_page_size: u64,
605    pub mm_size_of_paged_pool_in_bytes: u64,
606    pub mm_total_commit_limit: u64,
607    pub mm_total_committed_pages: u64,
608    pub mm_shared_commit: u64,
609    pub mm_driver_commit: u64,
610    pub mm_process_commit: u64,
611    pub mm_paged_pool_commit: u64,
612    pub mm_extended_commit: u64,
613    pub mm_zeroed_page_list_head: u64,
614    pub mm_free_page_list_head: u64,
615    pub mm_standby_page_list_head: u64,
616    pub mm_modified_page_list_head: u64,
617    pub mm_modified_no_write_page_list_head: u64,
618    pub mm_available_pages: u64,
619    pub mm_resident_available_pages: u64,
620    pub pool_track_table: u64,
621    pub non_paged_pool_descriptor: u64,
622    pub mm_highest_user_address: u64,
623    pub mm_system_range_start: u64,
624    pub mm_user_probe_address: u64,
625    pub kd_print_circular_buffer: u64,
626    pub kd_print_circular_buffer_end: u64,
627    pub kd_print_write_pointer: u64,
628    pub kd_print_rollover_count: u64,
629    pub mm_loaded_user_image_list: u64,
630    // NT 5.1 Addition
631    pub nt_build_lab: u64,
632    pub ki_normal_system_call: u64,
633    // NT 5.0 hotfix addition
634    pub ki_processor_block: u64,
635    pub mm_unloaded_drivers: u64,
636    pub mm_last_unloaded_driver: u64,
637    pub mm_triage_action_taken: u64,
638    pub mm_special_pool_tag: u64,
639    pub kernel_verifier: u64,
640    pub mm_verifier_data: u64,
641    pub mm_allocated_non_paged_pool: u64,
642    pub mm_peak_commitment: u64,
643    pub mm_total_commit_limit_maximum: u64,
644    pub cm_nt_csd_version: u64,
645    // NT 5.1 Addition
646    pub mm_physical_memory_block: u64,
647    pub mm_session_base: u64,
648    pub mm_session_size: u64,
649    pub mm_system_parent_table_page: u64,
650    // Server 2003 addition
651    pub mm_virtual_translation_base: u64,
652    pub offset_kthread_next_processor: u16,
653    pub offset_kthread_teb: u16,
654    pub offset_kthread_kernel_stack: u16,
655    pub offset_kthread_initial_stack: u16,
656    pub offset_kthread_apc_process: u16,
657    pub offset_kthread_state: u16,
658    pub offset_kthread_b_store: u16,
659    pub offset_kthread_b_store_limit: u16,
660    pub size_eprocess: u16,
661    pub offset_eprocess_peb: u16,
662    pub offset_eprocess_parent_cid: u16,
663    pub offset_eprocess_directory_table_base: u16,
664    pub size_prcb: u16,
665    pub offset_prcb_dpc_routine: u16,
666    pub offset_prcb_current_thread: u16,
667    pub offset_prcb_mhz: u16,
668    pub offset_prcb_cpu_type: u16,
669    pub offset_prcb_vendor_string: u16,
670    pub offset_prcb_proc_state_context: u16,
671    pub offset_prcb_number: u16,
672    pub size_ethread: u16,
673    pub kd_print_circular_buffer_ptr: u64,
674    pub kd_print_buffer_size: u64,
675    pub ke_loader_block: u64,
676    pub size_pcr: u16,
677    pub offset_pcr_self_pcr: u16,
678    pub offset_pcr_current_prcb: u16,
679    pub offset_pcr_contained_prcb: u16,
680    pub offset_pcr_initial_b_store: u16,
681    pub offset_pcr_b_store_limit: u16,
682    pub offset_pcr_initial_stack: u16,
683    pub offset_pcr_stack_limit: u16,
684    pub offset_prcb_pcr_page: u16,
685    pub offset_prcb_proc_state_special_reg: u16,
686    pub gdt_r0_code: u16,
687    pub gdt_r0_data: u16,
688    pub gdt_r0_pcr: u16,
689    pub gdt_r3_code: u16,
690    pub gdt_r3_data: u16,
691    pub gdt_r3_teb: u16,
692    pub gdt_ldt: u16,
693    pub gdt_tss: u16,
694    pub gdt64_r3_cm_code: u16,
695    pub gdt64_r3_cm_teb: u16,
696    pub iop_num_triage_dump_data_blocks: u64,
697    pub iop_triage_dump_data_blocks: u64,
698    // Longhorn addition
699    pub vf_crash_data_block: u64,
700    pub mm_bad_pages_detected: u64,
701    pub mm_zeroed_page_single_bit_errors_detected: u64,
702    // Windows 7 addition
703    pub etwp_debugger_data: u64,
704    pub offset_prcb_context: u16,
705    // ...
706}
707
708unsafe impl Pod for KdDebuggerData64 {}
709
710const _: () = assert!(size_of::<PhysmemDesc>() == 0x10);
711const _: () = assert!(size_of::<PhysmemRun>() == 0x10);
712const _: () = assert!(size_of::<Header64>() == 0x2_000);
713const _: () = assert!(size_of::<Context>() == 0x4d0);