summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Kain <joekain@gmail.com>2015-06-27 08:22:23 -0700
committerCarl Lerche <me@carllerche.com>2015-07-03 15:06:32 -0700
commita0fc60700f9e8b93e570e51460b10201f721b635 (patch)
tree7d619354e30ad92b009e9a83c1fe4bd3335b39af
parent90bbc63646991ae4b092da60bdcbaef01637cb04 (diff)
downloadnix-a0fc60700f9e8b93e570e51460b10201f721b635.zip
Add support for ptrace
Closes #138
-rw-r--r--src/errno.rs72
-rw-r--r--src/sys/mod.rs7
-rw-r--r--src/sys/ptrace.rs79
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)
+ }
+}