Implemented stepi but does not work when program exits
This commit is contained in:
parent
1dac90f0d2
commit
3e4520e055
|
|
@ -1,10 +1,16 @@
|
|||
use nix::libc::user_regs_struct;
|
||||
use nix::sys::signal::Signal;
|
||||
use nix::sys::wait::{waitid, Id, WaitPidFlag, WaitStatus};
|
||||
use nix::unistd::Pid;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
#[error("Error when calling ptrace: {0}")]
|
||||
pub struct PTraceError(#[from] nix::errno::Errno);
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum DebugError {
|
||||
#[error("Error when calling ptrace: {0}")]
|
||||
PTraceError(#[from] nix::errno::Errno),
|
||||
PTraceError(#[from] nix::errno::Errno), // TODO: do not repeat above implem
|
||||
|
||||
#[error("Child stopped with status {0:?}, but was not expecting to catch this one")]
|
||||
UnexpectedWaitStatus(nix::sys::wait::WaitStatus),
|
||||
|
|
@ -37,6 +43,18 @@ impl DebugTarget<Stopped> {
|
|||
nix::sys::ptrace::cont(self.state.pid, None)?;
|
||||
Ok(DebugTarget { state: Running { pid: self.state.pid } })
|
||||
}
|
||||
|
||||
pub fn stepi(self) -> Result<Self, DebugError> {
|
||||
nix::sys::ptrace::step(self.state.pid, None)?;
|
||||
match waitid(Id::Pid(self.state.pid), WaitPidFlag::WSTOPPED | WaitPidFlag::WEXITED)? {
|
||||
WaitStatus::PtraceEvent(_pid, Signal::SIGTRAP, _c_event) => Ok(self),
|
||||
status => Err(DebugError::UnexpectedWaitStatus(status)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_registers(&self) -> Result<user_regs_struct, PTraceError> {
|
||||
Ok(nix::sys::ptrace::getregs(self.state.pid)?)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Running {
|
||||
|
|
|
|||
48
src/main.rs
48
src/main.rs
|
|
@ -1,7 +1,7 @@
|
|||
mod child;
|
||||
mod debug_target;
|
||||
|
||||
use crate::debug_target::DebugTarget;
|
||||
use crate::debug_target::{DebugTarget, Stopped};
|
||||
use color_eyre::eyre::eyre;
|
||||
use nix::libc::user_regs_struct;
|
||||
use nix::sys::ptrace::*;
|
||||
|
|
@ -11,25 +11,13 @@ use nix::unistd::{fork, ForkResult, Pid};
|
|||
use std::ffi::{c_long, c_void, CString};
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn single_step_all(child_pid: Pid) -> color_eyre::Result<()> {
|
||||
fn single_step_all(mut target: DebugTarget<Stopped>) -> color_eyre::Result<()> {
|
||||
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)?;
|
||||
}
|
||||
Ok(WaitStatus::Exited(_, exit_code)) => {
|
||||
println!("👋 Child exited with code {exit_code}");
|
||||
return Ok(());
|
||||
}
|
||||
other => {
|
||||
return Err(eyre!("⚠️ Other (unexpected) wait status: {other:?}"))
|
||||
}
|
||||
}
|
||||
instruction_number += 1;
|
||||
let regs = target.get_registers()?;
|
||||
println!("🔎 [==> {}] rip= {:#016x}, rax = 0x{rax:x} ({rax})", instruction_number, regs.rip, rax = regs.rax);
|
||||
target = target.stepi()?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -97,16 +85,24 @@ fn main() -> color_eyre::Result<()> {
|
|||
let target = DebugTarget::new(child_pid)?;
|
||||
println!("✔️ Child ready!");
|
||||
|
||||
println!("⚙️ Continuing execution");
|
||||
let target = target.cont()?;
|
||||
let exit_code = target.wait_for_exit()?;
|
||||
|
||||
println!("👋 Child exited with code {exit_code}");
|
||||
|
||||
Ok(())
|
||||
// println!("🔎 rip: {:#x}", target.get_registers()?.rip);
|
||||
// println!("➡️➡️➡️ Stepping three times");
|
||||
// let mut target = target;
|
||||
// for _i in 0..3 {
|
||||
// target = target.stepi()?;
|
||||
// }
|
||||
// println!("🔎 rip: {:#x}", target.get_registers()?.rip);
|
||||
//
|
||||
// println!("⚙️ Continuing execution");
|
||||
// let target = target.cont()?;
|
||||
// let exit_code = target.wait_for_exit()?;
|
||||
//
|
||||
// println!("👋 Child exited with code {exit_code}");
|
||||
//
|
||||
// Ok(())
|
||||
|
||||
|
||||
// single_step_all(child_pid)
|
||||
single_step_all(target)
|
||||
// breakpoint_fun(child_pid)
|
||||
}
|
||||
Err(e) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue