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