| //! 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, unused)] |
| |
| 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; |
| pub use self::winapi::PEXCEPTION_ROUTINE; |
| #[cfg(target_pointer_width = "64")] |
| pub use self::winapi::PKNONVOLATILE_CONTEXT_POINTERS; |
| |
| 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::*; |
| pub use winapi::um::winnls::*; |
| pub use winapi::um::stringapiset::*; |
| |
| // Work around winapi not having this function on aarch64. |
| #[cfg(target_arch = "aarch64")] |
| #[link(name = "kernel32")] |
| extern "system" { |
| pub fn RtlVirtualUnwind( |
| HandlerType: ULONG, |
| ImageBase: ULONG64, |
| ControlPc: ULONG64, |
| FunctionEntry: PRUNTIME_FUNCTION, |
| ContextRecord: PCONTEXT, |
| HandlerData: *mut PVOID, |
| EstablisherFrame: PULONG64, |
| ContextPointers: PKNONVOLATILE_CONTEXT_POINTERS |
| ) -> PEXCEPTION_ROUTINE; |
| } |
| |
| // winapi doesn't have this type |
| pub type PENUMLOADED_MODULES_CALLBACKW64 = Option< |
| unsafe extern "system" fn( |
| modulename: PCWSTR, |
| modulebase: DWORD64, |
| modulesize: ULONG, |
| usercontext: PVOID, |
| ) -> BOOL, |
| >; |
| } |
| } 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; |
| pub type PEXCEPTION_ROUTINE = *mut c_void; |
| #[cfg(target_pointer_width = "64")] |
| pub type PKNONVOLATILE_CONTEXT_POINTERS = *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)*); |
| ); |
| |
| ($(#[$meta:meta])* extern "system" { $(pub fn $name:ident($($args:tt)*) -> $ret:ty;)* } $($rest:tt)*) => ( |
| $(#[$meta])* 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; |
| let _ = x; |
| x = winapi::$name; |
| let _ = 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 PENUMLOADED_MODULES_CALLBACKW64 = Option<unsafe extern "system" fn(modulename: PCWSTR, modulebase: DWORD64, modulesize: ULONG, usercontext: PVOID) -> BOOL>; |
| 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 const CP_UTF8: u32 = 65001; |
| |
| 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 USHORT = 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; |
| pub type PULONG = *mut ULONG; |
| pub type PULONG64 = *mut ULONG64; |
| |
| #[link(name = "kernel32")] |
| 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 GetCurrentProcessId() -> DWORD; |
| pub fn CloseHandle(h: HANDLE) -> BOOL; |
| 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; |
| pub fn lstrlenW(lpstring: PCWSTR) -> i32; |
| pub fn WideCharToMultiByte( |
| codepage: u32, |
| dwflags: u32, |
| lpwidecharstr: PCWSTR, |
| cchwidechar: i32, |
| lpmultibytestr: *mut i8, |
| cbmultibyte: i32, |
| lpdefaultchar: *const i8, |
| lpuseddefaultchar: *mut BOOL |
| ) -> i32; |
| } |
| } |
| |
| #[cfg(any( |
| target_arch = "x86_64", |
| target_arch = "aarch64", |
| target_arch = "arm64ec" |
| ))] |
| ffi! { |
| #[link(name = "kernel32")] |
| extern "system" { |
| pub fn RtlVirtualUnwind( |
| HandlerType: ULONG, |
| ImageBase: ULONG64, |
| ControlPc: ULONG64, |
| FunctionEntry: PRUNTIME_FUNCTION, |
| ContextRecord: PCONTEXT, |
| HandlerData: *mut PVOID, |
| EstablisherFrame: PULONG64, |
| ContextPointers: PKNONVOLATILE_CONTEXT_POINTERS |
| ) -> PEXCEPTION_ROUTINE; |
| } |
| } |
| |
| #[cfg(target_pointer_width = "64")] |
| ffi! { |
| #[link(name = "kernel32")] |
| 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(any(target_arch = "x86_64", target_arch = "arm64ec"))] |
| 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(any(target_arch = "x86_64", target_arch = "arm64ec"))] |
| #[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) |