linux_syscall/
linux-syscall.rs
1#![no_std]
58
59use linux_errno::Error;
60
61#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
63pub struct Syscall {
64 nr: u32,
65}
66
67impl Syscall {
68 #[inline]
69 pub const fn from_u32(nr: u32) -> Syscall {
70 Syscall { nr }
71 }
72}
73
74impl From<u32> for Syscall {
75 #[inline]
76 fn from(nr: u32) -> Syscall {
77 Syscall { nr }
78 }
79}
80
81impl From<Syscall> for u32 {
82 #[inline]
83 fn from(syscall: Syscall) -> u32 {
84 syscall.nr
85 }
86}
87
88pub trait Result {
90 fn check(&self) -> core::result::Result<(), Error>;
91}
92
93pub trait Result32: Result {
95 fn try_i32(&self) -> core::result::Result<i32, Error>;
96
97 fn try_u32(&self) -> core::result::Result<u32, Error>;
98}
99
100pub trait Result64: Result {
102 fn try_i64(&self) -> core::result::Result<i64, Error>;
103
104 fn try_u64(&self) -> core::result::Result<u64, Error>;
105}
106
107pub trait ResultPtr: Result {
109 fn try_ptr(&self) -> core::result::Result<*const (), Error>;
110
111 fn try_ptr_mut(&self) -> core::result::Result<*mut (), Error>;
112}
113
114pub trait ResultSize: Result {
116 fn try_isize(&self) -> core::result::Result<isize, Error>;
117
118 fn try_usize(&self) -> core::result::Result<usize, Error>;
119}
120
121macro_rules! single_register_result {
122 ($arch_result:ty) => {
123 use linux_errno::Error;
124
125 impl $crate::Result for $arch_result {
126 #[inline]
127 fn check(&self) -> core::result::Result<(), Error> {
128 if self.0 >= self::MAX_ERRNO {
129 return Err(new_err(self.0 as u16));
130 }
131 Ok(())
132 }
133 }
134
135 #[inline]
136 #[cold]
137 const fn new_err(truncated_register: u16) -> Error {
138 let (err, _) = truncated_register.overflowing_neg();
139 unsafe { Error::new_unchecked(err) }
140 }
141
142 impl $crate::ResultPtr for $arch_result {
143 #[inline]
144 fn try_ptr(&self) -> core::result::Result<*const (), Error> {
145 $crate::Result::check(self)?;
146 Ok(self.0 as *const ())
147 }
148
149 #[inline]
150 fn try_ptr_mut(&self) -> core::result::Result<*mut (), Error> {
151 $crate::Result::check(self)?;
152 Ok(self.0 as *mut ())
153 }
154 }
155
156 impl<T> core::convert::TryFrom<$arch_result> for *const T {
157 type Error = Error;
158
159 #[inline]
160 fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
161 $crate::ResultPtr::try_ptr(&rc).map(|p| p.cast())
162 }
163 }
164
165 impl<T> core::convert::TryFrom<$arch_result> for *mut T {
166 type Error = Error;
167
168 #[inline]
169 fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
170 $crate::ResultPtr::try_ptr_mut(&rc).map(|p| p.cast())
171 }
172 }
173
174 impl $crate::ResultSize for $arch_result {
175 #[inline]
176 fn try_isize(&self) -> core::result::Result<isize, Error> {
177 $crate::Result::check(self)?;
178 Ok(self.0 as isize)
179 }
180
181 #[inline]
182 fn try_usize(&self) -> core::result::Result<usize, Error> {
183 $crate::Result::check(self)?;
184 Ok(self.0 as usize)
185 }
186 }
187
188 impl core::convert::TryFrom<$arch_result> for isize {
189 type Error = Error;
190
191 #[inline]
192 fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
193 $crate::ResultSize::try_isize(&rc)
194 }
195 }
196
197 impl core::convert::TryFrom<$arch_result> for usize {
198 type Error = Error;
199
200 #[inline]
201 fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
202 $crate::ResultSize::try_usize(&rc)
203 }
204 }
205 };
206}
207
208#[cfg(any(target_pointer_width = "32", doc))]
209macro_rules! single_register_result32 {
210 ($arch_result:ty) => {
211 single_register_result!($arch_result);
212
213 const MAX_ERRNO: u32 = (-4095i32) as u32;
214
215 impl $crate::Result32 for $arch_result {
216 #[inline]
217 fn try_i32(&self) -> core::result::Result<i32, Error> {
218 $crate::Result::check(self)?;
219 Ok(self.0 as i32)
220 }
221
222 #[inline]
223 fn try_u32(&self) -> core::result::Result<u32, Error> {
224 $crate::Result::check(self)?;
225 Ok(self.0)
226 }
227 }
228
229 impl core::convert::TryFrom<$arch_result> for i32 {
230 type Error = Error;
231
232 #[inline]
233 fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
234 $crate::Result32::try_i32(&rc)
235 }
236 }
237
238 impl core::convert::TryFrom<$arch_result> for u32 {
239 type Error = Error;
240
241 #[inline]
242 fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
243 $crate::Result32::try_u32(&rc)
244 }
245 }
246 };
247}
248
249#[cfg(any(target_pointer_width = "64", doc))]
250macro_rules! single_register_result64 {
251 ($arch_result:ty) => {
252 single_register_result!($arch_result);
253
254 const MAX_ERRNO: u64 = (-4095i64) as u64;
255
256 impl $crate::Result64 for $arch_result {
257 #[inline]
258 fn try_i64(&self) -> core::result::Result<i64, Error> {
259 $crate::Result::check(self)?;
260 Ok(self.0 as i64)
261 }
262
263 #[inline]
264 fn try_u64(&self) -> core::result::Result<u64, Error> {
265 $crate::Result::check(self)?;
266 Ok(self.0)
267 }
268 }
269
270 impl core::convert::TryFrom<$arch_result> for i64 {
271 type Error = Error;
272
273 #[inline]
274 fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
275 $crate::Result64::try_i64(&rc)
276 }
277 }
278
279 impl core::convert::TryFrom<$arch_result> for u64 {
280 type Error = Error;
281
282 #[inline]
283 fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
284 $crate::Result64::try_u64(&rc)
285 }
286 }
287 };
288}
289
290macro_rules! syscall_constants {
291 ( $( $name:ident = $value:literal , )+ ) => {
292 use $crate::Syscall;
293 $(
294 pub const $name: Syscall = Syscall::from_u32($value);
295 )*
296 };
297}
298
299pub mod arch {
301 #[cfg(any(target_arch = "aarch64", doc))]
303 pub mod aarch64 {
304 mod syscall_asm;
305 pub use self::syscall_asm::Result;
306
307 pub(crate) mod syscall_tbl;
308 pub use self::syscall_tbl::*;
309 }
310
311 #[cfg(any(target_arch = "arm", doc))]
313 pub mod arm {
314 mod syscall_asm;
315 pub use self::syscall_asm::Result;
316
317 pub(crate) mod syscall_tbl;
318 pub use self::syscall_tbl::*;
319 }
320
321 #[cfg(any(target_arch = "riscv64", doc))]
323 pub mod riscv64 {
324 mod syscall_asm;
325 pub use self::syscall_asm::Result;
326
327 pub(crate) mod syscall_tbl;
328 pub use self::syscall_tbl::*;
329 }
330
331 #[cfg(any(target_arch = "s390x", doc))]
333 pub mod s390x {
334 mod syscall_asm;
335 pub use self::syscall_asm::Result;
336
337 pub(crate) mod syscall_tbl;
338 pub use self::syscall_tbl::*;
339 }
340
341 #[cfg(any(target_arch = "x86", doc))]
343 pub mod x86 {
344 mod syscall_asm;
345 pub use self::syscall_asm::Result;
346
347 pub(crate) mod syscall_tbl;
348 pub use self::syscall_tbl::*;
349 }
350
351 #[cfg(any(target_arch = "x86_64", doc))]
353 pub mod x86_64 {
354 mod syscall_asm;
355 pub use self::syscall_asm::Result;
356
357 pub(crate) mod syscall_tbl;
358 pub use self::syscall_tbl::*;
359 }
360}
361
362#[cfg(target_arch = "arm")]
363pub use crate::arch::arm::syscall_tbl::*;
364
365#[cfg(target_arch = "aarch64")]
366pub use crate::arch::aarch64::syscall_tbl::*;
367
368#[cfg(target_arch = "riscv64")]
369pub use crate::arch::riscv64::syscall_tbl::*;
370
371#[cfg(target_arch = "s390x")]
372pub use crate::arch::s390x::syscall_tbl::*;
373
374#[cfg(target_arch = "x86")]
375pub use crate::arch::x86::syscall_tbl::*;
376
377#[cfg(target_arch = "x86_64")]
378pub use crate::arch::x86_64::syscall_tbl::*;
379
380#[cfg(doc)]
415#[macro_export]
416macro_rules! syscall {
417 ($syscall:expr $(,)?) => {};
418 ($syscall:expr, $a1:expr $(,)?) => {};
419 ($syscall:expr, $a1:expr, $a2:expr $(,)?) => {};
420 ($syscall:expr, $a1:expr, $a2:expr, $a3:expr $(,)?) => {};
421 ($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr $(,)?) => {};
422 ($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr $(,)?) => {};
423 ($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr $(,)?) => {};
424}