diff options
Diffstat (limited to 'src/trace.rs')
-rw-r--r-- | src/trace.rs | 104 |
1 files changed, 70 insertions, 34 deletions
diff --git a/src/trace.rs b/src/trace.rs index 3612519..c097fba 100644 --- a/src/trace.rs +++ b/src/trace.rs @@ -1,3 +1,4 @@ +use crate::cli::Args; use crate::registers::RegistersData; use nix::{ sys::{ @@ -7,7 +8,14 @@ use nix::{ }, unistd::Pid, }; -use std::{fs::File, io::Write, os::unix::process::CommandExt, process::Command}; +use std::{ + fs::File, + // fs::File, + io::{self, Write}, + os::unix::process::CommandExt, + process::Command, + str, +}; /// Exec the `command` value tracing it with `ptrace` lib pub fn exec(command: &str) -> anyhow::Result<()> { @@ -25,54 +33,82 @@ pub fn exec(command: &str) -> anyhow::Result<()> { Ok(()) } -/// Trace a process with `pid` ID and returns a list of `RegistersData` -pub fn trace(pid: Pid, file_to_print: Option<String>) -> anyhow::Result<Vec<RegistersData>> { - // Since you have to do 2 syscalls (start and end) you have to alternate the print value, - // because it could be equals except for the `rax` register. - let mut have_to_print = true; +/// Attach a ptrace status to a `pid` +pub fn attach(pid: Pid) -> anyhow::Result<()> { + ptrace::attach(pid)?; + + Ok(()) +} +/// Trace a process with `pid` ID and returns a list of `RegistersData` +pub fn trace(pid: Pid, args: &Args, run_loop: bool) -> anyhow::Result<Vec<RegistersData>> { // First wait for the parent process _ = waitpid(pid, None)?; - // If `fiole_to_print` is not None, create a new file with that value for redirecting all the + // FIXME: file writing on attachment + // If `file_to_print` is not None, create a new file with that value for redirecting all the // output (also in stdout) let mut f = None; - if let Some(filename) = file_to_print { + if let Some(filename) = &args.file_to_print { f = Some(File::create(filename)?); } let mut lines: Vec<RegistersData> = Vec::new(); - loop { - have_to_print ^= true; - ptrace::syscall(pid, None)?; - let status = waitpid(pid, None)?; + if run_loop { + // Since you have to do 2 syscalls (start and end) you have to alternate the print value, + // because it could be equals except for the `rax` register. + let mut have_to_print = true; - match status { - // Break the loop if the process exists - WaitStatus::Exited(_pid, _) => { - break; - } - // Match the stopped value for a process - WaitStatus::Stopped(pid, signal) => { - match signal { - Signal::SIGTRAP => { - if have_to_print { - let reg = RegistersData::new(ptrace::getregs(pid)?); - - if let Some(ref mut f) = f { - writeln!(f, "{}", reg.output())?; - } - - lines.push(reg); + loop { + match trace_next(pid)? { + Some(reg) => { + have_to_print ^= true; + if have_to_print { + if let Some(ref mut f) = f { + writeln!(f, "{}", reg.output())?; + } + + if args.no_tui { + writeln!(io::stdout(), "{}", reg.output())?; } + + lines.push(reg); } - _ => {} - }; + } + None => { + break; + } } - _ => {} - }; + } } - Ok(lines) } + +/// Get the next step for a ptrace process +pub fn trace_next(pid: Pid) -> anyhow::Result<Option<RegistersData>> { + ptrace::syscall(pid, None)?; + let status = waitpid(pid, None).unwrap(); + + match status { + // Match the stopped value for a process + WaitStatus::Stopped(pid, signal) => { + match signal { + Signal::SIGTRAP => { + let reg = RegistersData::new(ptrace::getregs(pid)?); + return Ok(Some(reg)); + } + _ => {} + }; + } + _ => {} + }; + + Ok(None) +} + +/// Kill a process traced by ptrace +pub fn trace_kill(pid: Pid) -> anyhow::Result<()> { + let _ = ptrace::kill(pid); + Ok(()) +} |