diff --git a/src/main.rs b/src/main.rs index 2a9061f..d35e662 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,63 +1,48 @@ mod child; -use nix::libc::user_regs_struct; use nix::sys::ptrace::*; -use nix::sys::wait::waitpid; -use nix::unistd::{fork, ForkResult}; +use nix::sys::wait::{waitpid, WaitStatus}; +use nix::unistd::{fork, ForkResult, Pid}; use std::ffi::CString; use std::process::ExitCode; +fn single_step_all(child_pid: Pid) -> ExitCode { + let mut instruction_number = 0; + loop { + let wait_status = waitpid(child_pid, None); + match wait_status { + Ok(WaitStatus::Stopped(_, _)) => { + instruction_number += 1; + let regs = getregs(child_pid).unwrap(); + println!( + "🔎 [==> {}] rip= 0x{:016X}, rax = 0x{rax:X} ({rax})", + instruction_number, + regs.rip, + rax = regs.rax + ); + step(child_pid, None).unwrap(); + } + Ok(WaitStatus::Exited(_, exit_code)) => { + println!("👋 Child exited with code {exit_code}"); + return ExitCode::SUCCESS; + } + other => { + println!("⚠️ Other (unexpected) wait status: {other:?}"); + return ExitCode::FAILURE; + } + } + } +} + fn main() -> ExitCode { let child_exec_path = CString::new(env!("TEST_PROG_PATH")).unwrap(); match unsafe { fork() } { Ok(ForkResult::Child) => child::starti(child_exec_path), Ok(ForkResult::Parent { child: child_pid }) => { - println!("✔️ Started child {child_pid}"); - - let mut before_instruction = 0; - loop { - use nix::sys::signal::Signal::*; - use nix::sys::wait::WaitStatus::*; - match waitpid(child_pid, None) { - Err(e) => { - println!("❌ Wait failed: {e}"); - return ExitCode::FAILURE; - } - Ok(status) => match status { - Exited(_pid, exit_code) => { - println!("👋 Child exited with code {exit_code}"); - return ExitCode::SUCCESS; - } - Signaled(_, signal, _) => match signal { - SIGKILL => { - println!("💀 Child killed by SIGKILL"); - return ExitCode::SUCCESS; - } - s => println!("💡 Child received signal {s:?}"), - }, - Stopped(_pid, _signal) => { - let regs = getregs(child_pid).unwrap(); - println!( - "🔎 [{}] rip= 0x{:016X}, rax = 0x{rax:X} ({rax})", - before_instruction, - regs.rip, - rax = regs.rax - ); - if regs.rax == 60 { - println!("Let's change a register!"); - let new_regs = user_regs_struct { rdi: 54, ..regs }; - setregs(child_pid, new_regs).unwrap(); - } - before_instruction += 1; - step(child_pid, None).unwrap(); - } - status => { - println!("⚠️ Other (unexpected) wait status: {status:?}"); - } - }, - } - } + println!("✔️ Created child {child_pid}"); + return single_step_all(child_pid); + // todo!("Something interesting"); } Err(e) => { println!("❌ Fork failed: {e}");