diff options
author | Joseph Kain <joekain@gmail.com> | 2015-06-27 08:22:23 -0700 |
---|---|---|
committer | Carl Lerche <me@carllerche.com> | 2015-07-03 15:06:32 -0700 |
commit | a0fc60700f9e8b93e570e51460b10201f721b635 (patch) | |
tree | 7d619354e30ad92b009e9a83c1fe4bd3335b39af | |
parent | 90bbc63646991ae4b092da60bdcbaef01637cb04 (diff) | |
download | nix-a0fc60700f9e8b93e570e51460b10201f721b635.zip |
Add support for ptrace
Closes #138
-rw-r--r-- | src/errno.rs | 72 | ||||
-rw-r--r-- | src/sys/mod.rs | 7 | ||||
-rw-r--r-- | src/sys/ptrace.rs | 79 |
3 files changed, 127 insertions, 31 deletions
diff --git a/src/errno.rs b/src/errno.rs index d9226b96..b41cc834 100644 --- a/src/errno.rs +++ b/src/errno.rs @@ -3,44 +3,50 @@ use libc::c_int; pub use self::consts::*; pub use self::consts::Errno::*; -/// Returns the platform-specific value of errno -pub fn errno() -> i32 { - #[cfg(any(target_os = "macos", - target_os = "ios", - target_os = "freebsd"))] - unsafe fn errno_location() -> *const c_int { - extern { fn __error() -> *const c_int; } - __error() - } - #[cfg(target_os = "bitrig")] - fn errno_location() -> *const c_int { - extern { - fn __errno() -> *const c_int; - } - unsafe { - __errno() - } - } +#[cfg(any(target_os = "macos", + target_os = "ios", + target_os = "freebsd"))] +unsafe fn errno_location() -> *mut c_int { + extern { fn __error() -> *mut c_int; } + __error() +} - #[cfg(target_os = "dragonfly")] - unsafe fn errno_location() -> *const c_int { - extern { fn __dfly_error() -> *const c_int; } - __dfly_error() +#[cfg(target_os = "bitrig")] +fn errno_location() -> *mut c_int { + extern { + fn __errno() -> *mut c_int; } - - #[cfg(target_os = "openbsd")] - unsafe fn errno_location() -> *const c_int { - extern { fn __errno() -> *const c_int; } + unsafe { __errno() } +} - #[cfg(any(target_os = "linux", target_os = "android"))] - unsafe fn errno_location() -> *const c_int { - extern { fn __errno_location() -> *const c_int; } - __errno_location() - } +#[cfg(target_os = "dragonfly")] +unsafe fn errno_location() -> *mut c_int { + extern { fn __dfly_error() -> *mut c_int; } + __dfly_error() +} + +#[cfg(target_os = "openbsd")] +unsafe fn errno_location() -> *mut c_int { + extern { fn __errno() -> *mut c_int; } + __errno() +} + +#[cfg(any(target_os = "linux", target_os = "android"))] +unsafe fn errno_location() -> *mut c_int { + extern { fn __errno_location() -> *mut c_int; } + __errno_location() +} +/// Sets the platform-specific errno to no-error +unsafe fn clear() -> () { + *errno_location() = 0; +} + +/// Returns the platform-specific value of errno +pub fn errno() -> i32 { unsafe { (*errno_location()) as i32 } @@ -60,6 +66,10 @@ macro_rules! impl_errno { pub fn from_i32(err: i32) -> Errno { from_i32(err) } + + pub unsafe fn clear() -> () { + super::clear() + } } } } diff --git a/src/sys/mod.rs b/src/sys/mod.rs index ac9d6216..c124359d 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -34,3 +34,10 @@ pub mod mman; pub mod uio; pub mod time; + +#[cfg(all(target_os = "linux", + any(target_arch = "x86", + target_arch = "x86_64", + target_arch = "arm")), + )] +pub mod ptrace; diff --git a/src/sys/ptrace.rs b/src/sys/ptrace.rs new file mode 100644 index 00000000..efda8c4e --- /dev/null +++ b/src/sys/ptrace.rs @@ -0,0 +1,79 @@ +use {Error, Result}; +use errno::Errno; +use libc::{pid_t, c_void}; + +#[cfg(all(target_os = "linux", + any(target_arch = "x86", + target_arch = "x86_64", + target_arch = "arm")), + )] +pub mod ptrace { + use libc::c_int; + + pub type PtraceRequest = c_int; + + pub const PTRACE_TRACEME: PtraceRequest = 0; + pub const PTRACE_PEEKTEXT: PtraceRequest = 1; + pub const PTRACE_PEEKDATA: PtraceRequest = 2; + pub const PTRACE_PEEKUSER: PtraceRequest = 3; + pub const PTRACE_POKETEXT: PtraceRequest = 4; + pub const PTRACE_POKEDATA: PtraceRequest = 5; + pub const PTRACE_POKEUSER: PtraceRequest = 6; + pub const PTRACE_CONT: PtraceRequest = 7; + pub const PTRACE_KILL: PtraceRequest = 8; + pub const PTRACE_SINGLESTEP: PtraceRequest = 9; + pub const PTRACE_GETREGS: PtraceRequest = 12; + pub const PTRACE_SETREGS: PtraceRequest = 13; + pub const PTRACE_GETFPREGS: PtraceRequest = 14; + pub const PTRACE_SETFPREGS: PtraceRequest = 15; + pub const PTRACE_ATTACH: PtraceRequest = 16; + pub const PTRACE_DETACH: PtraceRequest = 17; + pub const PTRACE_GETFPXREGS: PtraceRequest = 18; + pub const PTRACE_SETFPXREGS: PtraceRequest = 19; + pub const PTRACE_SYSCALL: PtraceRequest = 24; + pub const PTRACE_SETOPTIONS: PtraceRequest = 0x4200; + pub const PTRACE_GETEVENTMSG: PtraceRequest = 0x4201; + pub const PTRACE_GETSIGINFO: PtraceRequest = 0x4202; + pub const PTRACE_SETSIGINFO: PtraceRequest = 0x4203; + pub const PTRACE_GETREGSET: PtraceRequest = 0x4204; + pub const PTRACE_SETREGSET: PtraceRequest = 0x4205; + pub const PTRACE_SEIZE: PtraceRequest = 0x4206; + pub const PTRACE_INTERRUPT: PtraceRequest = 0x4207; + pub const PTRACE_LISTEN: PtraceRequest = 0x4208; + pub const PTRACE_PEEKSIGINFO: PtraceRequest = 0x4209; +} + +mod ffi { + use libc::{pid_t, c_int, c_long, c_void}; + + extern { + pub fn ptrace(request: c_int, pid: pid_t, addr: * const c_void, data: * const c_void) -> c_long; + } +} + +pub fn ptrace(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<i64> { + use self::ptrace::*; + + match request { + PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_PEEKUSER => ptrace_peek(request, pid, addr, data), + _ => ptrace_other(request, pid, addr, data) + } +} + +fn ptrace_peek(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<i64> { + let ret = unsafe { + Errno::clear(); + ffi::ptrace(request, pid, addr, data) + }; + if ret == -1 && Errno::last() != Errno::UnknownErrno { + return Err(Error::Sys(Errno::last())); + } + Ok::<i64, Error>(ret) +} + +fn ptrace_other(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<i64> { + match unsafe { ffi::ptrace(request, pid, addr, data) } { + -1 => Err(Error::Sys(Errno::last())), + _ => Ok(0) + } +} |