linux_syscall/
linux-syscall.rs#![no_std]
use linux_errno::Error;
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Syscall {
nr: u32,
}
impl Syscall {
#[inline]
pub const fn from_u32(nr: u32) -> Syscall {
Syscall { nr }
}
}
impl From<u32> for Syscall {
#[inline]
fn from(nr: u32) -> Syscall {
Syscall { nr }
}
}
impl From<Syscall> for u32 {
#[inline]
fn from(syscall: Syscall) -> u32 {
syscall.nr
}
}
pub trait Result {
fn check(&self) -> core::result::Result<(), Error>;
}
pub trait Result32: Result {
fn try_i32(&self) -> core::result::Result<i32, Error>;
fn try_u32(&self) -> core::result::Result<u32, Error>;
}
pub trait Result64: Result {
fn try_i64(&self) -> core::result::Result<i64, Error>;
fn try_u64(&self) -> core::result::Result<u64, Error>;
}
pub trait ResultPtr: Result {
fn try_ptr(&self) -> core::result::Result<*const (), Error>;
fn try_ptr_mut(&self) -> core::result::Result<*mut (), Error>;
}
pub trait ResultSize: Result {
fn try_isize(&self) -> core::result::Result<isize, Error>;
fn try_usize(&self) -> core::result::Result<usize, Error>;
}
macro_rules! single_register_result {
($arch_result:ty) => {
use linux_errno::Error;
impl $crate::Result for $arch_result {
#[inline]
fn check(&self) -> core::result::Result<(), Error> {
if self.0 >= self::MAX_ERRNO {
return Err(new_err(self.0 as u16));
}
Ok(())
}
}
#[inline]
#[cold]
const fn new_err(truncated_register: u16) -> Error {
let (err, _) = truncated_register.overflowing_neg();
unsafe { Error::new_unchecked(err) }
}
impl $crate::ResultPtr for $arch_result {
#[inline]
fn try_ptr(&self) -> core::result::Result<*const (), Error> {
$crate::Result::check(self)?;
Ok(self.0 as *const ())
}
#[inline]
fn try_ptr_mut(&self) -> core::result::Result<*mut (), Error> {
$crate::Result::check(self)?;
Ok(self.0 as *mut ())
}
}
impl<T> core::convert::TryFrom<$arch_result> for *const T {
type Error = Error;
#[inline]
fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
$crate::ResultPtr::try_ptr(&rc).map(|p| p.cast())
}
}
impl<T> core::convert::TryFrom<$arch_result> for *mut T {
type Error = Error;
#[inline]
fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
$crate::ResultPtr::try_ptr_mut(&rc).map(|p| p.cast())
}
}
impl $crate::ResultSize for $arch_result {
#[inline]
fn try_isize(&self) -> core::result::Result<isize, Error> {
$crate::Result::check(self)?;
Ok(self.0 as isize)
}
#[inline]
fn try_usize(&self) -> core::result::Result<usize, Error> {
$crate::Result::check(self)?;
Ok(self.0 as usize)
}
}
impl core::convert::TryFrom<$arch_result> for isize {
type Error = Error;
#[inline]
fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
$crate::ResultSize::try_isize(&rc)
}
}
impl core::convert::TryFrom<$arch_result> for usize {
type Error = Error;
#[inline]
fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
$crate::ResultSize::try_usize(&rc)
}
}
};
}
#[cfg(any(target_pointer_width = "32", doc))]
macro_rules! single_register_result32 {
($arch_result:ty) => {
single_register_result!($arch_result);
const MAX_ERRNO: u32 = (-4095i32) as u32;
impl $crate::Result32 for $arch_result {
#[inline]
fn try_i32(&self) -> core::result::Result<i32, Error> {
$crate::Result::check(self)?;
Ok(self.0 as i32)
}
#[inline]
fn try_u32(&self) -> core::result::Result<u32, Error> {
$crate::Result::check(self)?;
Ok(self.0)
}
}
impl core::convert::TryFrom<$arch_result> for i32 {
type Error = Error;
#[inline]
fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
$crate::Result32::try_i32(&rc)
}
}
impl core::convert::TryFrom<$arch_result> for u32 {
type Error = Error;
#[inline]
fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
$crate::Result32::try_u32(&rc)
}
}
};
}
#[cfg(any(target_pointer_width = "64", doc))]
macro_rules! single_register_result64 {
($arch_result:ty) => {
single_register_result!($arch_result);
const MAX_ERRNO: u64 = (-4095i64) as u64;
impl $crate::Result64 for $arch_result {
#[inline]
fn try_i64(&self) -> core::result::Result<i64, Error> {
$crate::Result::check(self)?;
Ok(self.0 as i64)
}
#[inline]
fn try_u64(&self) -> core::result::Result<u64, Error> {
$crate::Result::check(self)?;
Ok(self.0)
}
}
impl core::convert::TryFrom<$arch_result> for i64 {
type Error = Error;
#[inline]
fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
$crate::Result64::try_i64(&rc)
}
}
impl core::convert::TryFrom<$arch_result> for u64 {
type Error = Error;
#[inline]
fn try_from(rc: $arch_result) -> core::result::Result<Self, Error> {
$crate::Result64::try_u64(&rc)
}
}
};
}
macro_rules! syscall_constants {
( $( $name:ident = $value:literal , )+ ) => {
use $crate::Syscall;
$(
pub const $name: Syscall = Syscall::from_u32($value);
)*
};
}
pub mod arch {
#[cfg(any(target_arch = "aarch64", doc))]
pub mod aarch64 {
mod syscall_asm;
pub use self::syscall_asm::Result;
pub(crate) mod syscall_tbl;
pub use self::syscall_tbl::*;
}
#[cfg(any(target_arch = "arm", doc))]
pub mod arm {
mod syscall_asm;
pub use self::syscall_asm::Result;
pub(crate) mod syscall_tbl;
pub use self::syscall_tbl::*;
}
#[cfg(any(target_arch = "riscv64", doc))]
pub mod riscv64 {
mod syscall_asm;
pub use self::syscall_asm::Result;
pub(crate) mod syscall_tbl;
pub use self::syscall_tbl::*;
}
#[cfg(any(target_arch = "x86", doc))]
pub mod x86 {
mod syscall_asm;
pub use self::syscall_asm::Result;
pub(crate) mod syscall_tbl;
pub use self::syscall_tbl::*;
}
#[cfg(any(target_arch = "x86_64", doc))]
pub mod x86_64 {
mod syscall_asm;
pub use self::syscall_asm::Result;
pub(crate) mod syscall_tbl;
pub use self::syscall_tbl::*;
}
}
#[cfg(target_arch = "arm")]
pub use crate::arch::arm::syscall_tbl::*;
#[cfg(target_arch = "aarch64")]
pub use crate::arch::aarch64::syscall_tbl::*;
#[cfg(target_arch = "riscv64")]
pub use crate::arch::riscv64::syscall_tbl::*;
#[cfg(target_arch = "x86")]
pub use crate::arch::x86::syscall_tbl::*;
#[cfg(target_arch = "x86_64")]
pub use crate::arch::x86_64::syscall_tbl::*;
#[cfg(doc)]
#[macro_export]
macro_rules! syscall {
($syscall:expr $(,)?) => {};
($syscall:expr, $a1:expr $(,)?) => {};
($syscall:expr, $a1:expr, $a2:expr $(,)?) => {};
($syscall:expr, $a1:expr, $a2:expr, $a3:expr $(,)?) => {};
($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr $(,)?) => {};
($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr $(,)?) => {};
($syscall:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr $(,)?) => {};
}