summaryrefslogtreecommitdiffstats
path: root/library/backtrace/src/windows.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--library/backtrace/src/windows.rs691
1 files changed, 691 insertions, 0 deletions
diff --git a/library/backtrace/src/windows.rs b/library/backtrace/src/windows.rs
new file mode 100644
index 000000000..d091874f1
--- /dev/null
+++ b/library/backtrace/src/windows.rs
@@ -0,0 +1,691 @@
+//! A module to define the FFI definitions we use on Windows for `dbghelp.dll`
+//!
+//! This module uses a custom macro, `ffi!`, to wrap all definitions to
+//! automatically generate tests to assert that our definitions here are the
+//! same as `winapi`.
+//!
+//! This module largely exists to integrate into libstd itself where winapi is
+//! not currently available.
+
+#![allow(bad_style, dead_code)]
+
+cfg_if::cfg_if! {
+ if #[cfg(feature = "verify-winapi")] {
+ pub use self::winapi::c_void;
+ pub use self::winapi::HINSTANCE;
+ pub use self::winapi::FARPROC;
+ pub use self::winapi::LPSECURITY_ATTRIBUTES;
+ #[cfg(target_pointer_width = "64")]
+ pub use self::winapi::PUNWIND_HISTORY_TABLE;
+ #[cfg(target_pointer_width = "64")]
+ pub use self::winapi::PRUNTIME_FUNCTION;
+
+ mod winapi {
+ pub use winapi::ctypes::*;
+ pub use winapi::shared::basetsd::*;
+ pub use winapi::shared::minwindef::*;
+ pub use winapi::um::dbghelp::*;
+ pub use winapi::um::fileapi::*;
+ pub use winapi::um::handleapi::*;
+ pub use winapi::um::libloaderapi::*;
+ pub use winapi::um::memoryapi::*;
+ pub use winapi::um::minwinbase::*;
+ pub use winapi::um::processthreadsapi::*;
+ pub use winapi::um::synchapi::*;
+ pub use winapi::um::tlhelp32::*;
+ pub use winapi::um::winbase::*;
+ pub use winapi::um::winnt::*;
+ }
+ } else {
+ pub use core::ffi::c_void;
+ pub type HINSTANCE = *mut c_void;
+ pub type FARPROC = *mut c_void;
+ pub type LPSECURITY_ATTRIBUTES = *mut c_void;
+ #[cfg(target_pointer_width = "64")]
+ pub type PRUNTIME_FUNCTION = *mut c_void;
+ #[cfg(target_pointer_width = "64")]
+ pub type PUNWIND_HISTORY_TABLE = *mut c_void;
+ }
+}
+
+macro_rules! ffi {
+ () => ();
+
+ (#[repr($($r:tt)*)] pub struct $name:ident { $(pub $field:ident: $ty:ty,)* } $($rest:tt)*) => (
+ #[repr($($r)*)]
+ #[cfg(not(feature = "verify-winapi"))]
+ #[derive(Copy, Clone)]
+ pub struct $name {
+ $(pub $field: $ty,)*
+ }
+
+ #[cfg(feature = "verify-winapi")]
+ pub use self::winapi::$name;
+
+ #[test]
+ #[cfg(feature = "verify-winapi")]
+ fn $name() {
+ use core::mem;
+
+ #[repr($($r)*)]
+ pub struct $name {
+ $(pub $field: $ty,)*
+ }
+
+ assert_eq!(
+ mem::size_of::<$name>(),
+ mem::size_of::<winapi::$name>(),
+ concat!("size of ", stringify!($name), " is wrong"),
+ );
+ assert_eq!(
+ mem::align_of::<$name>(),
+ mem::align_of::<winapi::$name>(),
+ concat!("align of ", stringify!($name), " is wrong"),
+ );
+
+ type Winapi = winapi::$name;
+
+ fn assert_same<T>(_: T, _: T) {}
+
+ unsafe {
+ let a = &*(mem::align_of::<$name>() as *const $name);
+ let b = &*(mem::align_of::<Winapi>() as *const Winapi);
+
+ $(
+ ffi!(@test_fields a b $field $ty);
+ )*
+ }
+ }
+
+ ffi!($($rest)*);
+ );
+
+ // Handling verification against unions in winapi requires some special care
+ (@test_fields $a:ident $b:ident FltSave $ty:ty) => (
+ // Skip this field on x86_64 `CONTEXT` since it's a union and a bit funny
+ );
+ (@test_fields $a:ident $b:ident D $ty:ty) => ({
+ let a = &$a.D;
+ let b = $b.D();
+ assert_same(a, b);
+ assert_eq!(a as *const $ty, b as *const $ty, "misplaced field D");
+ });
+ (@test_fields $a:ident $b:ident s $ty:ty) => ({
+ let a = &$a.s;
+ let b = $b.s();
+ assert_same(a, b);
+ assert_eq!(a as *const $ty, b as *const $ty, "misplaced field s");
+ });
+
+ // Otherwise test all fields normally.
+ (@test_fields $a:ident $b:ident $field:ident $ty:ty) => ({
+ let a = &$a.$field;
+ let b = &$b.$field;
+ assert_same(a, b);
+ assert_eq!(a as *const $ty, b as *const $ty,
+ concat!("misplaced field ", stringify!($field)));
+ });
+
+ (pub type $name:ident = $ty:ty; $($rest:tt)*) => (
+ pub type $name = $ty;
+
+ #[cfg(feature = "verify-winapi")]
+ #[allow(dead_code)]
+ const $name: () = {
+ fn _foo() {
+ trait SameType {}
+ impl<T> SameType for (T, T) {}
+ fn assert_same<T: SameType>() {}
+
+ assert_same::<($name, winapi::$name)>();
+ }
+ };
+
+ ffi!($($rest)*);
+ );
+
+ (pub const $name:ident: $ty:ty = $val:expr; $($rest:tt)*) => (
+ pub const $name: $ty = $val;
+
+ #[cfg(feature = "verify-winapi")]
+ #[allow(unused_imports)]
+ mod $name {
+ use super::*;
+ #[test]
+ fn assert_valid() {
+ let x: $ty = winapi::$name;
+ assert_eq!(x, $val);
+ }
+ }
+
+
+ ffi!($($rest)*);
+ );
+
+ (extern "system" { $(pub fn $name:ident($($args:tt)*) -> $ret:ty;)* } $($rest:tt)*) => (
+ extern "system" {
+ $(pub fn $name($($args)*) -> $ret;)*
+ }
+
+ $(
+ #[cfg(feature = "verify-winapi")]
+ mod $name {
+ #[test]
+ fn assert_same() {
+ use super::*;
+
+ assert_eq!($name as usize, winapi::$name as usize);
+ let mut x: unsafe extern "system" fn($($args)*) -> $ret;
+ x = $name;
+ drop(x);
+ x = winapi::$name;
+ drop(x);
+ }
+ }
+ )*
+
+ ffi!($($rest)*);
+ );
+
+ (impl $name:ident { $($i:tt)* } $($rest:tt)*) => (
+ #[cfg(not(feature = "verify-winapi"))]
+ impl $name {
+ $($i)*
+ }
+
+ ffi!($($rest)*);
+ );
+}
+
+ffi! {
+ #[repr(C)]
+ pub struct STACKFRAME64 {
+ pub AddrPC: ADDRESS64,
+ pub AddrReturn: ADDRESS64,
+ pub AddrFrame: ADDRESS64,
+ pub AddrStack: ADDRESS64,
+ pub AddrBStore: ADDRESS64,
+ pub FuncTableEntry: PVOID,
+ pub Params: [DWORD64; 4],
+ pub Far: BOOL,
+ pub Virtual: BOOL,
+ pub Reserved: [DWORD64; 3],
+ pub KdHelp: KDHELP64,
+ }
+
+ pub type LPSTACKFRAME64 = *mut STACKFRAME64;
+
+ #[repr(C)]
+ pub struct STACKFRAME_EX {
+ pub AddrPC: ADDRESS64,
+ pub AddrReturn: ADDRESS64,
+ pub AddrFrame: ADDRESS64,
+ pub AddrStack: ADDRESS64,
+ pub AddrBStore: ADDRESS64,
+ pub FuncTableEntry: PVOID,
+ pub Params: [DWORD64; 4],
+ pub Far: BOOL,
+ pub Virtual: BOOL,
+ pub Reserved: [DWORD64; 3],
+ pub KdHelp: KDHELP64,
+ pub StackFrameSize: DWORD,
+ pub InlineFrameContext: DWORD,
+ }
+
+ pub type LPSTACKFRAME_EX = *mut STACKFRAME_EX;
+
+ #[repr(C)]
+ pub struct IMAGEHLP_LINEW64 {
+ pub SizeOfStruct: DWORD,
+ pub Key: PVOID,
+ pub LineNumber: DWORD,
+ pub FileName: PWSTR,
+ pub Address: DWORD64,
+ }
+
+ pub type PIMAGEHLP_LINEW64 = *mut IMAGEHLP_LINEW64;
+
+ #[repr(C)]
+ pub struct SYMBOL_INFOW {
+ pub SizeOfStruct: ULONG,
+ pub TypeIndex: ULONG,
+ pub Reserved: [ULONG64; 2],
+ pub Index: ULONG,
+ pub Size: ULONG,
+ pub ModBase: ULONG64,
+ pub Flags: ULONG,
+ pub Value: ULONG64,
+ pub Address: ULONG64,
+ pub Register: ULONG,
+ pub Scope: ULONG,
+ pub Tag: ULONG,
+ pub NameLen: ULONG,
+ pub MaxNameLen: ULONG,
+ pub Name: [WCHAR; 1],
+ }
+
+ pub type PSYMBOL_INFOW = *mut SYMBOL_INFOW;
+
+ pub type PTRANSLATE_ADDRESS_ROUTINE64 = Option<
+ unsafe extern "system" fn(hProcess: HANDLE, hThread: HANDLE, lpaddr: LPADDRESS64) -> DWORD64,
+ >;
+ pub type PGET_MODULE_BASE_ROUTINE64 =
+ Option<unsafe extern "system" fn(hProcess: HANDLE, Address: DWORD64) -> DWORD64>;
+ pub type PFUNCTION_TABLE_ACCESS_ROUTINE64 =
+ Option<unsafe extern "system" fn(ahProcess: HANDLE, AddrBase: DWORD64) -> PVOID>;
+ pub type PREAD_PROCESS_MEMORY_ROUTINE64 = Option<
+ unsafe extern "system" fn(
+ hProcess: HANDLE,
+ qwBaseAddress: DWORD64,
+ lpBuffer: PVOID,
+ nSize: DWORD,
+ lpNumberOfBytesRead: LPDWORD,
+ ) -> BOOL,
+ >;
+
+ #[repr(C)]
+ pub struct ADDRESS64 {
+ pub Offset: DWORD64,
+ pub Segment: WORD,
+ pub Mode: ADDRESS_MODE,
+ }
+
+ pub type LPADDRESS64 = *mut ADDRESS64;
+
+ pub type ADDRESS_MODE = u32;
+
+ #[repr(C)]
+ pub struct KDHELP64 {
+ pub Thread: DWORD64,
+ pub ThCallbackStack: DWORD,
+ pub ThCallbackBStore: DWORD,
+ pub NextCallback: DWORD,
+ pub FramePointer: DWORD,
+ pub KiCallUserMode: DWORD64,
+ pub KeUserCallbackDispatcher: DWORD64,
+ pub SystemRangeStart: DWORD64,
+ pub KiUserExceptionDispatcher: DWORD64,
+ pub StackBase: DWORD64,
+ pub StackLimit: DWORD64,
+ pub BuildVersion: DWORD,
+ pub Reserved0: DWORD,
+ pub Reserved1: [DWORD64; 4],
+ }
+
+ #[repr(C)]
+ pub struct MODULEENTRY32W {
+ pub dwSize: DWORD,
+ pub th32ModuleID: DWORD,
+ pub th32ProcessID: DWORD,
+ pub GlblcntUsage: DWORD,
+ pub ProccntUsage: DWORD,
+ pub modBaseAddr: *mut u8,
+ pub modBaseSize: DWORD,
+ pub hModule: HMODULE,
+ pub szModule: [WCHAR; MAX_MODULE_NAME32 + 1],
+ pub szExePath: [WCHAR; MAX_PATH],
+ }
+
+ pub const MAX_SYM_NAME: usize = 2000;
+ pub const AddrModeFlat: ADDRESS_MODE = 3;
+ pub const TRUE: BOOL = 1;
+ pub const FALSE: BOOL = 0;
+ pub const PROCESS_QUERY_INFORMATION: DWORD = 0x400;
+ pub const IMAGE_FILE_MACHINE_ARM64: u16 = 43620;
+ pub const IMAGE_FILE_MACHINE_AMD64: u16 = 34404;
+ pub const IMAGE_FILE_MACHINE_I386: u16 = 332;
+ pub const IMAGE_FILE_MACHINE_ARMNT: u16 = 452;
+ pub const FILE_SHARE_READ: DWORD = 0x1;
+ pub const FILE_SHARE_WRITE: DWORD = 0x2;
+ pub const OPEN_EXISTING: DWORD = 0x3;
+ pub const GENERIC_READ: DWORD = 0x80000000;
+ pub const INFINITE: DWORD = !0;
+ pub const PAGE_READONLY: DWORD = 2;
+ pub const FILE_MAP_READ: DWORD = 4;
+ pub const TH32CS_SNAPMODULE: DWORD = 0x00000008;
+ pub const INVALID_HANDLE_VALUE: HANDLE = -1isize as HANDLE;
+ pub const MAX_MODULE_NAME32: usize = 255;
+ pub const MAX_PATH: usize = 260;
+
+ pub type DWORD = u32;
+ pub type PDWORD = *mut u32;
+ pub type BOOL = i32;
+ pub type DWORD64 = u64;
+ pub type PDWORD64 = *mut u64;
+ pub type HANDLE = *mut c_void;
+ pub type PVOID = HANDLE;
+ pub type PCWSTR = *const u16;
+ pub type LPSTR = *mut i8;
+ pub type LPCSTR = *const i8;
+ pub type PWSTR = *mut u16;
+ pub type WORD = u16;
+ pub type ULONG = u32;
+ pub type ULONG64 = u64;
+ pub type WCHAR = u16;
+ pub type PCONTEXT = *mut CONTEXT;
+ pub type LPDWORD = *mut DWORD;
+ pub type DWORDLONG = u64;
+ pub type HMODULE = HINSTANCE;
+ pub type SIZE_T = usize;
+ pub type LPVOID = *mut c_void;
+ pub type LPCVOID = *const c_void;
+ pub type LPMODULEENTRY32W = *mut MODULEENTRY32W;
+
+ extern "system" {
+ pub fn GetCurrentProcess() -> HANDLE;
+ pub fn GetCurrentThread() -> HANDLE;
+ pub fn RtlCaptureContext(ContextRecord: PCONTEXT) -> ();
+ pub fn LoadLibraryA(a: *const i8) -> HMODULE;
+ pub fn GetProcAddress(h: HMODULE, name: *const i8) -> FARPROC;
+ pub fn GetModuleHandleA(name: *const i8) -> HMODULE;
+ pub fn OpenProcess(
+ dwDesiredAccess: DWORD,
+ bInheitHandle: BOOL,
+ dwProcessId: DWORD,
+ ) -> HANDLE;
+ pub fn GetCurrentProcessId() -> DWORD;
+ pub fn CloseHandle(h: HANDLE) -> BOOL;
+ pub fn CreateFileA(
+ lpFileName: LPCSTR,
+ dwDesiredAccess: DWORD,
+ dwShareMode: DWORD,
+ lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
+ dwCreationDisposition: DWORD,
+ dwFlagsAndAttributes: DWORD,
+ hTemplateFile: HANDLE,
+ ) -> HANDLE;
+ pub fn CreateMutexA(
+ attrs: LPSECURITY_ATTRIBUTES,
+ initial: BOOL,
+ name: LPCSTR,
+ ) -> HANDLE;
+ pub fn ReleaseMutex(hMutex: HANDLE) -> BOOL;
+ pub fn WaitForSingleObjectEx(
+ hHandle: HANDLE,
+ dwMilliseconds: DWORD,
+ bAlertable: BOOL,
+ ) -> DWORD;
+ pub fn CreateFileMappingA(
+ hFile: HANDLE,
+ lpFileMappingAttributes: LPSECURITY_ATTRIBUTES,
+ flProtect: DWORD,
+ dwMaximumSizeHigh: DWORD,
+ dwMaximumSizeLow: DWORD,
+ lpName: LPCSTR,
+ ) -> HANDLE;
+ pub fn MapViewOfFile(
+ hFileMappingObject: HANDLE,
+ dwDesiredAccess: DWORD,
+ dwFileOffsetHigh: DWORD,
+ dwFileOffsetLow: DWORD,
+ dwNumberOfBytesToMap: SIZE_T,
+ ) -> LPVOID;
+ pub fn UnmapViewOfFile(lpBaseAddress: LPCVOID) -> BOOL;
+ pub fn CreateToolhelp32Snapshot(
+ dwFlags: DWORD,
+ th32ProcessID: DWORD,
+ ) -> HANDLE;
+ pub fn Module32FirstW(
+ hSnapshot: HANDLE,
+ lpme: LPMODULEENTRY32W,
+ ) -> BOOL;
+ pub fn Module32NextW(
+ hSnapshot: HANDLE,
+ lpme: LPMODULEENTRY32W,
+ ) -> BOOL;
+ }
+}
+
+#[cfg(target_pointer_width = "64")]
+ffi! {
+ extern "system" {
+ pub fn RtlLookupFunctionEntry(
+ ControlPc: DWORD64,
+ ImageBase: PDWORD64,
+ HistoryTable: PUNWIND_HISTORY_TABLE,
+ ) -> PRUNTIME_FUNCTION;
+ }
+}
+
+#[cfg(target_arch = "aarch64")]
+ffi! {
+ #[repr(C, align(16))]
+ pub struct CONTEXT {
+ pub ContextFlags: DWORD,
+ pub Cpsr: DWORD,
+ pub u: CONTEXT_u,
+ pub Sp: u64,
+ pub Pc: u64,
+ pub V: [ARM64_NT_NEON128; 32],
+ pub Fpcr: DWORD,
+ pub Fpsr: DWORD,
+ pub Bcr: [DWORD; ARM64_MAX_BREAKPOINTS],
+ pub Bvr: [DWORD64; ARM64_MAX_BREAKPOINTS],
+ pub Wcr: [DWORD; ARM64_MAX_WATCHPOINTS],
+ pub Wvr: [DWORD64; ARM64_MAX_WATCHPOINTS],
+ }
+
+ #[repr(C)]
+ pub struct CONTEXT_u {
+ pub s: CONTEXT_u_s,
+ }
+
+ impl CONTEXT_u {
+ pub unsafe fn s(&self) -> &CONTEXT_u_s {
+ &self.s
+ }
+ }
+
+ #[repr(C)]
+ pub struct CONTEXT_u_s {
+ pub X0: u64,
+ pub X1: u64,
+ pub X2: u64,
+ pub X3: u64,
+ pub X4: u64,
+ pub X5: u64,
+ pub X6: u64,
+ pub X7: u64,
+ pub X8: u64,
+ pub X9: u64,
+ pub X10: u64,
+ pub X11: u64,
+ pub X12: u64,
+ pub X13: u64,
+ pub X14: u64,
+ pub X15: u64,
+ pub X16: u64,
+ pub X17: u64,
+ pub X18: u64,
+ pub X19: u64,
+ pub X20: u64,
+ pub X21: u64,
+ pub X22: u64,
+ pub X23: u64,
+ pub X24: u64,
+ pub X25: u64,
+ pub X26: u64,
+ pub X27: u64,
+ pub X28: u64,
+ pub Fp: u64,
+ pub Lr: u64,
+ }
+
+ pub const ARM64_MAX_BREAKPOINTS: usize = 8;
+ pub const ARM64_MAX_WATCHPOINTS: usize = 2;
+
+ #[repr(C)]
+ pub struct ARM64_NT_NEON128 {
+ pub D: [f64; 2],
+ }
+}
+
+#[cfg(target_arch = "x86")]
+ffi! {
+ #[repr(C)]
+ pub struct CONTEXT {
+ pub ContextFlags: DWORD,
+ pub Dr0: DWORD,
+ pub Dr1: DWORD,
+ pub Dr2: DWORD,
+ pub Dr3: DWORD,
+ pub Dr6: DWORD,
+ pub Dr7: DWORD,
+ pub FloatSave: FLOATING_SAVE_AREA,
+ pub SegGs: DWORD,
+ pub SegFs: DWORD,
+ pub SegEs: DWORD,
+ pub SegDs: DWORD,
+ pub Edi: DWORD,
+ pub Esi: DWORD,
+ pub Ebx: DWORD,
+ pub Edx: DWORD,
+ pub Ecx: DWORD,
+ pub Eax: DWORD,
+ pub Ebp: DWORD,
+ pub Eip: DWORD,
+ pub SegCs: DWORD,
+ pub EFlags: DWORD,
+ pub Esp: DWORD,
+ pub SegSs: DWORD,
+ pub ExtendedRegisters: [u8; 512],
+ }
+
+ #[repr(C)]
+ pub struct FLOATING_SAVE_AREA {
+ pub ControlWord: DWORD,
+ pub StatusWord: DWORD,
+ pub TagWord: DWORD,
+ pub ErrorOffset: DWORD,
+ pub ErrorSelector: DWORD,
+ pub DataOffset: DWORD,
+ pub DataSelector: DWORD,
+ pub RegisterArea: [u8; 80],
+ pub Spare0: DWORD,
+ }
+}
+
+#[cfg(target_arch = "x86_64")]
+ffi! {
+ #[repr(C, align(8))]
+ pub struct CONTEXT {
+ pub P1Home: DWORDLONG,
+ pub P2Home: DWORDLONG,
+ pub P3Home: DWORDLONG,
+ pub P4Home: DWORDLONG,
+ pub P5Home: DWORDLONG,
+ pub P6Home: DWORDLONG,
+
+ pub ContextFlags: DWORD,
+ pub MxCsr: DWORD,
+
+ pub SegCs: WORD,
+ pub SegDs: WORD,
+ pub SegEs: WORD,
+ pub SegFs: WORD,
+ pub SegGs: WORD,
+ pub SegSs: WORD,
+ pub EFlags: DWORD,
+
+ pub Dr0: DWORDLONG,
+ pub Dr1: DWORDLONG,
+ pub Dr2: DWORDLONG,
+ pub Dr3: DWORDLONG,
+ pub Dr6: DWORDLONG,
+ pub Dr7: DWORDLONG,
+
+ pub Rax: DWORDLONG,
+ pub Rcx: DWORDLONG,
+ pub Rdx: DWORDLONG,
+ pub Rbx: DWORDLONG,
+ pub Rsp: DWORDLONG,
+ pub Rbp: DWORDLONG,
+ pub Rsi: DWORDLONG,
+ pub Rdi: DWORDLONG,
+ pub R8: DWORDLONG,
+ pub R9: DWORDLONG,
+ pub R10: DWORDLONG,
+ pub R11: DWORDLONG,
+ pub R12: DWORDLONG,
+ pub R13: DWORDLONG,
+ pub R14: DWORDLONG,
+ pub R15: DWORDLONG,
+
+ pub Rip: DWORDLONG,
+
+ pub FltSave: FLOATING_SAVE_AREA,
+
+ pub VectorRegister: [M128A; 26],
+ pub VectorControl: DWORDLONG,
+
+ pub DebugControl: DWORDLONG,
+ pub LastBranchToRip: DWORDLONG,
+ pub LastBranchFromRip: DWORDLONG,
+ pub LastExceptionToRip: DWORDLONG,
+ pub LastExceptionFromRip: DWORDLONG,
+ }
+
+ #[repr(C)]
+ pub struct M128A {
+ pub Low: u64,
+ pub High: i64,
+ }
+}
+
+#[repr(C)]
+#[cfg(target_arch = "x86_64")]
+#[derive(Copy, Clone)]
+pub struct FLOATING_SAVE_AREA {
+ _Dummy: [u8; 512],
+}
+
+#[cfg(target_arch = "arm")]
+ffi! {
+ // #[repr(C)]
+ // pub struct NEON128 {
+ // pub Low: ULONG64,
+ // pub High: LONG64,
+ // }
+
+ // pub type PNEON128 = *mut NEON128;
+
+ #[repr(C)]
+ pub struct CONTEXT_u {
+ // pub Q: [NEON128; 16],
+ pub D: [ULONG64; 32],
+ // pub S: [DWORD; 32],
+ }
+
+ pub const ARM_MAX_BREAKPOINTS: usize = 8;
+ pub const ARM_MAX_WATCHPOINTS: usize = 1;
+
+ #[repr(C)]
+ pub struct CONTEXT {
+ pub ContextFlags: DWORD,
+ pub R0: DWORD,
+ pub R1: DWORD,
+ pub R2: DWORD,
+ pub R3: DWORD,
+ pub R4: DWORD,
+ pub R5: DWORD,
+ pub R6: DWORD,
+ pub R7: DWORD,
+ pub R8: DWORD,
+ pub R9: DWORD,
+ pub R10: DWORD,
+ pub R11: DWORD,
+ pub R12: DWORD,
+ pub Sp: DWORD,
+ pub Lr: DWORD,
+ pub Pc: DWORD,
+ pub Cpsr: DWORD,
+ pub Fpsrc: DWORD,
+ pub Padding: DWORD,
+ pub u: CONTEXT_u,
+ pub Bvr: [DWORD; ARM_MAX_BREAKPOINTS],
+ pub Bcr: [DWORD; ARM_MAX_BREAKPOINTS],
+ pub Wvr: [DWORD; ARM_MAX_WATCHPOINTS],
+ pub Wcr: [DWORD; ARM_MAX_WATCHPOINTS],
+ pub Padding2: [DWORD; 2],
+ }
+} // IFDEF(arm)