1 //! A module to define the FFI definitions we use on Windows for `dbghelp.dll`
2 //!
3 //! This module uses a custom macro, `ffi!`, to wrap all definitions to
4 //! automatically generate tests to assert that our definitions here are the
5 //! same as `winapi`.
6 //!
7 //! This module largely exists to integrate into libstd itself where winapi is
8 //! not currently available.
9 
10 #![allow(bad_style, dead_code)]
11 
12 cfg_if::cfg_if! {
13     if #[cfg(feature = "verify-winapi")] {
14         pub use self::winapi::c_void;
15         pub use self::winapi::HINSTANCE;
16         pub use self::winapi::FARPROC;
17         pub use self::winapi::LPSECURITY_ATTRIBUTES;
18         #[cfg(target_pointer_width = "64")]
19         pub use self::winapi::PUNWIND_HISTORY_TABLE;
20         #[cfg(target_pointer_width = "64")]
21         pub use self::winapi::PRUNTIME_FUNCTION;
22 
23         mod winapi {
24             pub use winapi::ctypes::*;
25             pub use winapi::shared::basetsd::*;
26             pub use winapi::shared::minwindef::*;
27             pub use winapi::um::dbghelp::*;
28             pub use winapi::um::fileapi::*;
29             pub use winapi::um::handleapi::*;
30             pub use winapi::um::libloaderapi::*;
31             pub use winapi::um::memoryapi::*;
32             pub use winapi::um::minwinbase::*;
33             pub use winapi::um::processthreadsapi::*;
34             pub use winapi::um::synchapi::*;
35             pub use winapi::um::tlhelp32::*;
36             pub use winapi::um::winbase::*;
37             pub use winapi::um::winnt::*;
38         }
39     } else {
40         pub use core::ffi::c_void;
41         pub type HINSTANCE = *mut c_void;
42         pub type FARPROC = *mut c_void;
43         pub type LPSECURITY_ATTRIBUTES = *mut c_void;
44         #[cfg(target_pointer_width = "64")]
45         pub type PRUNTIME_FUNCTION = *mut c_void;
46         #[cfg(target_pointer_width = "64")]
47         pub type PUNWIND_HISTORY_TABLE = *mut c_void;
48     }
49 }
50 
51 macro_rules! ffi {
52 	() => ();
53 
54     (#[repr($($r:tt)*)] pub struct $name:ident { $(pub $field:ident: $ty:ty,)* } $($rest:tt)*) => (
55         #[repr($($r)*)]
56         #[cfg(not(feature = "verify-winapi"))]
57         #[derive(Copy, Clone)]
58         pub struct $name {
59             $(pub $field: $ty,)*
60         }
61 
62         #[cfg(feature = "verify-winapi")]
63         pub use self::winapi::$name;
64 
65         #[test]
66         #[cfg(feature = "verify-winapi")]
67         fn $name() {
68             use core::mem;
69 
70             #[repr($($r)*)]
71             pub struct $name {
72                 $(pub $field: $ty,)*
73             }
74 
75             assert_eq!(
76                 mem::size_of::<$name>(),
77                 mem::size_of::<winapi::$name>(),
78                 concat!("size of ", stringify!($name), " is wrong"),
79             );
80             assert_eq!(
81                 mem::align_of::<$name>(),
82                 mem::align_of::<winapi::$name>(),
83                 concat!("align of ", stringify!($name), " is wrong"),
84             );
85 
86             type Winapi = winapi::$name;
87 
88             fn assert_same<T>(_: T, _: T) {}
89 
90             unsafe {
91                 let a = &*(mem::align_of::<$name>() as *const $name);
92                 let b = &*(mem::align_of::<Winapi>() as *const Winapi);
93 
94                 $(
95                     ffi!(@test_fields a b $field $ty);
96                 )*
97             }
98         }
99 
100         ffi!($($rest)*);
101     );
102 
103     // Handling verification against unions in winapi requires some special care
104     (@test_fields $a:ident $b:ident FltSave $ty:ty) => (
105         // Skip this field on x86_64 `CONTEXT` since it's a union and a bit funny
106     );
107     (@test_fields $a:ident $b:ident D $ty:ty) => ({
108         let a = &$a.D;
109         let b = $b.D();
110         assert_same(a, b);
111         assert_eq!(a as *const $ty, b as *const $ty, "misplaced field D");
112     });
113     (@test_fields $a:ident $b:ident s $ty:ty) => ({
114         let a = &$a.s;
115         let b = $b.s();
116         assert_same(a, b);
117         assert_eq!(a as *const $ty, b as *const $ty, "misplaced field s");
118     });
119 
120     // Otherwise test all fields normally.
121     (@test_fields $a:ident $b:ident $field:ident $ty:ty) => ({
122         let a = &$a.$field;
123         let b = &$b.$field;
124         assert_same(a, b);
125         assert_eq!(a as *const $ty, b as *const $ty,
126                    concat!("misplaced field ", stringify!($field)));
127     });
128 
129     (pub type $name:ident = $ty:ty; $($rest:tt)*) => (
130         pub type $name = $ty;
131 
132         #[cfg(feature = "verify-winapi")]
133         #[allow(dead_code)]
134         const $name: () = {
135             fn _foo() {
136                 trait SameType {}
137                 impl<T> SameType for (T, T) {}
138                 fn assert_same<T: SameType>() {}
139 
140                 assert_same::<($name, winapi::$name)>();
141             }
142         };
143 
144         ffi!($($rest)*);
145     );
146 
147     (pub const $name:ident: $ty:ty = $val:expr; $($rest:tt)*) => (
148         pub const $name: $ty = $val;
149 
150         #[cfg(feature = "verify-winapi")]
151         #[allow(unused_imports)]
152         mod $name {
153             use super::*;
154             #[test]
155             fn assert_valid() {
156                 let x: $ty = winapi::$name;
157                 assert_eq!(x, $val);
158             }
159         }
160 
161 
162         ffi!($($rest)*);
163     );
164 
165     (extern "system" { $(pub fn $name:ident($($args:tt)*) -> $ret:ty;)* } $($rest:tt)*) => (
166         extern "system" {
167             $(pub fn $name($($args)*) -> $ret;)*
168         }
169 
170         $(
171             #[cfg(feature = "verify-winapi")]
172             mod $name {
173                 #[test]
174                 fn assert_same() {
175                     use super::*;
176 
177                     assert_eq!($name as usize, winapi::$name as usize);
178                     let mut x: unsafe extern "system" fn($($args)*) -> $ret;
179                     x = $name;
180                     drop(x);
181                     x = winapi::$name;
182                     drop(x);
183                 }
184             }
185         )*
186 
187         ffi!($($rest)*);
188     );
189 
190     (impl $name:ident { $($i:tt)* } $($rest:tt)*) => (
191         #[cfg(not(feature = "verify-winapi"))]
192         impl $name {
193             $($i)*
194         }
195 
196         ffi!($($rest)*);
197     );
198 }
199 
200 ffi! {
201     #[repr(C)]
202     pub struct STACKFRAME64 {
203         pub AddrPC: ADDRESS64,
204         pub AddrReturn: ADDRESS64,
205         pub AddrFrame: ADDRESS64,
206         pub AddrStack: ADDRESS64,
207         pub AddrBStore: ADDRESS64,
208         pub FuncTableEntry: PVOID,
209         pub Params: [DWORD64; 4],
210         pub Far: BOOL,
211         pub Virtual: BOOL,
212         pub Reserved: [DWORD64; 3],
213         pub KdHelp: KDHELP64,
214     }
215 
216     pub type LPSTACKFRAME64 = *mut STACKFRAME64;
217 
218     #[repr(C)]
219     pub struct STACKFRAME_EX {
220         pub AddrPC: ADDRESS64,
221         pub AddrReturn: ADDRESS64,
222         pub AddrFrame: ADDRESS64,
223         pub AddrStack: ADDRESS64,
224         pub AddrBStore: ADDRESS64,
225         pub FuncTableEntry: PVOID,
226         pub Params: [DWORD64; 4],
227         pub Far: BOOL,
228         pub Virtual: BOOL,
229         pub Reserved: [DWORD64; 3],
230         pub KdHelp: KDHELP64,
231         pub StackFrameSize: DWORD,
232         pub InlineFrameContext: DWORD,
233     }
234 
235     pub type LPSTACKFRAME_EX = *mut STACKFRAME_EX;
236 
237     #[repr(C)]
238     pub struct IMAGEHLP_LINEW64 {
239         pub SizeOfStruct: DWORD,
240         pub Key: PVOID,
241         pub LineNumber: DWORD,
242         pub FileName: PWSTR,
243         pub Address: DWORD64,
244     }
245 
246     pub type PIMAGEHLP_LINEW64 = *mut IMAGEHLP_LINEW64;
247 
248     #[repr(C)]
249     pub struct SYMBOL_INFOW {
250         pub SizeOfStruct: ULONG,
251         pub TypeIndex: ULONG,
252         pub Reserved: [ULONG64; 2],
253         pub Index: ULONG,
254         pub Size: ULONG,
255         pub ModBase: ULONG64,
256         pub Flags: ULONG,
257         pub Value: ULONG64,
258         pub Address: ULONG64,
259         pub Register: ULONG,
260         pub Scope: ULONG,
261         pub Tag: ULONG,
262         pub NameLen: ULONG,
263         pub MaxNameLen: ULONG,
264         pub Name: [WCHAR; 1],
265     }
266 
267     pub type PSYMBOL_INFOW = *mut SYMBOL_INFOW;
268 
269     pub type PTRANSLATE_ADDRESS_ROUTINE64 = Option<
270         unsafe extern "system" fn(hProcess: HANDLE, hThread: HANDLE, lpaddr: LPADDRESS64) -> DWORD64,
271     >;
272     pub type PGET_MODULE_BASE_ROUTINE64 =
273         Option<unsafe extern "system" fn(hProcess: HANDLE, Address: DWORD64) -> DWORD64>;
274     pub type PFUNCTION_TABLE_ACCESS_ROUTINE64 =
275         Option<unsafe extern "system" fn(ahProcess: HANDLE, AddrBase: DWORD64) -> PVOID>;
276     pub type PREAD_PROCESS_MEMORY_ROUTINE64 = Option<
277         unsafe extern "system" fn(
278             hProcess: HANDLE,
279             qwBaseAddress: DWORD64,
280             lpBuffer: PVOID,
281             nSize: DWORD,
282             lpNumberOfBytesRead: LPDWORD,
283         ) -> BOOL,
284     >;
285 
286     #[repr(C)]
287     pub struct ADDRESS64 {
288         pub Offset: DWORD64,
289         pub Segment: WORD,
290         pub Mode: ADDRESS_MODE,
291     }
292 
293     pub type LPADDRESS64 = *mut ADDRESS64;
294 
295     pub type ADDRESS_MODE = u32;
296 
297     #[repr(C)]
298     pub struct KDHELP64 {
299         pub Thread: DWORD64,
300         pub ThCallbackStack: DWORD,
301         pub ThCallbackBStore: DWORD,
302         pub NextCallback: DWORD,
303         pub FramePointer: DWORD,
304         pub KiCallUserMode: DWORD64,
305         pub KeUserCallbackDispatcher: DWORD64,
306         pub SystemRangeStart: DWORD64,
307         pub KiUserExceptionDispatcher: DWORD64,
308         pub StackBase: DWORD64,
309         pub StackLimit: DWORD64,
310         pub BuildVersion: DWORD,
311         pub Reserved0: DWORD,
312         pub Reserved1: [DWORD64; 4],
313     }
314 
315     #[repr(C)]
316     pub struct MODULEENTRY32W {
317         pub dwSize: DWORD,
318         pub th32ModuleID: DWORD,
319         pub th32ProcessID: DWORD,
320         pub GlblcntUsage: DWORD,
321         pub ProccntUsage: DWORD,
322         pub modBaseAddr: *mut u8,
323         pub modBaseSize: DWORD,
324         pub hModule: HMODULE,
325         pub szModule: [WCHAR; MAX_MODULE_NAME32 + 1],
326         pub szExePath: [WCHAR; MAX_PATH],
327     }
328 
329     pub const MAX_SYM_NAME: usize = 2000;
330     pub const AddrModeFlat: ADDRESS_MODE = 3;
331     pub const TRUE: BOOL = 1;
332     pub const FALSE: BOOL = 0;
333     pub const PROCESS_QUERY_INFORMATION: DWORD = 0x400;
334     pub const IMAGE_FILE_MACHINE_ARM64: u16 = 43620;
335     pub const IMAGE_FILE_MACHINE_AMD64: u16 = 34404;
336     pub const IMAGE_FILE_MACHINE_I386: u16 = 332;
337     pub const IMAGE_FILE_MACHINE_ARMNT: u16 = 452;
338     pub const FILE_SHARE_READ: DWORD = 0x1;
339     pub const FILE_SHARE_WRITE: DWORD = 0x2;
340     pub const OPEN_EXISTING: DWORD = 0x3;
341     pub const GENERIC_READ: DWORD = 0x80000000;
342     pub const INFINITE: DWORD = !0;
343     pub const PAGE_READONLY: DWORD = 2;
344     pub const FILE_MAP_READ: DWORD = 4;
345     pub const TH32CS_SNAPMODULE: DWORD = 0x00000008;
346     pub const INVALID_HANDLE_VALUE: HANDLE = -1isize as HANDLE;
347     pub const MAX_MODULE_NAME32: usize = 255;
348     pub const MAX_PATH: usize = 260;
349 
350     pub type DWORD = u32;
351     pub type PDWORD = *mut u32;
352     pub type BOOL = i32;
353     pub type DWORD64 = u64;
354     pub type PDWORD64 = *mut u64;
355     pub type HANDLE = *mut c_void;
356     pub type PVOID = HANDLE;
357     pub type PCWSTR = *const u16;
358     pub type LPSTR = *mut i8;
359     pub type LPCSTR = *const i8;
360     pub type PWSTR = *mut u16;
361     pub type WORD = u16;
362     pub type ULONG = u32;
363     pub type ULONG64 = u64;
364     pub type WCHAR = u16;
365     pub type PCONTEXT = *mut CONTEXT;
366     pub type LPDWORD = *mut DWORD;
367     pub type DWORDLONG = u64;
368     pub type HMODULE = HINSTANCE;
369     pub type SIZE_T = usize;
370     pub type LPVOID = *mut c_void;
371     pub type LPCVOID = *const c_void;
372     pub type LPMODULEENTRY32W = *mut MODULEENTRY32W;
373 
374     extern "system" {
375         pub fn GetCurrentProcess() -> HANDLE;
376         pub fn GetCurrentThread() -> HANDLE;
377         pub fn RtlCaptureContext(ContextRecord: PCONTEXT) -> ();
378         pub fn LoadLibraryA(a: *const i8) -> HMODULE;
379         pub fn GetProcAddress(h: HMODULE, name: *const i8) -> FARPROC;
380         pub fn GetModuleHandleA(name: *const i8) -> HMODULE;
381         pub fn OpenProcess(
382             dwDesiredAccess: DWORD,
383             bInheitHandle: BOOL,
384             dwProcessId: DWORD,
385         ) -> HANDLE;
386         pub fn GetCurrentProcessId() -> DWORD;
387         pub fn CloseHandle(h: HANDLE) -> BOOL;
388         pub fn CreateFileA(
389             lpFileName: LPCSTR,
390             dwDesiredAccess: DWORD,
391             dwShareMode: DWORD,
392             lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
393             dwCreationDisposition: DWORD,
394             dwFlagsAndAttributes: DWORD,
395             hTemplateFile: HANDLE,
396         ) -> HANDLE;
397         pub fn CreateMutexA(
398             attrs: LPSECURITY_ATTRIBUTES,
399             initial: BOOL,
400             name: LPCSTR,
401         ) -> HANDLE;
402         pub fn ReleaseMutex(hMutex: HANDLE) -> BOOL;
403         pub fn WaitForSingleObjectEx(
404             hHandle: HANDLE,
405             dwMilliseconds: DWORD,
406             bAlertable: BOOL,
407         ) -> DWORD;
408         pub fn CreateFileMappingA(
409             hFile: HANDLE,
410             lpFileMappingAttributes: LPSECURITY_ATTRIBUTES,
411             flProtect: DWORD,
412             dwMaximumSizeHigh: DWORD,
413             dwMaximumSizeLow: DWORD,
414             lpName: LPCSTR,
415         ) -> HANDLE;
416         pub fn MapViewOfFile(
417             hFileMappingObject: HANDLE,
418             dwDesiredAccess: DWORD,
419             dwFileOffsetHigh: DWORD,
420             dwFileOffsetLow: DWORD,
421             dwNumberOfBytesToMap: SIZE_T,
422         ) -> LPVOID;
423         pub fn UnmapViewOfFile(lpBaseAddress: LPCVOID) -> BOOL;
424         pub fn CreateToolhelp32Snapshot(
425             dwFlags: DWORD,
426             th32ProcessID: DWORD,
427         ) -> HANDLE;
428         pub fn Module32FirstW(
429             hSnapshot: HANDLE,
430             lpme: LPMODULEENTRY32W,
431         ) -> BOOL;
432         pub fn Module32NextW(
433             hSnapshot: HANDLE,
434             lpme: LPMODULEENTRY32W,
435         ) -> BOOL;
436     }
437 }
438 
439 #[cfg(target_pointer_width = "64")]
440 ffi! {
441     extern "system" {
442         pub fn RtlLookupFunctionEntry(
443             ControlPc: DWORD64,
444             ImageBase: PDWORD64,
445             HistoryTable: PUNWIND_HISTORY_TABLE,
446         ) -> PRUNTIME_FUNCTION;
447     }
448 }
449 
450 #[cfg(target_arch = "aarch64")]
451 ffi! {
452     #[repr(C, align(16))]
453     pub struct CONTEXT {
454         pub ContextFlags: DWORD,
455         pub Cpsr: DWORD,
456         pub u: CONTEXT_u,
457         pub Sp: u64,
458         pub Pc: u64,
459         pub V: [ARM64_NT_NEON128; 32],
460         pub Fpcr: DWORD,
461         pub Fpsr: DWORD,
462         pub Bcr: [DWORD; ARM64_MAX_BREAKPOINTS],
463         pub Bvr: [DWORD64; ARM64_MAX_BREAKPOINTS],
464         pub Wcr: [DWORD; ARM64_MAX_WATCHPOINTS],
465         pub Wvr: [DWORD64; ARM64_MAX_WATCHPOINTS],
466     }
467 
468     #[repr(C)]
469     pub struct CONTEXT_u {
470         pub s: CONTEXT_u_s,
471     }
472 
473     impl CONTEXT_u {
474         pub unsafe fn s(&self) -> &CONTEXT_u_s {
475             &self.s
476         }
477     }
478 
479     #[repr(C)]
480     pub struct CONTEXT_u_s {
481         pub X0: u64,
482         pub X1: u64,
483         pub X2: u64,
484         pub X3: u64,
485         pub X4: u64,
486         pub X5: u64,
487         pub X6: u64,
488         pub X7: u64,
489         pub X8: u64,
490         pub X9: u64,
491         pub X10: u64,
492         pub X11: u64,
493         pub X12: u64,
494         pub X13: u64,
495         pub X14: u64,
496         pub X15: u64,
497         pub X16: u64,
498         pub X17: u64,
499         pub X18: u64,
500         pub X19: u64,
501         pub X20: u64,
502         pub X21: u64,
503         pub X22: u64,
504         pub X23: u64,
505         pub X24: u64,
506         pub X25: u64,
507         pub X26: u64,
508         pub X27: u64,
509         pub X28: u64,
510         pub Fp: u64,
511         pub Lr: u64,
512     }
513 
514     pub const ARM64_MAX_BREAKPOINTS: usize = 8;
515     pub const ARM64_MAX_WATCHPOINTS: usize = 2;
516 
517     #[repr(C)]
518     pub struct ARM64_NT_NEON128 {
519         pub D: [f64; 2],
520     }
521 }
522 
523 #[cfg(target_arch = "x86")]
524 ffi! {
525     #[repr(C)]
526     pub struct CONTEXT {
527         pub ContextFlags: DWORD,
528         pub Dr0: DWORD,
529         pub Dr1: DWORD,
530         pub Dr2: DWORD,
531         pub Dr3: DWORD,
532         pub Dr6: DWORD,
533         pub Dr7: DWORD,
534         pub FloatSave: FLOATING_SAVE_AREA,
535         pub SegGs: DWORD,
536         pub SegFs: DWORD,
537         pub SegEs: DWORD,
538         pub SegDs: DWORD,
539         pub Edi: DWORD,
540         pub Esi: DWORD,
541         pub Ebx: DWORD,
542         pub Edx: DWORD,
543         pub Ecx: DWORD,
544         pub Eax: DWORD,
545         pub Ebp: DWORD,
546         pub Eip: DWORD,
547         pub SegCs: DWORD,
548         pub EFlags: DWORD,
549         pub Esp: DWORD,
550         pub SegSs: DWORD,
551         pub ExtendedRegisters: [u8; 512],
552     }
553 
554     #[repr(C)]
555     pub struct FLOATING_SAVE_AREA {
556         pub ControlWord: DWORD,
557         pub StatusWord: DWORD,
558         pub TagWord: DWORD,
559         pub ErrorOffset: DWORD,
560         pub ErrorSelector: DWORD,
561         pub DataOffset: DWORD,
562         pub DataSelector: DWORD,
563         pub RegisterArea: [u8; 80],
564         pub Spare0: DWORD,
565     }
566 }
567 
568 #[cfg(target_arch = "x86_64")]
569 ffi! {
570     #[repr(C, align(8))]
571     pub struct CONTEXT {
572         pub P1Home: DWORDLONG,
573         pub P2Home: DWORDLONG,
574         pub P3Home: DWORDLONG,
575         pub P4Home: DWORDLONG,
576         pub P5Home: DWORDLONG,
577         pub P6Home: DWORDLONG,
578 
579         pub ContextFlags: DWORD,
580         pub MxCsr: DWORD,
581 
582         pub SegCs: WORD,
583         pub SegDs: WORD,
584         pub SegEs: WORD,
585         pub SegFs: WORD,
586         pub SegGs: WORD,
587         pub SegSs: WORD,
588         pub EFlags: DWORD,
589 
590         pub Dr0: DWORDLONG,
591         pub Dr1: DWORDLONG,
592         pub Dr2: DWORDLONG,
593         pub Dr3: DWORDLONG,
594         pub Dr6: DWORDLONG,
595         pub Dr7: DWORDLONG,
596 
597         pub Rax: DWORDLONG,
598         pub Rcx: DWORDLONG,
599         pub Rdx: DWORDLONG,
600         pub Rbx: DWORDLONG,
601         pub Rsp: DWORDLONG,
602         pub Rbp: DWORDLONG,
603         pub Rsi: DWORDLONG,
604         pub Rdi: DWORDLONG,
605         pub R8:  DWORDLONG,
606         pub R9:  DWORDLONG,
607         pub R10: DWORDLONG,
608         pub R11: DWORDLONG,
609         pub R12: DWORDLONG,
610         pub R13: DWORDLONG,
611         pub R14: DWORDLONG,
612         pub R15: DWORDLONG,
613 
614         pub Rip: DWORDLONG,
615 
616         pub FltSave: FLOATING_SAVE_AREA,
617 
618         pub VectorRegister: [M128A; 26],
619         pub VectorControl: DWORDLONG,
620 
621         pub DebugControl: DWORDLONG,
622         pub LastBranchToRip: DWORDLONG,
623         pub LastBranchFromRip: DWORDLONG,
624         pub LastExceptionToRip: DWORDLONG,
625         pub LastExceptionFromRip: DWORDLONG,
626     }
627 
628     #[repr(C)]
629     pub struct M128A {
630         pub Low: u64,
631         pub High: i64,
632     }
633 }
634 
635 #[repr(C)]
636 #[cfg(target_arch = "x86_64")]
637 #[derive(Copy, Clone)]
638 pub struct FLOATING_SAVE_AREA {
639     _Dummy: [u8; 512],
640 }
641 
642 #[cfg(target_arch = "arm")]
643 ffi! {
644     // #[repr(C)]
645     // pub struct NEON128 {
646     //     pub Low: ULONG64,
647     //     pub High: LONG64,
648     // }
649 
650     // pub type PNEON128 = *mut NEON128;
651 
652     #[repr(C)]
653     pub struct CONTEXT_u {
654         // pub Q: [NEON128; 16],
655         pub D: [ULONG64; 32],
656         // pub S: [DWORD; 32],
657     }
658 
659     pub const ARM_MAX_BREAKPOINTS: usize = 8;
660     pub const ARM_MAX_WATCHPOINTS: usize = 1;
661 
662     #[repr(C)]
663     pub struct CONTEXT {
664         pub ContextFlags: DWORD,
665         pub R0: DWORD,
666         pub R1: DWORD,
667         pub R2: DWORD,
668         pub R3: DWORD,
669         pub R4: DWORD,
670         pub R5: DWORD,
671         pub R6: DWORD,
672         pub R7: DWORD,
673         pub R8: DWORD,
674         pub R9: DWORD,
675         pub R10: DWORD,
676         pub R11: DWORD,
677         pub R12: DWORD,
678         pub Sp: DWORD,
679         pub Lr: DWORD,
680         pub Pc: DWORD,
681         pub Cpsr: DWORD,
682         pub Fpsrc: DWORD,
683         pub Padding: DWORD,
684         pub u: CONTEXT_u,
685         pub Bvr: [DWORD; ARM_MAX_BREAKPOINTS],
686         pub Bcr: [DWORD; ARM_MAX_BREAKPOINTS],
687         pub Wvr: [DWORD; ARM_MAX_WATCHPOINTS],
688         pub Wcr: [DWORD; ARM_MAX_WATCHPOINTS],
689         pub Padding2: [DWORD; 2],
690     }
691 } // IFDEF(arm)
692