osi/ffi/abi.rs
1//! Common ABIs
2//!
3//! This module provides type definitions for a set of platform ABIs. This can
4//! be used to introspect or synthesize objects of foreign platform ABIs.
5//!
6//! The individual sub-modules represent known ABIs of different platforms.
7//! Each module exports the same set of symbols. Preferably, this would be
8//! represented by a trait, which is implemented by each ABI. Unfortunately,
9//! Rust traits are too limited right now to be suitable here (most
10//! importantly, they do not allow constant methods). Hence, we instead export
11//! a set of modules.
12//!
13//! [`native`] exports a special ABI which always represents the ABI of the
14//! target platform and uses the Rust native data-types (i.e., it uses the
15//! builtin primitive integers like `u16`, `i64`, and `usize`). Use this ABI
16//! to get a native Rust experience. This is suitable if foreign data access
17//! is not needed.
18//!
19//! [`auto`] is an alias of one of the other ABIs and represents the target
20//! platform. Unlike [`native`], this does not necessarily use native Rust
21//! data-types, but is a real alias to one of the other fixed definitions of
22//! platform ABIs.
23//!
24//! ## Foreign ABI
25//!
26//! When accessing foreign ABIs, care must be taken to ensure datatypes have
27//! the correct layout. The builtin primitives like `u32`, `i64`, etc., always
28//! follow the native ABI, and thus cannot be reliably used to represent
29//! data-structures of foreign ABIs. The utilities in this module can be used
30//! instead.
31//!
32//! As an example, imagine a 32-bit Linux process that visualizes core-dumps of
33//! crashed processes. If that process needs to read core-dumps of a 64-bit
34//! system, it likely cannot use `u64` to model the structures used in that
35//! core-dump, since it will have an alignment of 4, rather than the original
36//! alignment of 8. Instead, [`crate::ffi::Integer`] can be used to model the
37//! exact ABI of the foreign system.
38
39// Little-endian integer with the given native type and alignment.
40type Le<Native, Alignment> = crate::ffi::Integer<
41 crate::ffi::LittleEndian<Native>,
42 Alignment,
43>;
44
45// This module is imported by all ABIs and provides default symbols valid on
46// all targets.
47mod shared {
48 /// Creates a number by converting the input value from native
49 /// representation into the representation of the target type.
50 ///
51 /// This is the preferred method to initialize foreign ordered datatypes
52 /// with a logical value. This method will take care of endian conversion,
53 /// such that a machine of the foreign platform would read the same logical
54 /// value.
55 ///
56 /// If this method is used to initialize non-foreign (native) datatypes,
57 /// it will be an identity function and return the input unchanged.
58 ///
59 /// This works with any type that implements [`crate::ffi::NativeEndian`].
60 pub const fn num<Endian: crate::ffi::NativeEndian<Raw>, Raw: Copy>(r: Raw) -> Endian {
61 crate::ffi::from_native(r)
62 }
63}
64
65/// # Native ABI
66///
67/// The native ABI uses the native primitive types of Rust, and thus represents
68/// the ABI of the compilation target platform. This is the preferred ABI to
69/// use when interfacing with native platform APIs, rather than foreign
70/// platform APIs.
71///
72/// The types of this ABI directly alias Rust primitive types like `u16` or
73/// `i64`. Hence, these should integrate nicely into native Rust code bases and
74/// no special handling is needed.
75pub mod native {
76 pub type I8 = i8;
77 pub type I16 = i16;
78 pub type I32 = i32;
79 pub type I64 = i64;
80 pub type I128 = i128;
81 pub type Isize = isize;
82
83 pub type U8 = u8;
84 pub type U16 = u16;
85 pub type U32 = u32;
86 pub type U64 = u64;
87 pub type U128 = u128;
88 pub type Usize = usize;
89
90 pub type F32 = f32;
91 pub type F64 = f64;
92
93 pub type Addr = core::num::NonZeroUsize;
94 pub type Ptr<Target> = core::ptr::NonNull<Target>;
95
96 pub use super::shared::*;
97}
98
99/// # System-V x86 ABI
100///
101/// This ABI represents the 32-bit ABI of System-V for x86 systems. It is used
102/// by most UNIX compatible systems, including Linux.
103pub mod x86_sysv {
104 use crate::align;
105
106 pub type I8 = super::Le<i8, align::AlignAs<1>>;
107 pub type I16 = super::Le<i16, align::AlignAs<2>>;
108 pub type I32 = super::Le<i32, align::AlignAs<4>>;
109 pub type I64 = super::Le<i64, align::AlignAs<4>>;
110 pub type I128 = super::Le<i128, align::AlignAs<4>>;
111 pub type Isize = super::Le<i32, align::AlignAs<4>>;
112
113 pub type U8 = super::Le<u8, align::AlignAs<1>>;
114 pub type U16 = super::Le<u16, align::AlignAs<2>>;
115 pub type U32 = super::Le<u32, align::AlignAs<4>>;
116 pub type U64 = super::Le<u64, align::AlignAs<4>>;
117 pub type U128 = super::Le<u128, align::AlignAs<4>>;
118 pub type Usize = super::Le<u32, align::AlignAs<4>>;
119
120 pub type F32 = super::Le<f32, align::AlignAs<4>>;
121 pub type F64 = super::Le<f64, align::AlignAs<4>>;
122
123 pub type Addr = super::Le<core::num::NonZeroU32, align::AlignAs<4>>;
124 pub type Ptr<Target> = crate::ffi::Pointer<Addr, Target>;
125
126 pub use super::shared::*;
127}
128
129/// # System-V x86-64 ABI
130///
131/// This ABI represents the 64-bit ABI of System-V for x86 systems. It is used
132/// by most UNIX compatible systems, including Linux.
133pub mod x86_64_sysv {
134 use crate::align;
135
136 pub type I8 = super::Le<i8, align::AlignAs<1>>;
137 pub type I16 = super::Le<i16, align::AlignAs<2>>;
138 pub type I32 = super::Le<i32, align::AlignAs<4>>;
139 pub type I64 = super::Le<i64, align::AlignAs<8>>;
140 pub type I128 = super::Le<i128, align::AlignAs<16>>;
141 pub type Isize = super::Le<i64, align::AlignAs<8>>;
142
143 pub type U8 = super::Le<u8, align::AlignAs<1>>;
144 pub type U16 = super::Le<u16, align::AlignAs<2>>;
145 pub type U32 = super::Le<u32, align::AlignAs<4>>;
146 pub type U64 = super::Le<u64, align::AlignAs<8>>;
147 pub type U128 = super::Le<u128, align::AlignAs<16>>;
148 pub type Usize = super::Le<u64, align::AlignAs<8>>;
149
150 pub type F32 = super::Le<f32, align::AlignAs<4>>;
151 pub type F64 = super::Le<f64, align::AlignAs<8>>;
152
153 pub type Addr = super::Le<core::num::NonZeroU64, align::AlignAs<8>>;
154 pub type Ptr<Target> = crate::ffi::Pointer<Addr, Target>;
155
156 pub use super::shared::*;
157}
158
159#[cfg(all(
160 target_arch = "x86",
161 target_family = "unix",
162))]
163pub use x86_sysv as auto;
164
165#[cfg(all(
166 target_arch = "x86_64",
167 target_family = "unix",
168))]
169pub use x86_64_sysv as auto;
170
171#[cfg(all(
172 target_arch = "x86",
173 target_env = "msvc",
174 target_family = "windows",
175))]
176pub use x86_win as auto;
177
178#[cfg(all(
179 target_arch = "x86_64",
180 target_env = "msvc",
181 target_family = "windows",
182))]
183pub use x86_64_win as auto;