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