diff --git a/src/clibwrap/mod.rs b/src/clibwrap/mod.rs new file mode 100644 index 0000000..e613ce5 --- /dev/null +++ b/src/clibwrap/mod.rs @@ -0,0 +1,11 @@ +use std::ffi::c_long; + +pub mod ptrace; + +type Pid = i32; + +#[derive(Debug, thiserror::Error)] +#[error("Some kind of error when calling into C code: return code {error_code}")] +pub struct CError { + error_code: c_long, +} diff --git a/src/clibwrap/ptrace.rs b/src/clibwrap/ptrace.rs new file mode 100644 index 0000000..98b33e9 --- /dev/null +++ b/src/clibwrap/ptrace.rs @@ -0,0 +1,31 @@ +use crate::clibwrap::{CError, Pid}; +use std::ffi::{c_long, c_void}; + +#[allow(non_camel_case_types)] +#[repr(u32)] +enum PTraceRequest { + PTRACE_CONT = 7, + PTRACE_SINGLESTEP = 9, +} + +unsafe extern "C" { + fn ptrace(request: PTraceRequest, pid: Pid, addr: *mut c_void, data: *mut c_void) -> c_long; +} + +pub fn cont(pid: Pid) -> Result<(), CError> { + let return_code = unsafe { ptrace(PTraceRequest::PTRACE_CONT, pid, 0 as _, 0 as _) }; + if return_code == 0 { + Ok(()) + } else { + Err(CError { error_code: return_code }) + } +} + +pub fn single_step(pid: Pid) -> Result<(), CError> { + let return_code = unsafe { ptrace(PTraceRequest::PTRACE_SINGLESTEP, pid, 0 as _, 0 as _) }; + if return_code == 0 { + Ok(()) + } else { + Err(CError { error_code: return_code }) + } +} diff --git a/src/debug_target/mod.rs b/src/debug_target/mod.rs index e303071..d35c951 100644 --- a/src/debug_target/mod.rs +++ b/src/debug_target/mod.rs @@ -1,6 +1,7 @@ mod stopped_target; mod running_target; +use crate::clibwrap; use nix::unistd::Pid; pub use running_target::*; pub use stopped_target::*; @@ -18,6 +19,9 @@ pub enum DebugError { #[error(transparent)] PTraceError(#[from] PTraceError), + #[error(transparent)] + CustomPTraceError(#[from] clibwrap::CError), + #[error(transparent)] WaitError(#[from] WaitError), diff --git a/src/debug_target/stopped_target.rs b/src/debug_target/stopped_target.rs index a89ab10..f146c33 100644 --- a/src/debug_target/stopped_target.rs +++ b/src/debug_target/stopped_target.rs @@ -1,3 +1,4 @@ +use crate::clibwrap; use crate::debug_target::{DebugError, PTraceError, RunningTarget, WaitError}; use crate::syscall_info::{syscall_info, SyscallInfo, SyscallInfoError}; use libc::{c_long, user_regs_struct}; @@ -42,7 +43,7 @@ impl StoppedTarget { if self.on_breakpoint()? { self.breakpoint_remove_and_rewind()?; } - nix::sys::ptrace::cont(self.pid, None).map_err(PTraceError)?; + clibwrap::ptrace::cont(self.pid.as_raw())?; Ok(self.to_running()) } @@ -50,7 +51,7 @@ impl StoppedTarget { if self.on_breakpoint()? { self.breakpoint_remove_and_rewind()?; } - nix::sys::ptrace::step(self.pid, None).map_err(PTraceError)?; + clibwrap::ptrace::single_step(self.pid.as_raw())?; Ok(self.to_running()) } diff --git a/src/main.rs b/src/main.rs index b9f96d1..595fcf4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ mod debug_target; mod syscall_info; +mod clibwrap; use crate::debug_target::{ExitedTarget, StoppedTarget}; use color_eyre::eyre::eyre;