From 82652914c933f50931338e4bbc924013c358fe71 Mon Sep 17 00:00:00 2001 From: edef Date: Sat, 30 Jul 2022 19:29:15 +0000 Subject: ripple/minitrace/syscall_abi: init Factor out the rather sprawling syscall ABI definitions from the main program. The macros, argument parsing, and file descriptor code get some space to breathe too. Change-Id: I0aa01b6b94e4d4b770bb9ef59926e2236c50b258 --- ripple/minitrace/src/main.rs | 404 +---------------------------- ripple/minitrace/src/syscall_abi/arg.rs | 84 ++++++ ripple/minitrace/src/syscall_abi/fd.rs | 62 +++++ ripple/minitrace/src/syscall_abi/macros.rs | 161 ++++++++++++ ripple/minitrace/src/syscall_abi/mod.rs | 127 +++++++++ 5 files changed, 437 insertions(+), 401 deletions(-) create mode 100644 ripple/minitrace/src/syscall_abi/arg.rs create mode 100644 ripple/minitrace/src/syscall_abi/fd.rs create mode 100644 ripple/minitrace/src/syscall_abi/macros.rs create mode 100644 ripple/minitrace/src/syscall_abi/mod.rs diff --git a/ripple/minitrace/src/main.rs b/ripple/minitrace/src/main.rs index c7fb369..74bfee2 100644 --- a/ripple/minitrace/src/main.rs +++ b/ripple/minitrace/src/main.rs @@ -3,6 +3,7 @@ // SPDX-License-Identifier: OSL-3.0 use { + crate::syscall_abi::{AtFlags, DirFd, MapFlags, SyscallEntry}, anyhow::{bail, Context, Result}, bitflags::bitflags, nix::{ @@ -17,10 +18,9 @@ use { unistd::Pid, }, std::{ - convert::TryInto, env, ffi::CString, - fmt::{self, Debug}, + fmt::Debug, fs::{self, File}, io::{self, BufRead, Seek, SeekFrom}, os::unix::process::CommandExt, @@ -29,6 +29,7 @@ use { }; mod maps_file; +mod syscall_abi; // TODO(edef): consider implementing this in terms of TID? // tgids are a strict subset of tids @@ -178,272 +179,6 @@ impl Process { } } -macro_rules! define_syscalls { - (enum $SyscallEntry:ident { - $(fn $syscall:ident ( $($arg:ident : $Arg:ty),* ) -> $Ret:ty = $nr:literal ;)* - }) => { - #[derive(Debug, Clone)] - #[allow(non_camel_case_types)] - // TODO(edef): re-enable dead_code lint when we start fully interpreting syscall args - #[allow(dead_code)] - enum $SyscallEntry { - $($syscall { - $($arg : $Arg),* - }),* - } - - impl $SyscallEntry { - fn from_regs(process: &Process, regs: libc::user_regs_struct) -> Result<$SyscallEntry> { - Ok(match (regs.orig_rax, [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9]) { - $( - ($nr, [$($arg,)* ..]) => $SyscallEntry::$syscall { - $($arg: match ProcessSyscallArg::try_from_process_reg(process, $arg) { - Some(x) => x, - None => bail!("couldn't parse {}(2) {}: {:#08x}", stringify!($syscall), stringify!($arg), $arg) - }),* - }, - )* - (n, _) => bail!("unknown syscall number {n}") - }) - } - } - } -} - -#[cfg(test)] -fn libc_check( - item: &'static str, - (our_name, our_value): (&'static str, T), - (libc_name, libc_value): (&'static str, T), -) { - match () { - _ if libc_name.ends_with(our_name) => {} - _ if libc_name.starts_with(&format!("{our_name}_")) => {} - () => panic!("{libc_name} doesn't match {our_name}"), - } - - assert!( - our_value == libc_value, - "{item}::{our_name} ({our_value:#x}) != libc::{libc_name} ({libc_value:#x})", - ); -} - -macro_rules! syscall_bitflags { - ( - $( - struct $BitFlags:ident: $T:ty { - $( - const $FLAG:ident = $value:expr => $LIBC_FLAG:ident; - )* - } - )* - ) => { - #[test] - fn verify_syscall_bitflags() { - $( - $BitFlags::verify(); - )* - } - - $( - bitflags! { - struct $BitFlags: $T { - $( - const $FLAG = $value; - )* - } - } - - impl $BitFlags { - #[cfg(test)] - fn verify() { - $( - libc_check( - stringify!($BitFlags), - (stringify!($FLAG), Self::$FLAG.bits()), - (stringify!($LIBC_FLAG), libc::$LIBC_FLAG) - ); - )* - } - } - - impl SyscallArg for $BitFlags { - fn try_from_reg(reg: u64) -> Option { - SyscallArg::try_from_reg(reg).and_then(Self::from_bits) - } - } - )* - }; -} - -macro_rules! syscall_enums { - ( - $( - enum $Enum:ident: $T:ty { - $( - $VARIANT:ident = $value:literal $(=> $LIBC_VALUE:ident)?, - )* - } - )* - ) => { - #[test] - fn verify_syscall_enums() { - $( - $Enum::verify(); - )* - } - - $( - #[derive(Debug, Copy, Clone, Eq, PartialEq)] - #[allow(non_camel_case_types)] - enum $Enum { - $($VARIANT = $value),* - } - - impl SyscallArg for $Enum { - fn try_from_reg(reg: u64) -> Option { - let reg = <$T as SyscallArg>::try_from_reg(reg)?; - Some(match reg { - $( - $value => $Enum::$VARIANT, - )* - _ => return None - }) - } - } - - impl $Enum { - #[cfg(test)] - fn verify() { - $( - $( - libc_check( - stringify!($Enum), - (stringify!($VARIANT), Self::$VARIANT as $T), - (stringify!($LIBC_VALUE), libc::$LIBC_VALUE) - ); - )? - )* - } - } - )* - }; -} - -trait ProcessSyscallArg: Sized { - fn try_from_process_reg(process: &Process, reg: u64) -> Option; -} - -impl ProcessSyscallArg for CString { - fn try_from_process_reg(process: &Process, reg: u64) -> Option { - process.read_mem_cstr(reg).ok() - } -} - -impl ProcessSyscallArg for T { - fn try_from_process_reg(_process: &Process, reg: u64) -> Option { - SyscallArg::try_from_reg(reg) - } -} - -trait SyscallArg: Sized { - fn try_from_reg(reg: u64) -> Option; -} - -impl SyscallArg for u16 { - fn try_from_reg(reg: u64) -> Option { - reg.try_into().ok() - } -} - -impl SyscallArg for u32 { - fn try_from_reg(reg: u64) -> Option { - reg.try_into().ok() - } -} - -impl SyscallArg for u64 { - fn try_from_reg(reg: u64) -> Option { - Some(reg) - } -} - -impl SyscallArg for i32 { - fn try_from_reg(reg: u64) -> Option { - Some(u32::try_from(reg).ok()? as i32) - } -} - -impl SyscallArg for *mut i32 { - fn try_from_reg(reg: u64) -> Option { - Some(usize::try_from_reg(reg)? as *mut i32) - } -} - -impl SyscallArg for usize { - fn try_from_reg(reg: u64) -> Option { - reg.try_into().ok() - } -} - -impl SyscallArg for *const u8 { - fn try_from_reg(reg: u64) -> Option { - Some(usize::try_from_reg(reg)? as *const u8) - } -} - -impl SyscallArg for *mut u8 { - fn try_from_reg(reg: u64) -> Option { - Some(usize::try_from_reg(reg)? as *mut u8) - } -} - -type SigAction = (); -type SysInfo = (); -type Tms = (); -type Stat = (); -type RobustListHead = (); -type RLimit64 = (); - -impl SyscallArg for *mut () { - fn try_from_reg(reg: u64) -> Option { - Some(usize::try_from_reg(reg)? as *mut ()) - } -} - -impl SyscallArg for *const () { - fn try_from_reg(reg: u64) -> Option { - Some(usize::try_from_reg(reg)? as *const ()) - } -} - -define_syscalls! { - enum SyscallEntry { - fn read(fd: FileDesc, buf: *mut u8, count: usize) -> i64 = 0; - fn write(fd: FileDesc, buf: *const u8, count: usize) -> i64 = 1; - fn close(fd: FileDesc) -> i64 = 3; - fn mmap(addr: u64, len: u64, prot: ProtFlags, flags: MapFlags, fd: Option, off: u64) -> i64 = 9; - fn mprotect(addr: u64, len: usize, prot: ProtFlags) -> i64 = 10; - fn brk(brk: u64) -> i64 = 12; - fn rt_sigaction(sig: Signal, act: *const SigAction, oact: *mut SigAction, sigsetsize: usize) -> i64 = 13; - fn ioctl(fd: FileDesc, cmd: Ioctl, arg: u64) -> i64 = 16; - fn pread64(fd: FileDesc, buf: *mut u8, count: usize, pos: u64) -> i64 = 17; - fn access(filename: CString, mode: AccessMode) -> i64 = 21; - fn getcwd(buf: *mut u8, size: u64) -> i64 = 79; - fn readlink(path: CString, buf: *mut u8, bufsiz: i32) -> i64 = 89; - fn sysinfo(info: *mut SysInfo) -> i64 = 99; - fn times(tbuf: *mut Tms) -> i64 = 100; - fn arch_prctl(option: ArchOption, arg2: u64) -> i64 = 158; - fn set_tid_address(tidptr: *mut i32) -> i64 = 218; - fn exit_group(error_code: i32) -> i64 = 231; - fn openat(dfd: DirFd, filename: CString, flags: OpenFlags, mode: FileMode) -> i64 = 257; - fn newfstatat(dfd: DirFd, filename: CString, statbuf: *mut Stat, flags: AtFlags) -> i64 = 262; - fn set_robust_list(head: *mut RobustListHead, len: usize) -> i64 = 273; - fn prlimit64(pid: i32, resource: ResourceLimit, new_rlim: *const RLimit64, old_rlim: *mut RLimit64) -> i64 = 302; - fn getrandom(ubuf: *mut u8, len: usize, flags: GrndFlags) -> i64 = 318; - } -} - #[derive(Debug, Clone)] enum EntryExit { /// Process is about to enter a syscall @@ -535,8 +270,6 @@ fn main() -> Result<()> { Ok(()) } -const AT_FDCWD: i32 = -100; - fn check_syscall(entry: &SyscallEntry) -> bool { match *entry { SyscallEntry::mmap { @@ -648,134 +381,3 @@ fn check_syscall(entry: &SyscallEntry) -> bool { } true } - -syscall_bitflags! { - struct OpenFlags: i32 { - const WRONLY = 1 << 0 => O_WRONLY; - const CREAT = 1 << 6 => O_CREAT; - const NOCTTY = 1 << 8 => O_NOCTTY; - const TRUNC = 1 << 9 => O_TRUNC; - const CLOEXEC = 1 << 19 => O_CLOEXEC; - } - - struct GrndFlags: u32 { - const NONBLOCK = 1 << 0 => GRND_NONBLOCK; - const RANDOM = 1 << 1 => GRND_RANDOM; - } - - struct MapFlags: i32 { - const PRIVATE = 1 << 1 => MAP_PRIVATE; - const FIXED = 1 << 4 => MAP_FIXED; - const ANONYMOUS = 1 << 5 => MAP_ANONYMOUS; - const DENYWRITE = 1 << 11 => MAP_DENYWRITE; - } - - struct ProtFlags: i32 { - const READ = 1 << 0 => PROT_READ; - const WRITE = 1 << 1 => PROT_WRITE; - const EXEC = 1 << 2 => PROT_EXEC; - } - - struct AtFlags: i32 { - const EMPTY_PATH = 1 << 12 => AT_EMPTY_PATH; - } - - struct AccessMode: i32 { - const F = 0 => F_OK; - const X = 1 << 0 => X_OK; - const W = 1 << 1 => W_OK; - const R = 1 << 2 => R_OK; - } - - struct FileMode: u32 { - const IRUSR = 0o400 => S_IRUSR; - const IWUSR = 0o200 => S_IWUSR; - const IXUSR = 0o100 => S_IXUSR; - - const IRGRP = 0o040 => S_IRGRP; - const IWGRP = 0o020 => S_IWGRP; - const IXGRP = 0o010 => S_IXGRP; - - const IROTH = 0o004 => S_IROTH; - const IWOTH = 0o002 => S_IWOTH; - const IXOTH = 0o001 => S_IXOTH; - } -} - -syscall_enums! { - enum ResourceLimit: u32 { - STACK = 0x3 => RLIMIT_STACK, - RSS = 0x5 => RLIMIT_RSS, - AS = 0x9 => RLIMIT_AS, - } - - enum ArchOption: i32 { - SET_FS = 0x1002, - } - - enum Ioctl: u64 { - TCGETS = 0x5401 => TCGETS, - TIOCGWINSZ = 0x5413 => TIOCGWINSZ, - } - - enum Signal: i32 { - ILL = 4 => SIGILL, - ABRT = 6 => SIGABRT, - BUS = 7 => SIGBUS, - FPE = 8 => SIGFPE, - SEGV = 11 => SIGSEGV, - } -} - -#[derive(Clone, Copy, Eq, PartialEq)] -struct FileDesc(i32); - -impl Debug for FileDesc { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -impl SyscallArg for FileDesc { - fn try_from_reg(reg: u64) -> Option { - Some(match i32::try_from_reg(reg)? { - fd @ 0..=i32::MAX => FileDesc(fd), - _ => return None, - }) - } -} - -impl SyscallArg for Option { - fn try_from_reg(reg: u64) -> Option { - Some(match i32::try_from_reg(reg)? { - -1 => None, - fd @ 0..=i32::MAX => Some(FileDesc(fd)), - _ => return None, - }) - } -} - -#[derive(Clone, Copy, Eq, PartialEq)] -enum DirFd { - Cwd, - Fd(FileDesc), -} - -impl Debug for DirFd { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - DirFd::Cwd => write!(f, "AT_FDCWD"), - DirFd::Fd(FileDesc(fd)) => write!(f, "{fd}"), - } - } -} - -impl SyscallArg for DirFd { - fn try_from_reg(reg: u64) -> Option { - Some(match i32::try_from_reg(reg)? { - AT_FDCWD => Self::Cwd, - fd @ 0..=i32::MAX => DirFd::Fd(FileDesc(fd)), - _ => return None, - }) - } -} diff --git a/ripple/minitrace/src/syscall_abi/arg.rs b/ripple/minitrace/src/syscall_abi/arg.rs new file mode 100644 index 0000000..b25757c --- /dev/null +++ b/ripple/minitrace/src/syscall_abi/arg.rs @@ -0,0 +1,84 @@ +// SPDX-FileCopyrightText: edef +// SPDX-License-Identifier: OSL-3.0 + +use {crate::Process, std::ffi::CString}; + +pub(crate) trait ProcessSyscallArg: Sized { + fn try_from_process_reg(process: &Process, reg: u64) -> Option; +} + +impl ProcessSyscallArg for CString { + fn try_from_process_reg(process: &Process, reg: u64) -> Option { + process.read_mem_cstr(reg).ok() + } +} + +impl ProcessSyscallArg for T { + fn try_from_process_reg(_process: &Process, reg: u64) -> Option { + SyscallArg::try_from_reg(reg) + } +} + +pub(crate) trait SyscallArg: Sized { + fn try_from_reg(reg: u64) -> Option; +} + +impl SyscallArg for u16 { + fn try_from_reg(reg: u64) -> Option { + reg.try_into().ok() + } +} + +impl SyscallArg for u32 { + fn try_from_reg(reg: u64) -> Option { + reg.try_into().ok() + } +} + +impl SyscallArg for u64 { + fn try_from_reg(reg: u64) -> Option { + Some(reg) + } +} + +impl SyscallArg for i32 { + fn try_from_reg(reg: u64) -> Option { + Some(u32::try_from(reg).ok()? as i32) + } +} + +impl SyscallArg for *mut i32 { + fn try_from_reg(reg: u64) -> Option { + Some(usize::try_from_reg(reg)? as *mut i32) + } +} + +impl SyscallArg for usize { + fn try_from_reg(reg: u64) -> Option { + reg.try_into().ok() + } +} + +impl SyscallArg for *const u8 { + fn try_from_reg(reg: u64) -> Option { + Some(usize::try_from_reg(reg)? as *const u8) + } +} + +impl SyscallArg for *mut u8 { + fn try_from_reg(reg: u64) -> Option { + Some(usize::try_from_reg(reg)? as *mut u8) + } +} + +impl SyscallArg for *mut () { + fn try_from_reg(reg: u64) -> Option { + Some(usize::try_from_reg(reg)? as *mut ()) + } +} + +impl SyscallArg for *const () { + fn try_from_reg(reg: u64) -> Option { + Some(usize::try_from_reg(reg)? as *const ()) + } +} diff --git a/ripple/minitrace/src/syscall_abi/fd.rs b/ripple/minitrace/src/syscall_abi/fd.rs new file mode 100644 index 0000000..cd0c008 --- /dev/null +++ b/ripple/minitrace/src/syscall_abi/fd.rs @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: edef +// SPDX-License-Identifier: OSL-3.0 + +use { + super::SyscallArg, + std::fmt::{self, Debug}, +}; + +#[derive(Clone, Copy, Eq, PartialEq)] +pub(crate) struct FileDesc(i32); + +impl Debug for FileDesc { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl SyscallArg for FileDesc { + fn try_from_reg(reg: u64) -> Option { + Some(match i32::try_from_reg(reg)? { + fd @ 0..=i32::MAX => FileDesc(fd), + _ => return None, + }) + } +} + +impl SyscallArg for Option { + fn try_from_reg(reg: u64) -> Option { + Some(match i32::try_from_reg(reg)? { + -1 => None, + fd @ 0..=i32::MAX => Some(FileDesc(fd)), + _ => return None, + }) + } +} + +#[derive(Clone, Copy, Eq, PartialEq)] +pub(crate) enum DirFd { + Cwd, + Fd(FileDesc), +} + +const AT_FDCWD: i32 = -100; + +impl Debug for DirFd { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + DirFd::Cwd => write!(f, "AT_FDCWD"), + DirFd::Fd(FileDesc(fd)) => write!(f, "{fd}"), + } + } +} + +impl SyscallArg for DirFd { + fn try_from_reg(reg: u64) -> Option { + Some(match i32::try_from_reg(reg)? { + AT_FDCWD => Self::Cwd, + fd @ 0..=i32::MAX => DirFd::Fd(FileDesc(fd)), + _ => return None, + }) + } +} diff --git a/ripple/minitrace/src/syscall_abi/macros.rs b/ripple/minitrace/src/syscall_abi/macros.rs new file mode 100644 index 0000000..07e6099 --- /dev/null +++ b/ripple/minitrace/src/syscall_abi/macros.rs @@ -0,0 +1,161 @@ +// SPDX-FileCopyrightText: edef +// SPDX-License-Identifier: OSL-3.0 + +#[cfg(test)] +use std::fmt::{self, Debug}; + +#[cfg(test)] +pub(crate) fn libc_check( + item: &'static str, + (our_name, our_value): (&'static str, T), + (libc_name, libc_value): (&'static str, T), +) { + match () { + _ if libc_name.ends_with(our_name) => {} + _ if libc_name.starts_with(&format!("{our_name}_")) => {} + () => panic!("{libc_name} doesn't match {our_name}"), + } + + assert!( + our_value == libc_value, + "{item}::{our_name} ({our_value:#x}) != libc::{libc_name} ({libc_value:#x})", + ); +} + +#[macro_export] +macro_rules! syscall_bitflags { + ( + $( + struct $BitFlags:ident: $T:ty { + $( + const $FLAG:ident = $value:expr => $LIBC_FLAG:ident; + )* + } + )* + ) => { + #[test] + fn verify_syscall_bitflags() { + $( + $BitFlags::verify(); + )* + } + + $( + $crate::bitflags! { + pub(crate) struct $BitFlags: $T { + $( + const $FLAG = $value; + )* + } + } + + impl $BitFlags { + #[cfg(test)] + fn verify() { + $( + $crate::syscall_abi::macros::libc_check( + stringify!($BitFlags), + (stringify!($FLAG), Self::$FLAG.bits()), + (stringify!($LIBC_FLAG), $crate::libc::$LIBC_FLAG) + ); + )* + } + } + + impl $crate::syscall_abi::SyscallArg for $BitFlags { + fn try_from_reg(reg: u64) -> Option { + $crate::syscall_abi::SyscallArg::try_from_reg(reg).and_then(Self::from_bits) + } + } + )* + }; +} + +#[macro_export] +macro_rules! syscall_enums { + ( + $( + enum $Enum:ident: $T:ty { + $( + $VARIANT:ident = $value:literal $(=> $LIBC_VALUE:ident)?, + )* + } + )* + ) => { + #[test] + fn verify_syscall_enums() { + $( + $Enum::verify(); + )* + } + + $( + #[derive(Debug, Copy, Clone, Eq, PartialEq)] + #[allow(non_camel_case_types)] + pub(crate) enum $Enum { + $($VARIANT = $value),* + } + + impl $crate::syscall_abi::SyscallArg for $Enum { + fn try_from_reg(reg: u64) -> Option { + let reg = <$T as $crate::syscall_abi::SyscallArg>::try_from_reg(reg)?; + Some(match reg { + $( + $value => $Enum::$VARIANT, + )* + _ => return None + }) + } + } + + impl $Enum { + #[cfg(test)] + fn verify() { + $( + $( + $crate::syscall_abi::macros::libc_check( + stringify!($Enum), + (stringify!($VARIANT), Self::$VARIANT as $T), + (stringify!($LIBC_VALUE), $crate::libc::$LIBC_VALUE) + ); + )? + )* + } + } + )* + }; +} + +#[macro_export] +macro_rules! define_syscalls { + (enum $SyscallEntry:ident { + $(fn $syscall:ident ( $($arg:ident : $Arg:ty),* ) -> $Ret:ty = $nr:literal ;)* + }) => { + #[derive(Debug, Clone)] + #[allow(non_camel_case_types)] + // TODO(edef): re-enable dead_code lint when we start fully interpreting syscall args + #[allow(dead_code)] + pub(crate) enum $SyscallEntry { + $($syscall { + $($arg : $Arg),* + }),* + } + + impl $SyscallEntry { + pub(crate) fn from_regs(process: &Process, regs: $crate::libc::user_regs_struct) -> anyhow::Result<$SyscallEntry> { + use anyhow::bail; + Ok(match (regs.orig_rax, [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9]) { + $( + ($nr, [$($arg,)* ..]) => $SyscallEntry::$syscall { + $($arg: match ProcessSyscallArg::try_from_process_reg(process, $arg) { + Some(x) => x, + None => bail!("couldn't parse {}(2) {}: {:#08x}", stringify!($syscall), stringify!($arg), $arg) + }),* + }, + )* + (n, _) => bail!("unknown syscall number {n}") + }) + } + } + } +} diff --git a/ripple/minitrace/src/syscall_abi/mod.rs b/ripple/minitrace/src/syscall_abi/mod.rs new file mode 100644 index 0000000..e0b35a9 --- /dev/null +++ b/ripple/minitrace/src/syscall_abi/mod.rs @@ -0,0 +1,127 @@ +// SPDX-FileCopyrightText: edef +// SPDX-FileCopyrightText: V +// SPDX-License-Identifier: OSL-3.0 + +use { + crate::{define_syscalls, syscall_bitflags, syscall_enums, Process}, + std::ffi::CString, +}; + +pub(crate) use arg::{ProcessSyscallArg, SyscallArg}; +pub(crate) use fd::{DirFd, FileDesc}; + +mod arg; +mod fd; +pub mod macros; + +type SigAction = (); +type SysInfo = (); +type Tms = (); +type Stat = (); +type RobustListHead = (); +type RLimit64 = (); + +define_syscalls! { + enum SyscallEntry { + fn read(fd: FileDesc, buf: *mut u8, count: usize) -> i64 = 0; + fn write(fd: FileDesc, buf: *const u8, count: usize) -> i64 = 1; + fn close(fd: FileDesc) -> i64 = 3; + fn mmap(addr: u64, len: u64, prot: ProtFlags, flags: MapFlags, fd: Option, off: u64) -> i64 = 9; + fn mprotect(addr: u64, len: usize, prot: ProtFlags) -> i64 = 10; + fn brk(brk: u64) -> i64 = 12; + fn rt_sigaction(sig: Signal, act: *const SigAction, oact: *mut SigAction, sigsetsize: usize) -> i64 = 13; + fn ioctl(fd: FileDesc, cmd: Ioctl, arg: u64) -> i64 = 16; + fn pread64(fd: FileDesc, buf: *mut u8, count: usize, pos: u64) -> i64 = 17; + fn access(filename: CString, mode: AccessMode) -> i64 = 21; + fn getcwd(buf: *mut u8, size: u64) -> i64 = 79; + fn readlink(path: CString, buf: *mut u8, bufsiz: i32) -> i64 = 89; + fn sysinfo(info: *mut SysInfo) -> i64 = 99; + fn times(tbuf: *mut Tms) -> i64 = 100; + fn arch_prctl(option: ArchOption, arg2: u64) -> i64 = 158; + fn set_tid_address(tidptr: *mut i32) -> i64 = 218; + fn exit_group(error_code: i32) -> i64 = 231; + fn openat(dfd: DirFd, filename: CString, flags: OpenFlags, mode: FileMode) -> i64 = 257; + fn newfstatat(dfd: DirFd, filename: CString, statbuf: *mut Stat, flags: AtFlags) -> i64 = 262; + fn set_robust_list(head: *mut RobustListHead, len: usize) -> i64 = 273; + fn prlimit64(pid: i32, resource: ResourceLimit, new_rlim: *const RLimit64, old_rlim: *mut RLimit64) -> i64 = 302; + fn getrandom(ubuf: *mut u8, len: usize, flags: GrndFlags) -> i64 = 318; + } +} + +syscall_bitflags! { + struct OpenFlags: i32 { + const WRONLY = 1 << 0 => O_WRONLY; + const CREAT = 1 << 6 => O_CREAT; + const NOCTTY = 1 << 8 => O_NOCTTY; + const TRUNC = 1 << 9 => O_TRUNC; + const CLOEXEC = 1 << 19 => O_CLOEXEC; + } + + struct GrndFlags: u32 { + const NONBLOCK = 1 << 0 => GRND_NONBLOCK; + const RANDOM = 1 << 1 => GRND_RANDOM; + } + + struct MapFlags: i32 { + const PRIVATE = 1 << 1 => MAP_PRIVATE; + const FIXED = 1 << 4 => MAP_FIXED; + const ANONYMOUS = 1 << 5 => MAP_ANONYMOUS; + const DENYWRITE = 1 << 11 => MAP_DENYWRITE; + } + + struct ProtFlags: i32 { + const READ = 1 << 0 => PROT_READ; + const WRITE = 1 << 1 => PROT_WRITE; + const EXEC = 1 << 2 => PROT_EXEC; + } + + struct AtFlags: i32 { + const EMPTY_PATH = 1 << 12 => AT_EMPTY_PATH; + } + + struct AccessMode: i32 { + const F = 0 => F_OK; + const X = 1 << 0 => X_OK; + const W = 1 << 1 => W_OK; + const R = 1 << 2 => R_OK; + } + + struct FileMode: u32 { + const IRUSR = 0o400 => S_IRUSR; + const IWUSR = 0o200 => S_IWUSR; + const IXUSR = 0o100 => S_IXUSR; + + const IRGRP = 0o040 => S_IRGRP; + const IWGRP = 0o020 => S_IWGRP; + const IXGRP = 0o010 => S_IXGRP; + + const IROTH = 0o004 => S_IROTH; + const IWOTH = 0o002 => S_IWOTH; + const IXOTH = 0o001 => S_IXOTH; + } +} + +syscall_enums! { + enum ResourceLimit: u32 { + STACK = 0x3 => RLIMIT_STACK, + RSS = 0x5 => RLIMIT_RSS, + AS = 0x9 => RLIMIT_AS, + } + + enum ArchOption: i32 { + SET_FS = 0x1002, + } + + enum Ioctl: u64 { + TCGETS = 0x5401 => TCGETS, + TIOCGWINSZ = 0x5413 => TIOCGWINSZ, + } + + enum Signal: i32 { + ILL = 4 => SIGILL, + ABRT = 6 => SIGABRT, + BUS = 7 => SIGBUS, + FPE = 8 => SIGFPE, + SEGV = 11 => SIGSEGV, + } +} -- cgit 1.4.1