summaryrefslogtreecommitdiff
path: root/src/trace.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/trace.rs')
-rw-r--r--src/trace.rs49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/trace.rs b/src/trace.rs
new file mode 100644
index 0000000..0031fcd
--- /dev/null
+++ b/src/trace.rs
@@ -0,0 +1,49 @@
+use nix::{
+ sys::{
+ ptrace,
+ signal::Signal,
+ wait::{waitpid, WaitStatus},
+ },
+ unistd::Pid,
+};
+use std::{os::unix::process::CommandExt, process::Command};
+
+pub fn exec(command: &mut Command) -> anyhow::Result<Pid> {
+ unsafe {
+ command.pre_exec(|| ptrace::traceme().map_err(|e| e.into()));
+ }
+ let child = command.spawn()?;
+ Ok(Pid::from_raw(child.id() as i32))
+}
+
+pub fn trace(pid: Pid) -> anyhow::Result<()> {
+ let mut have_to_print = true;
+ loop {
+ have_to_print ^= true;
+ ptrace::syscall(pid, None)?;
+ let status = waitpid(pid, None)?;
+
+ match status {
+ WaitStatus::Exited(_pid, _) => {
+ break;
+ }
+ WaitStatus::Stopped(pid, signal) => {
+ match signal {
+ Signal::SIGTRAP => {
+ let regs = ptrace::getregs(pid)?;
+ if have_to_print {
+ println!(
+ "{}({:x}, {:x}, {:x}, ...) = {:x}",
+ regs.orig_rax, regs.rdi, regs.rsi, regs.rdx, regs.rax,
+ );
+ }
+ }
+ _ => {}
+ };
+ }
+ _ => {}
+ };
+ }
+
+ Ok(())
+}