summary refs log tree commit diff
path: root/ripple/minitrace/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ripple/minitrace/src/main.rs')
-rw-r--r--ripple/minitrace/src/main.rs404
1 files changed, 3 insertions, 401 deletions
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<T: Debug + Eq + fmt::LowerHex>(
-	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<Self> {
-					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<Self> {
-					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<Self>;
-}
-
-impl ProcessSyscallArg for CString {
-	fn try_from_process_reg(process: &Process, reg: u64) -> Option<Self> {
-		process.read_mem_cstr(reg).ok()
-	}
-}
-
-impl<T: SyscallArg> ProcessSyscallArg for T {
-	fn try_from_process_reg(_process: &Process, reg: u64) -> Option<Self> {
-		SyscallArg::try_from_reg(reg)
-	}
-}
-
-trait SyscallArg: Sized {
-	fn try_from_reg(reg: u64) -> Option<Self>;
-}
-
-impl SyscallArg for u16 {
-	fn try_from_reg(reg: u64) -> Option<Self> {
-		reg.try_into().ok()
-	}
-}
-
-impl SyscallArg for u32 {
-	fn try_from_reg(reg: u64) -> Option<Self> {
-		reg.try_into().ok()
-	}
-}
-
-impl SyscallArg for u64 {
-	fn try_from_reg(reg: u64) -> Option<Self> {
-		Some(reg)
-	}
-}
-
-impl SyscallArg for i32 {
-	fn try_from_reg(reg: u64) -> Option<Self> {
-		Some(u32::try_from(reg).ok()? as i32)
-	}
-}
-
-impl SyscallArg for *mut i32 {
-	fn try_from_reg(reg: u64) -> Option<Self> {
-		Some(usize::try_from_reg(reg)? as *mut i32)
-	}
-}
-
-impl SyscallArg for usize {
-	fn try_from_reg(reg: u64) -> Option<Self> {
-		reg.try_into().ok()
-	}
-}
-
-impl SyscallArg for *const u8 {
-	fn try_from_reg(reg: u64) -> Option<Self> {
-		Some(usize::try_from_reg(reg)? as *const u8)
-	}
-}
-
-impl SyscallArg for *mut u8 {
-	fn try_from_reg(reg: u64) -> Option<Self> {
-		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<Self> {
-		Some(usize::try_from_reg(reg)? as *mut ())
-	}
-}
-
-impl SyscallArg for *const () {
-	fn try_from_reg(reg: u64) -> Option<Self> {
-		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<FileDesc>, 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<Self> {
-		Some(match i32::try_from_reg(reg)? {
-			fd @ 0..=i32::MAX => FileDesc(fd),
-			_ => return None,
-		})
-	}
-}
-
-impl SyscallArg for Option<FileDesc> {
-	fn try_from_reg(reg: u64) -> Option<Self> {
-		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<Self> {
-		Some(match i32::try_from_reg(reg)? {
-			AT_FDCWD => Self::Cwd,
-			fd @ 0..=i32::MAX => DirFd::Fd(FileDesc(fd)),
-			_ => return None,
-		})
-	}
-}