1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//! Utilities to check against C signatures.
#![allow(unused_macros)]
#![allow(dead_code)]
/// Cast the given pointer to another type, similarly to calling `cast()` on
/// it, while verifying that the layout of the pointee stays the same after the
/// cast.
macro_rules! checked_cast {
($ptr:expr) => {{
let src_ptr = $ptr;
let target_ptr = src_ptr.cast();
#[allow(unnecessary_transmutes)]
if false {
let target = crate::use_libc::Pad::new(core::ptr::read(target_ptr));
// Uses the fact that the compiler checks for size equality,
// when transmuting between types.
let size_check = core::mem::transmute(core::ptr::read(src_ptr));
target.compare_size(size_check);
let align_check =
core::mem::transmute(crate::use_libc::Pad::new(core::ptr::read(src_ptr)));
target.compare_alignment(align_check);
}
target_ptr
}};
}
/// A macro for ensuring that the `libc` crate signature for a function matches
/// the signature that our implementation of it is using.
///
/// # Example
///
/// ```no_compile
/// #[no_mangle]
/// unsafe extern "C" fn strlen(s: *const c_char) -> usize {
/// libc!(libc::strlen(s));
/// // ...
/// }
/// ```
///
/// This will elicit a compile-time error if the signature doesn't match.
macro_rules! libc {
($e:expr) => {
#[allow(unreachable_code)]
#[allow(clippy::diverging_sub_expression)]
if false {
#[allow(unused_imports)]
use crate::use_libc::*;
return $e;
}
};
}
/// This is used to check that our type definition matches the layout of the
/// corresponding libc type.
#[cfg(all(feature = "take-charge", feature = "thread"))]
macro_rules! libc_type {
($name:ident, $libc:ident) => {
const _: () = {
if core::mem::size_of::<$name>() != core::mem::size_of::<libc::$libc>() {
panic!();
}
if core::mem::align_of::<$name>() != core::mem::align_of::<libc::$libc>() {
panic!();
}
};
};
}
/// A struct that adds `align_of<T>` padding bytes to type `T`.
///
/// Based on the rules of C struct alignment:
/// * `align_of<Pad<T>> == max(align_of<T>, align_of<u8>) == align_of<T>`
/// * `size_of<Pad<T>> / align_of<Pad<T>> == ciel( (size_of<T> + size_of<u8>) /
/// align_of<Pad<T>>)`
/// * `size_of<T> % align_of<T> == 0`
///
/// Therefore `size_of<Pad<T>> == size_of<T> + align_of<T>`.
#[repr(C)]
pub(crate) struct Pad<T> {
field: T,
force_padding: u8,
}
impl<T> Pad<T> {
pub unsafe fn new(v: T) -> Self {
Pad {
field: v,
force_padding: 0,
}
}
/// Used to check that `size_of<T> == size_of<U>` with `transmute`.
pub fn compare_size(&self, _v: T) {}
/// Used to check that `size_of<Pad<T>> == size_of<Pad<U>>` with
/// `transmute`.
///
/// Since `size_of<Pad<T>> == size_of<T> + align_of<T>`,
/// if `size_of<T> == size_of<U>` then `align_of<T> == align_of<U>`.
pub fn compare_alignment(&self, _pad: Pad<T>) {}
}