Stepi now returning running state for handling program exit
This commit is contained in:
parent
b20fa4672d
commit
99999346ed
|
|
@ -37,6 +37,7 @@ name = "bdb"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"color-eyre",
|
||||
"either",
|
||||
"nix",
|
||||
"thiserror",
|
||||
]
|
||||
|
|
@ -95,6 +96,12 @@ dependencies = [
|
|||
"tracing-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "eyre"
|
||||
version = "0.6.12"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ publish = false
|
|||
nix = { version = "0.29.0", features = ["process", "ptrace"] }
|
||||
thiserror = "2.0.12"
|
||||
color-eyre = "0.6.3"
|
||||
either = "1.15.0"
|
||||
|
||||
[build-dependencies]
|
||||
color-eyre = "0.6.3"
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
use either::{Either, Left, Right};
|
||||
use nix::libc::user_regs_struct;
|
||||
use nix::sys::signal::Signal;
|
||||
use nix::sys::wait::{waitid, Id, WaitPidFlag, WaitStatus};
|
||||
use nix::unistd::Pid;
|
||||
|
||||
|
|
@ -40,6 +40,7 @@ impl DebugState for Stopped {
|
|||
fn pid(&self) -> Pid { self.pid }
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl DebugTarget<Stopped> {
|
||||
pub fn new(pid: Pid) -> Result<Self, WaitError> {
|
||||
waitid(Id::Pid(pid), WaitPidFlag::WSTOPPED).map_err(WaitError)?;
|
||||
|
|
@ -51,12 +52,9 @@ impl DebugTarget<Stopped> {
|
|||
Ok(DebugTarget { state: Running { pid: self.state.pid } })
|
||||
}
|
||||
|
||||
pub fn stepi(self) -> Result<Self, DebugError> {
|
||||
pub fn stepi(self) -> Result<DebugTarget<Running>, PTraceError> {
|
||||
nix::sys::ptrace::step(self.state.pid, None).map_err(PTraceError)?;
|
||||
match waitid(Id::Pid(self.state.pid), WaitPidFlag::WSTOPPED).map_err(WaitError)? {
|
||||
WaitStatus::PtraceEvent(_pid, Signal::SIGTRAP, _c_event) => Ok(self),
|
||||
status => Err(DebugError::UnexpectedWaitStatus(status)),
|
||||
}
|
||||
Ok(DebugTarget { state: Running { pid: self.state.pid } })
|
||||
}
|
||||
|
||||
pub fn get_registers(&self) -> Result<user_regs_struct, PTraceError> {
|
||||
|
|
@ -72,8 +70,16 @@ impl DebugState for Running {
|
|||
fn pid(&self) -> Pid { self.pid }
|
||||
}
|
||||
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl DebugTarget<Running> {
|
||||
pub fn wait_for_something(self) -> Result<Either<DebugTarget<Stopped>, i32>, DebugError> {
|
||||
match waitid(Id::Pid(self.state.pid), WaitPidFlag::WSTOPPED | WaitPidFlag::WEXITED).map_err(WaitError)? {
|
||||
WaitStatus::Exited(_pid, exit_code) => Ok(Right(exit_code)),
|
||||
WaitStatus::PtraceEvent(_pid, _signal, _c_event) => Ok(Left(DebugTarget { state: Stopped { pid: self.state.pid } })),
|
||||
status => Err(DebugError::UnexpectedWaitStatus(status)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wait_for_exit(self) -> Result<i32, DebugError> {
|
||||
match waitid(Id::Pid(self.state.pid), WaitPidFlag::WEXITED).map_err(WaitError)? {
|
||||
WaitStatus::Exited(_pid, exit_code) => Ok(exit_code),
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ mod debug_target;
|
|||
|
||||
use crate::debug_target::{DebugTarget, Stopped};
|
||||
use color_eyre::eyre::eyre;
|
||||
use either::Either;
|
||||
use nix::libc::user_regs_struct;
|
||||
use nix::sys::ptrace::*;
|
||||
use nix::sys::signal::Signal::*;
|
||||
|
|
@ -17,7 +18,13 @@ fn single_step_all(mut target: DebugTarget<Stopped>) -> color_eyre::Result<()> {
|
|||
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()?;
|
||||
match target.stepi()?.wait_for_something()? {
|
||||
Either::Left(t) => target = t,
|
||||
Either::Right(exit_code) => {
|
||||
println!("👋 Child exited with code {exit_code}");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue