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