diff options
author | Daniel McKenna <danielmckenna93@gmail.com> | 2017-06-01 21:34:36 +0100 |
---|---|---|
committer | xd009642 <danielmckenna93@gmail.com> | 2017-06-13 18:16:57 +0100 |
commit | 43a29431b63516b23016aae76d3c15bf083f091c (patch) | |
tree | e4c7221df798f533ed93819281457507b171bd67 /src/sys/ptrace.rs | |
parent | 6783ffc206de568ca8867abe6133bdad9110211e (diff) | |
download | nix-43a29431b63516b23016aae76d3c15bf083f091c.zip |
Added ptrace utilities.
Some ptrace functions return structures through the data argument. This commit adds utilities to return data through this mechanism and function specialisations for a few of these functions (getting event messages or the siginfo_t struct). Once the next version of libc is released these utilities will be expanded to include the fpregs and user_regs structs.
Ptrace requests that are now satisfied by a more specific public function will return an unsupported operation error. This has involved adding an UnsupportedOperation to the nix::Error enum and removed the mapping from Error to Errno and from Error to std::io::Error.
Diffstat (limited to 'src/sys/ptrace.rs')
-rw-r--r-- | src/sys/ptrace.rs | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/src/sys/ptrace.rs b/src/sys/ptrace.rs index edbc9734..bf6ee8bb 100644 --- a/src/sys/ptrace.rs +++ b/src/sys/ptrace.rs @@ -1,5 +1,6 @@ +use std::{mem, ptr}; use {Errno, Error, Result}; -use libc::{pid_t, c_void, c_long}; +use libc::{pid_t, c_void, c_long, siginfo_t}; #[cfg(all(target_os = "linux", any(target_arch = "x86", @@ -71,11 +72,14 @@ mod ffi { } } +/// Performs a ptrace request. If the request in question is provided by a specialised function +/// this function will return an unsupported operation error. pub fn ptrace(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<c_long> { use self::ptrace::*; match request { PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_PEEKUSER => ptrace_peek(request, pid, addr, data), + PTRACE_GETSIGINFO | PTRACE_GETEVENTMSG | PTRACE_SETSIGINFO | PTRACE_SETOPTIONS => Err(Error::UnsupportedOperation), _ => ptrace_other(request, pid, addr, data) } } @@ -91,6 +95,20 @@ fn ptrace_peek(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, da } } +/// Function for ptrace requests that return values from the data field. +/// Some ptrace get requests populate structs or larger elements than c_long +/// and therefore use the data field to return values. This function handles these +/// requests. +fn ptrace_get_data<T>(request: ptrace::PtraceRequest, pid: pid_t) -> Result<T> { + // Creates an uninitialized pointer to store result in + let data: Box<T> = Box::new(unsafe { mem::uninitialized() }); + let data: *mut c_void = unsafe { mem::transmute(data) }; + ptrace(request, pid, ptr::null_mut(), data)?; + // Convert back into the original data format and return unboxed value + let data: Box<T> = unsafe { mem::transmute(data) }; + Ok(*data) +} + fn ptrace_other(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<c_long> { Errno::result(unsafe { ffi::ptrace(request, pid, addr, data) }).map(|_| 0) } @@ -102,3 +120,28 @@ pub fn ptrace_setoptions(pid: pid_t, options: ptrace::PtraceOptions) -> Result<( ptrace(PTRACE_SETOPTIONS, pid, ptr::null_mut(), options as *mut c_void).map(drop) } + +/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)` +pub fn ptrace_getevent(pid: pid_t) -> Result<c_long> { + use self::ptrace::*; + ptrace_get_data::<c_long>(PTRACE_GETEVENTMSG, pid) +} + +/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO,...)` +pub fn ptrace_getsiginfo(pid: pid_t) -> Result<siginfo_t> { + use self::ptrace::*; + ptrace_get_data::<siginfo_t>(PTRACE_GETSIGINFO, pid) +} + +/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)` +pub fn ptrace_setsiginfo(pid: pid_t, sig: &siginfo_t) -> Result<()> { + use self::ptrace::*; + let ret = unsafe{ + Errno::clear(); + ffi::ptrace(PTRACE_SETSIGINFO, pid, ptr::null_mut(), sig as *const _ as *const c_void) + }; + match Errno::result(ret) { + Ok(_) => Ok(()), + Err(e) => Err(e), + } +} |