1use std::fmt;
4
5pub const STREAM_TYPE_UNUSED: u32 = 0;
6pub const STREAM_TYPE_THREAD_LIST: u32 = 3;
7pub const STREAM_TYPE_MODULE_LIST: u32 = 4;
8pub const STREAM_TYPE_EXCEPTION: u32 = 6;
9pub const STREAM_TYPE_SYSTEM_INFO: u32 = 7;
10pub const STREAM_TYPE_MEMORY64_LIST: u32 = 9;
11pub const STREAM_TYPE_MEMORY_INFO_LIST: u32 = 16;
12
13pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
14
15pub const EXPECTED_DUMP_SIGNATURE: u32 = 0x504d_444d;
16
17pub const VALID_DUMP_FLAGS: u32 = 0x001f_ffff;
18
19pub const WOW64_MAXIMUM_SUPPORTED_EXTENSION: usize = 512;
20
21pub const WOW64_SIZE_OF_80387_REGISTERS: usize = 80;
22
23pub const ARCH_X86: u16 = 0;
24pub const ARCH_X64: u16 = 9;
25
26#[derive(Debug, Default)]
27#[repr(C)]
28pub struct Header {
29 pub signature: u32,
30 pub version: u16,
31 pub implementation_version: u16,
32 pub number_of_streams: u32,
33 pub stream_directory_rva: u32,
34 pub checksum: u32,
35 pub reserved: u32,
36 pub timedatestamp: u32,
37 pub flags: u32,
38}
39
40#[derive(Debug, Default, Clone, Copy)]
41#[repr(C)]
42pub struct LocationDescriptor32 {
43 pub data_size: u32,
44 pub rva: u32,
45}
46
47#[derive(Debug, Default)]
48#[repr(C)]
49pub struct Directory {
50 pub stream_type: u32,
51 pub location: LocationDescriptor32,
52}
53
54#[derive(Debug, Default)]
55#[repr(C)]
56pub struct SystemInfoStream {
57 pub processor_arch: u16,
58 pub processor_level: u16,
59 pub processor_revision: u16,
60 pub number_of_processors: u8,
61 pub product_type: u8,
62 pub major_version: u32,
63 pub minor_version: u32,
64 pub build_number: u32,
65 pub platform_id: u32,
66 pub csd_version_rva: u32,
67 pub suite_mask: u16,
68 pub reserverd2: u16,
69}
70
71#[derive(Default, Debug)]
72#[repr(C)]
73pub struct ExceptionRecord {
74 pub exception_code: u32,
75 pub exception_flags: u32,
76 pub exception_record: u64,
77 pub exception_address: u64,
78 pub number_parameters: u32,
79 pub unused_alignment: u32,
80 pub exception_information: [u64; EXCEPTION_MAXIMUM_PARAMETERS],
81}
82
83#[derive(Default, Debug)]
84#[repr(C)]
85pub struct ExceptionStream {
86 pub thread_id: u32,
87 pub alignment: u32,
88 pub exception_record: ExceptionRecord,
89 pub thread_context: LocationDescriptor32,
90}
91
92#[derive(Default, Debug)]
93#[repr(C)]
94pub struct MemoryInfo {
95 pub base_address: u64,
96 pub allocation_base: u64,
97 pub allocation_protect: u32,
98 pub alignment1: u32,
99 pub region_size: u64,
100 pub state: u32,
101 pub protect: u32,
102 pub type_: u32,
103 pub alignment2: u32,
104}
105
106#[derive(Default, Debug)]
107#[repr(C)]
108pub struct MemoryInfoListStream {
109 pub size_of_header: u32,
110 pub size_of_entry: u32,
111 pub number_of_entries: u64,
112}
113
114#[derive(Default, Debug)]
115#[repr(C)]
116pub struct Memory64ListStream {
117 pub number_of_memory_ranges: u64,
118 pub base_rva: u64,
119}
120
121#[derive(Default, Debug)]
122#[repr(C)]
123pub struct MemoryDescriptor64 {
124 pub start_of_memory_range: u64,
125 pub data_size: u64,
126}
127
128#[derive(Default, Debug)]
129#[repr(C)]
130pub struct ThreadList {
131 pub number_of_threads: u32,
132}
133
134#[derive(Default, Debug)]
135#[repr(C)]
136pub struct MemoryDescriptor {
137 pub start_of_memory_range: u64,
138 pub memory: LocationDescriptor32,
139}
140
141#[derive(Default, Debug)]
142#[repr(C)]
143pub struct ThreadEntry {
144 pub thread_id: u32,
145 pub suspend_count: u32,
146 pub priority_class: u32,
147 pub priority: u32,
148 pub teb: u64,
149 pub stack: MemoryDescriptor,
150 pub thread_context: LocationDescriptor32,
151}
152
153#[derive(Default, Debug)]
154#[repr(C)]
155pub struct ModuleList {
156 pub number_of_modules: u32,
157}
158
159#[derive(Default, Debug, Clone, Copy)]
160#[repr(C)]
161pub struct FixedFileInfo {
162 pub signature: u32,
163 pub struc_version: u32,
164 pub file_version_ms: u32,
165 pub file_version_ls: u32,
166 pub product_version_ms: u32,
167 pub product_version_ls: u32,
168 pub file_flags_mask: u32,
169 pub file_flags: u32,
170 pub file_os: u32,
171 pub file_type: u32,
172 pub file_subtype: u32,
173 pub file_date_ms: u32,
174 pub file_date_ls: u32,
175}
176
177#[derive(Default, Debug)]
178#[repr(packed(1))]
179pub struct ModuleEntry {
180 pub base_of_image: u64,
181 pub size_of_image: u32,
182 pub checksum: u32,
183 pub time_date_stamp: u32,
184 pub module_name_rva: u32,
185 pub version_info: FixedFileInfo,
186 pub cv_record: LocationDescriptor32,
187 pub misc_record: LocationDescriptor32,
188 _reserved0: u64,
189 _reserved1: u64,
190}
191
192#[derive(Debug, PartialEq)]
193#[repr(C)]
194pub struct FloatingSaveArea32 {
195 pub control_word: u32,
196 pub status_word: u32,
197 pub tag_word: u32,
198 pub error_offset: u32,
199 pub error_selector: u32,
200 pub data_offset: u32,
201 pub data_selector: u32,
202 pub register_area: [u8; WOW64_SIZE_OF_80387_REGISTERS],
203 pub cr0_npx_state: u32,
204}
205
206impl Default for FloatingSaveArea32 {
207 fn default() -> Self {
208 unsafe { std::mem::zeroed() }
211 }
212}
213
214#[derive(Debug)]
216#[repr(C)]
217pub struct ThreadContextX86 {
218 pub context_flags: u32,
219 pub dr0: u32,
220 pub dr1: u32,
221 pub dr2: u32,
222 pub dr3: u32,
223 pub dr6: u32,
224 pub dr7: u32,
225 pub float_save: FloatingSaveArea32,
226 pub seg_gs: u32,
227 pub seg_fs: u32,
228 pub seg_es: u32,
229 pub seg_ds: u32,
230 pub edi: u32,
231 pub esi: u32,
232 pub ebx: u32,
233 pub edx: u32,
234 pub ecx: u32,
235 pub eax: u32,
236 pub ebp: u32,
237 pub eip: u32,
238 pub seg_cs: u32,
239 pub eflags: u32,
240 pub esp: u32,
241 pub seg_ss: u32,
242 pub extended_registers: [u8; WOW64_MAXIMUM_SUPPORTED_EXTENSION],
243}
244
245impl fmt::Display for ThreadContextX86 {
246 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247 writeln!(
248 f,
249 "eax={:08x} ebx={:08x} ecx={:08x} edx={:08x} esi={:08x} edi={:08x}",
250 self.eax, self.ebx, self.ecx, self.edx, self.esi, self.edi
251 )?;
252 writeln!(
253 f,
254 "eip={:08x} esp={:08x} ebp={:08x}",
255 self.eip, self.esp, self.ebp
256 )?;
257 write!(
258 f,
259 "cs={:04x} ss={:04x} ds={:04x} es={:04x} fs={:04x} gs={:04x} efl={:08x}",
260 self.seg_cs,
261 self.seg_ss,
262 self.seg_ds,
263 self.seg_es,
264 self.seg_fs,
265 self.seg_gs,
266 self.eflags
267 )
268 }
269}
270
271impl Default for ThreadContextX86 {
272 fn default() -> Self {
273 unsafe { std::mem::zeroed() }
276 }
277}
278
279#[derive(Debug)]
281#[repr(C)]
282pub struct ThreadContextX64 {
283 pub p1_home: u64,
284 pub p2_home: u64,
285 pub p3_home: u64,
286 pub p4_home: u64,
287 pub p5_home: u64,
288 pub p6_home: u64,
289 pub context_flags: u32,
290 pub mxcsr: u32,
291 pub seg_cs: u16,
292 pub seg_ds: u16,
293 pub seg_es: u16,
294 pub seg_fs: u16,
295 pub seg_gs: u16,
296 pub seg_ss: u16,
297 pub eflags: u32,
298 pub dr0: u64,
299 pub dr1: u64,
300 pub dr2: u64,
301 pub dr3: u64,
302 pub dr6: u64,
303 pub dr7: u64,
304 pub rax: u64,
305 pub rcx: u64,
306 pub rdx: u64,
307 pub rbx: u64,
308 pub rsp: u64,
309 pub rbp: u64,
310 pub rsi: u64,
311 pub rdi: u64,
312 pub r8: u64,
313 pub r9: u64,
314 pub r10: u64,
315 pub r11: u64,
316 pub r12: u64,
317 pub r13: u64,
318 pub r14: u64,
319 pub r15: u64,
320 pub rip: u64,
321 pub control_word: u16,
322 pub status_word: u16,
323 pub tag_word: u8,
324 pub reserved1: u8,
325 pub error_opcode: u16,
326 pub error_offset: u32,
327 pub error_selector: u16,
328 pub reserved2: u16,
329 pub data_offset: u32,
330 pub data_selector: u16,
331 pub reserved3: u16,
332 pub mxcsr2: u32,
333 pub mxcsr_mask: u32,
334 pub float_registers: [u128; 8],
335 pub xmm0: u128,
336 pub xmm1: u128,
337 pub xmm2: u128,
338 pub xmm3: u128,
339 pub xmm4: u128,
340 pub xmm5: u128,
341 pub xmm6: u128,
342 pub xmm7: u128,
343 pub xmm8: u128,
344 pub xmm9: u128,
345 pub xmm10: u128,
346 pub xmm11: u128,
347 pub xmm12: u128,
348 pub xmm13: u128,
349 pub xmm14: u128,
350 pub xmm15: u128,
351 pub padding: [u8; 0x60],
352 pub vector_registers: [u128; 26],
353 pub vector_control: u64,
354 pub debug_control: u64,
355 pub last_branch_to_rip: u64,
356 pub last_branch_from_rip: u64,
357 pub last_exception_to_rip: u64,
358 pub last_exception_from_rip: u64,
359}
360
361impl fmt::Display for ThreadContextX64 {
362 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
363 writeln!(
364 f,
365 "rax={:016x} rbx={:016x} rcx={:016x}",
366 self.rax, self.rbx, self.rcx
367 )?;
368 writeln!(
369 f,
370 "rdx={:016x} rsi={:016x} rdi={:016x}",
371 self.rdx, self.rsi, self.rdi
372 )?;
373 writeln!(
374 f,
375 "rip={:016x} rsp={:016x} rbp={:016x}",
376 self.rip, self.rsp, self.rbp
377 )?;
378 writeln!(
379 f,
380 " r8={:016x} r9={:016x} r10={:016x}",
381 self.r8, self.r9, self.r10
382 )?;
383 writeln!(
384 f,
385 "r11={:016x} r12={:016x} r13={:016x}",
386 self.r11, self.r12, self.r13
387 )?;
388 writeln!(f, "r14={:016x} r15={:016x}", self.r14, self.r15)?;
389 writeln!(f, "cs={:04x} ss={:04x} ds={:04x} es={:04x} fs={:04x} gs={:04x} efl={:08x}",
390 self.seg_cs, self.seg_ss, self.seg_ds, self.seg_es, self.seg_fs, self.seg_gs,
391 self.eflags)?;
392 writeln!(
393 f,
394 "fpcw={:04x} fpsw={:04x} fptw={:04x}",
395 self.control_word, self.status_word, self.tag_word
396 )?;
397 writeln!(
398 f,
399 " st0={:032x} st1={:032x}",
400 self.float_registers[0], self.float_registers[1]
401 )?;
402 writeln!(
403 f,
404 " st2={:032x} st3={:032x}",
405 self.float_registers[2], self.float_registers[3]
406 )?;
407 writeln!(
408 f,
409 " st4={:032x} st5={:032x}",
410 self.float_registers[4], self.float_registers[5]
411 )?;
412 writeln!(
413 f,
414 " st6={:032x} st7={:032x}",
415 self.float_registers[6], self.float_registers[7]
416 )?;
417 writeln!(f, " xmm0={:032x} xmm1={:032x}", self.xmm0, self.xmm1)?;
418 writeln!(f, " xmm2={:032x} xmm3={:032x}", self.xmm2, self.xmm3)?;
419 writeln!(f, " xmm4={:032x} xmm5={:032x}", self.xmm4, self.xmm5)?;
420 writeln!(f, " xmm6={:032x} xmm7={:032x}", self.xmm6, self.xmm7)?;
421 writeln!(f, " xmm8={:032x} xmm9={:032x}", self.xmm8, self.xmm9)?;
422 writeln!(f, "xmm10={:032x} xmm11={:032x}", self.xmm10, self.xmm11)?;
423 writeln!(f, "xmm12={:032x} xmm13={:032x}", self.xmm12, self.xmm13)?;
424 write!(f, "xmm14={:032x} xmm15={:032x}", self.xmm14, self.xmm15)
425 }
426}
427
428impl Default for ThreadContextX64 {
429 fn default() -> Self {
430 unsafe { std::mem::zeroed() }
433 }
434}
435
436#[cfg(test)]
437mod tests {
438 use std::mem;
439
440 use super::*;
441
442 #[test]
444 fn sizeofs() {
445 assert_eq!(mem::size_of::<FloatingSaveArea32>(), 0x70);
446 assert_eq!(mem::size_of::<ThreadContextX86>(), 0x2cc);
447 assert_eq!(mem::size_of::<ThreadContextX64>(), 0x4d0);
450 assert_eq!(mem::size_of::<Header>(), 0x20);
451 assert_eq!(mem::size_of::<LocationDescriptor32>(), 0x8);
452 assert_eq!(mem::size_of::<Directory>(), 0xC);
453 assert_eq!(mem::size_of::<Memory64ListStream>(), 0x10);
454 assert_eq!(mem::size_of::<MemoryDescriptor64>(), 0x10);
455 assert_eq!(mem::size_of::<FixedFileInfo>(), 0x34);
456 assert_eq!(mem::size_of::<ModuleEntry>(), 0x6c);
457 assert_eq!(mem::size_of::<MemoryInfoListStream>(), 0x10);
458 assert_eq!(mem::size_of::<MemoryInfo>(), 0x30);
459 assert_eq!(mem::size_of::<MemoryDescriptor>(), 0x10);
460 assert_eq!(mem::size_of::<ThreadEntry>(), 0x30);
461 assert_eq!(mem::size_of::<SystemInfoStream>(), 32);
462 assert_eq!(mem::size_of::<ExceptionRecord>(), 0x98);
463 assert_eq!(mem::size_of::<ExceptionStream>(), 0xa8);
464 }
465}