65 lines
1.9 KiB
Rust
65 lines
1.9 KiB
Rust
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<TraceEvent>;
|
|
fn resume(&mut self) -> io::Result<()>;
|
|
fn kill(&mut self) -> io::Result<()>;
|
|
|
|
unsafe fn peek_u8(&mut self, address: usize) -> io::Result<u8> {
|
|
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<u32> {
|
|
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<u64>;
|
|
|
|
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<usize> {
|
|
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<usize> {
|
|
// 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<Self::ChildTrace>;
|
|
}
|