|
| 1 | +use {Error, Result}; |
| 2 | +use errno::Errno; |
| 3 | +use libc::{pid_t, c_void}; |
| 4 | + |
| 5 | +#[cfg(all(target_os = "linux", |
| 6 | + any(target_arch = "x86", |
| 7 | + target_arch = "x86_64", |
| 8 | + target_arch = "arm")), |
| 9 | + )] |
| 10 | +pub mod ptrace { |
| 11 | + use libc::c_int; |
| 12 | + |
| 13 | + pub type PtraceRequest = c_int; |
| 14 | + |
| 15 | + pub const PTRACE_TRACEME: PtraceRequest = 0; |
| 16 | + pub const PTRACE_PEEKTEXT: PtraceRequest = 1; |
| 17 | + pub const PTRACE_PEEKDATA: PtraceRequest = 2; |
| 18 | + pub const PTRACE_PEEKUSER: PtraceRequest = 3; |
| 19 | + pub const PTRACE_POKETEXT: PtraceRequest = 4; |
| 20 | + pub const PTRACE_POKEDATA: PtraceRequest = 5; |
| 21 | + pub const PTRACE_POKEUSER: PtraceRequest = 6; |
| 22 | + pub const PTRACE_CONT: PtraceRequest = 7; |
| 23 | + pub const PTRACE_KILL: PtraceRequest = 8; |
| 24 | + pub const PTRACE_SINGLESTEP: PtraceRequest = 9; |
| 25 | + pub const PTRACE_GETREGS: PtraceRequest = 12; |
| 26 | + pub const PTRACE_SETREGS: PtraceRequest = 13; |
| 27 | + pub const PTRACE_GETFPREGS: PtraceRequest = 14; |
| 28 | + pub const PTRACE_SETFPREGS: PtraceRequest = 15; |
| 29 | + pub const PTRACE_ATTACH: PtraceRequest = 16; |
| 30 | + pub const PTRACE_DETACH: PtraceRequest = 17; |
| 31 | + pub const PTRACE_GETFPXREGS: PtraceRequest = 18; |
| 32 | + pub const PTRACE_SETFPXREGS: PtraceRequest = 19; |
| 33 | + pub const PTRACE_SYSCALL: PtraceRequest = 24; |
| 34 | + pub const PTRACE_SETOPTIONS: PtraceRequest = 0x4200; |
| 35 | + pub const PTRACE_GETEVENTMSG: PtraceRequest = 0x4201; |
| 36 | + pub const PTRACE_GETSIGINFO: PtraceRequest = 0x4202; |
| 37 | + pub const PTRACE_SETSIGINFO: PtraceRequest = 0x4203; |
| 38 | + pub const PTRACE_GETREGSET: PtraceRequest = 0x4204; |
| 39 | + pub const PTRACE_SETREGSET: PtraceRequest = 0x4205; |
| 40 | + pub const PTRACE_SEIZE: PtraceRequest = 0x4206; |
| 41 | + pub const PTRACE_INTERRUPT: PtraceRequest = 0x4207; |
| 42 | + pub const PTRACE_LISTEN: PtraceRequest = 0x4208; |
| 43 | + pub const PTRACE_PEEKSIGINFO: PtraceRequest = 0x4209; |
| 44 | +} |
| 45 | + |
| 46 | +mod ffi { |
| 47 | + use libc::{pid_t, c_int, c_long, c_void}; |
| 48 | + |
| 49 | + extern { |
| 50 | + pub fn ptrace(request: c_int, pid: pid_t, addr: * const c_void, data: * const c_void) -> c_long; |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +pub fn ptrace(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<i64> { |
| 55 | + use self::ptrace::*; |
| 56 | + |
| 57 | + match request { |
| 58 | + PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_PEEKUSER => ptrace_peek(request, pid, addr, data), |
| 59 | + _ => ptrace_other(request, pid, addr, data) |
| 60 | + } |
| 61 | +} |
| 62 | + |
| 63 | +fn ptrace_peek(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<i64> { |
| 64 | + let ret = unsafe { |
| 65 | + Errno::clear(); |
| 66 | + ffi::ptrace(request, pid, addr, data) |
| 67 | + }; |
| 68 | + if ret == -1 && Errno::last() != Errno::UnknownErrno { |
| 69 | + return Err(Error::Sys(Errno::last())); |
| 70 | + } |
| 71 | + Ok::<i64, Error>(ret) |
| 72 | +} |
| 73 | + |
| 74 | +fn ptrace_other(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<i64> { |
| 75 | + match unsafe { ffi::ptrace(request, pid, addr, data) } { |
| 76 | + -1 => Err(Error::Sys(Errno::last())), |
| 77 | + _ => Ok(0) |
| 78 | + } |
| 79 | +} |
0 commit comments