use std::io; #[derive(Debug)] pub enum TraceEvent { SyscallEntry(u64, [u64; 6]), SyscallExit(i64), Exited, } pub trait ChildTrace { fn next_event(&mut self) -> io::Result; fn resume(&mut self) -> io::Result<()>; fn kill(&mut self) -> io::Result<()>; unsafe fn peek_u8(&mut self, address: usize) -> io::Result { let aligned = address & !7; let shift = (address & 7) << 3; let word = self.peek_u64(aligned)?; Ok((word >> shift) as u8) } unsafe fn peek_u32(&mut self, address: usize) -> io::Result { eprintln!("PEEK U32 @ {address:#x}"); assert_eq!(address & 3, 0); let aligned = address & !7; let shift = (address & 7) << 3; let word = self.peek_u64(aligned)?; Ok((word >> shift) as u32) } unsafe fn peek_u64(&mut self, address: usize) -> io::Result; unsafe fn peek_bytes(&mut self, address: usize, buffer: &mut [u8]) -> io::Result<()> { for i in 0..buffer.len() { buffer[i] = self.peek_u8(address + i)?; } Ok(()) } unsafe fn peek_cstr(&mut self, address: usize, buffer: &mut [u8]) -> io::Result { let mut len = 0; while len < buffer.len() - 1 { let byte = self.peek_u8(address + len)?; buffer[len] = byte; if byte == 0 { break; } len += 1; } Ok(len) } unsafe fn peek_usize(&mut self, address: usize) -> io::Result { // FIXME I only support 64-bit archs Ok(self.peek_u64(address)? as _) } } pub trait CommandSpawnExt { type ChildTrace: ChildTrace; fn create_session(&mut self) -> io::Result<&mut Self>; fn create_process_group(&mut self) -> io::Result<&mut Self>; // TODO options for tracing across subchildren, etc fn spawn_with_trace(&mut self) -> io::Result; }