From 1fb5e8c0f8515ab24020d6b2f9af9fe0c8c739eb Mon Sep 17 00:00:00 2001 From: Elnath Date: Sun, 18 May 2025 15:36:47 +0200 Subject: [PATCH] Organised modules in folders --- src/debug_target.rs | 105 ------------------- src/debug_target/mod.rs | 32 ++++++ src/debug_target/running_target.rs | 37 +++++++ src/debug_target/stopped_target.rs | 47 +++++++++ src/main.rs | 1 - src/{syscall_info.rs => syscall_info/mod.rs} | 8 +- src/{ => syscall_info}/syscall_names.rs | 0 7 files changed, 120 insertions(+), 110 deletions(-) delete mode 100644 src/debug_target.rs create mode 100644 src/debug_target/mod.rs create mode 100644 src/debug_target/running_target.rs create mode 100644 src/debug_target/stopped_target.rs rename src/{syscall_info.rs => syscall_info/mod.rs} (95%) rename src/{ => syscall_info}/syscall_names.rs (100%) diff --git a/src/debug_target.rs b/src/debug_target.rs deleted file mode 100644 index ec1e1dd..0000000 --- a/src/debug_target.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::syscall_info::{syscall_info, SyscallInfo, SyscallInfoError}; -use either::{Either, Left, Right}; -use nix::libc::user_regs_struct; -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)] -#[error("Error when waiting on child process: {0}")] -pub struct WaitError(#[from] nix::errno::Errno); - -#[derive(thiserror::Error, Debug)] -pub enum DebugError { - #[error(transparent)] - PTraceError(#[from] PTraceError), - - #[error(transparent)] - WaitError(#[from] WaitError), - - #[error("Child stopped with status {0:?}, but was not expecting to catch this one")] - UnexpectedWaitStatus(nix::sys::wait::WaitStatus), -} - -pub struct StoppedTarget { - pub pid: Pid, -} - - -#[allow(dead_code)] -impl StoppedTarget { - fn to_running(self) -> RunningTarget { - RunningTarget { pid: self.pid } - } - - pub fn new(pid: Pid) -> Result { - waitid(Id::Pid(pid), WaitPidFlag::WSTOPPED).map_err(WaitError)?; - // Needed for waiting on syscalls and apparently also for getting syscall info (can not get it to work without this) - nix::sys::ptrace::setoptions(pid, nix::sys::ptrace::Options::PTRACE_O_TRACESYSGOOD).map_err(PTraceError)?; - Ok(Self { pid }) - } - - pub fn cont(self) -> Result { - nix::sys::ptrace::cont(self.pid, None).map_err(PTraceError)?; - Ok(self.to_running()) - } - - pub fn stepi(self) -> Result { - nix::sys::ptrace::step(self.pid, None).map_err(PTraceError)?; - Ok(self.to_running()) - } - - pub fn cont_syscall(self) -> Result { - nix::sys::ptrace::syscall(self.pid, None).map_err(PTraceError)?; - Ok(self.to_running()) - } - - pub fn get_registers(&self) -> Result { - Ok(nix::sys::ptrace::getregs(self.pid)?) - } - - pub fn get_syscall_info(&self) -> Result { - Ok(syscall_info(self.pid.as_raw())?) - } -} - -pub struct RunningTarget { - pub pid: Pid, -} - -#[allow(dead_code)] -impl RunningTarget { - fn to_stopped(self) -> StoppedTarget { - StoppedTarget { pid: self.pid } - } - - pub fn wait_for_something(self) -> Result, DebugError> { - match waitid(Id::Pid(self.pid), WaitPidFlag::WSTOPPED | WaitPidFlag::WEXITED).map_err(WaitError)? { - WaitStatus::Exited(_pid, exit_code) => Ok(Right(ExitedTarget { exit_code, was_pid: self.pid })), - WaitStatus::PtraceEvent(..) | WaitStatus::PtraceSyscall(..) => Ok(Left(self.to_stopped())), - status => Err(DebugError::UnexpectedWaitStatus(status)), - } - } - - pub fn wait_for_syscall(self) -> Result { - match waitid(Id::Pid(self.pid), WaitPidFlag::WSTOPPED).map_err(WaitError)? { - WaitStatus::PtraceSyscall(..) => Ok(self.to_stopped()), - status => Err(DebugError::UnexpectedWaitStatus(status)), - } - } - - pub fn wait_for_exit(self) -> Result { - match waitid(Id::Pid(self.pid), WaitPidFlag::WEXITED).map_err(WaitError)? { - WaitStatus::Exited(_pid, exit_code) => Ok(ExitedTarget { exit_code, was_pid: self.pid }), - status => Err(DebugError::UnexpectedWaitStatus(status)) - } - } -} - -pub struct ExitedTarget { - pub exit_code: i32, - pub was_pid: Pid, -} \ No newline at end of file diff --git a/src/debug_target/mod.rs b/src/debug_target/mod.rs new file mode 100644 index 0000000..c5f7331 --- /dev/null +++ b/src/debug_target/mod.rs @@ -0,0 +1,32 @@ +mod stopped_target; +mod running_target; + +use nix::unistd::Pid; +pub use running_target::*; +pub use stopped_target::*; + +#[derive(thiserror::Error, Debug)] +#[error("Error when calling ptrace: {0}")] +pub struct PTraceError(#[from] nix::errno::Errno); + +#[derive(thiserror::Error, Debug)] +#[error("Error when waiting on child process: {0}")] +pub struct WaitError(#[from] nix::errno::Errno); + +#[derive(thiserror::Error, Debug)] +pub enum DebugError { + #[error(transparent)] + PTraceError(#[from] PTraceError), + + #[error(transparent)] + WaitError(#[from] WaitError), + + #[error("Child stopped with status {0:?}, but was not expecting to catch this one")] + UnexpectedWaitStatus(nix::sys::wait::WaitStatus), +} + + +pub struct ExitedTarget { + pub exit_code: i32, + pub was_pid: Pid, +} diff --git a/src/debug_target/running_target.rs b/src/debug_target/running_target.rs new file mode 100644 index 0000000..575f0eb --- /dev/null +++ b/src/debug_target/running_target.rs @@ -0,0 +1,37 @@ +use crate::debug_target::{DebugError, ExitedTarget, StoppedTarget, WaitError}; +use either::{Either, Left, Right}; +use nix::sys::wait::{waitid, Id, WaitPidFlag, WaitStatus}; +use nix::unistd::Pid; + +pub struct RunningTarget { + pub pid: Pid, +} + +#[allow(dead_code)] +impl RunningTarget { + fn to_stopped(self) -> StoppedTarget { + StoppedTarget { pid: self.pid } + } + + pub fn wait_for_something(self) -> Result, DebugError> { + match waitid(Id::Pid(self.pid), WaitPidFlag::WSTOPPED | WaitPidFlag::WEXITED).map_err(WaitError)? { + WaitStatus::Exited(_pid, exit_code) => Ok(Right(ExitedTarget { exit_code, was_pid: self.pid })), + WaitStatus::PtraceEvent(..) | WaitStatus::PtraceSyscall(..) => Ok(Left(self.to_stopped())), + status => Err(DebugError::UnexpectedWaitStatus(status)), + } + } + + pub fn wait_for_syscall(self) -> Result { + match waitid(Id::Pid(self.pid), WaitPidFlag::WSTOPPED).map_err(WaitError)? { + WaitStatus::PtraceSyscall(..) => Ok(self.to_stopped()), + status => Err(DebugError::UnexpectedWaitStatus(status)), + } + } + + pub fn wait_for_exit(self) -> Result { + match waitid(Id::Pid(self.pid), WaitPidFlag::WEXITED).map_err(WaitError)? { + WaitStatus::Exited(_pid, exit_code) => Ok(ExitedTarget { exit_code, was_pid: self.pid }), + status => Err(DebugError::UnexpectedWaitStatus(status)) + } + } +} diff --git a/src/debug_target/stopped_target.rs b/src/debug_target/stopped_target.rs new file mode 100644 index 0000000..a6a1e28 --- /dev/null +++ b/src/debug_target/stopped_target.rs @@ -0,0 +1,47 @@ +use crate::debug_target::{DebugError, PTraceError, RunningTarget, WaitError}; +use crate::syscall_info::{syscall_info, SyscallInfo, SyscallInfoError}; +use libc::user_regs_struct; +use nix::sys::wait::{waitid, Id, WaitPidFlag}; +use nix::unistd::Pid; + +pub struct StoppedTarget { + pub pid: Pid, +} + + +#[allow(dead_code)] +impl StoppedTarget { + fn to_running(self) -> RunningTarget { + RunningTarget { pid: self.pid } + } + + pub fn new(pid: Pid) -> Result { + waitid(Id::Pid(pid), WaitPidFlag::WSTOPPED).map_err(WaitError)?; + // Needed for waiting on syscalls and apparently also for getting syscall info (can not get it to work without this) + nix::sys::ptrace::setoptions(pid, nix::sys::ptrace::Options::PTRACE_O_TRACESYSGOOD).map_err(PTraceError)?; + Ok(Self { pid }) + } + + pub fn cont(self) -> Result { + nix::sys::ptrace::cont(self.pid, None).map_err(PTraceError)?; + Ok(self.to_running()) + } + + pub fn stepi(self) -> Result { + nix::sys::ptrace::step(self.pid, None).map_err(PTraceError)?; + Ok(self.to_running()) + } + + pub fn cont_syscall(self) -> Result { + nix::sys::ptrace::syscall(self.pid, None).map_err(PTraceError)?; + Ok(self.to_running()) + } + + pub fn get_registers(&self) -> Result { + Ok(nix::sys::ptrace::getregs(self.pid)?) + } + + pub fn get_syscall_info(&self) -> Result { + Ok(syscall_info(self.pid.as_raw())?) + } +} diff --git a/src/main.rs b/src/main.rs index fc66a57..695c586 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ mod child; mod debug_target; mod syscall_info; -mod syscall_names; use crate::debug_target::{ExitedTarget, StoppedTarget}; use color_eyre::eyre::eyre; diff --git a/src/syscall_info.rs b/src/syscall_info/mod.rs similarity index 95% rename from src/syscall_info.rs rename to src/syscall_info/mod.rs index 7ab37fd..ae2cf61 100644 --- a/src/syscall_info.rs +++ b/src/syscall_info/mod.rs @@ -3,10 +3,10 @@ Currently nix's (v0.30.1) implementation for PTRACE_GET_SYSCALL_INFO does not se It also returns the raw libc struct containing a union, while this parses it in a custom union-free type. This is an alternative implementation that relies on libc and unsafe. */ - -use crate::syscall_info::SyscallInfoError::UnsupportedType; +mod syscall_names; use std::mem::MaybeUninit; -use crate::syscall_names::syscall_name; +pub use syscall_names::syscall_name; + #[derive(thiserror::Error, Debug)] pub enum SyscallInfoError { @@ -76,6 +76,6 @@ pub fn syscall_info(pid: libc::pid_t) -> Result { is_error: syscall_info_raw.u.exit.is_error, } }), - op => Err(UnsupportedType { op }), + op => Err(SyscallInfoError::UnsupportedType { op }), } } diff --git a/src/syscall_names.rs b/src/syscall_info/syscall_names.rs similarity index 100% rename from src/syscall_names.rs rename to src/syscall_info/syscall_names.rs