Skip to content

Commit

Permalink
support ptrace events for Linux. Fixes nix-rust#434
Browse files Browse the repository at this point in the history
  • Loading branch information
luser committed Nov 4, 2016
1 parent bf00bf2 commit 92a3cf7
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

name = "nix"
description = "Rust friendly bindings to *nix APIs"
version = "0.7.1-pre"
version = "0.8.0-pre"
authors = ["Carl Lerche <[email protected]>"]
homepage = "https://github.com/nix-rust/nix"
repository = "https://github.com/nix-rust/nix"
Expand Down
2 changes: 1 addition & 1 deletion src/sys/ptrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub mod ptrace {
pub const PTRACE_EVENT_EXEC: PtraceEvent = 4;
pub const PTRACE_EVENT_VFORK_DONE: PtraceEvent = 5;
pub const PTRACE_EVENT_EXIT: PtraceEvent = 6;
pub const PTRACE_EVENT_SECCOMP: PtraceEvent = 6;
pub const PTRACE_EVENT_SECCOMP: PtraceEvent = 7;
pub const PTRACE_EVENT_STOP: PtraceEvent = 128;

pub type PtraceOptions = c_int;
Expand Down
61 changes: 59 additions & 2 deletions src/sys/wait.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use libc::{self, pid_t, c_int};
use {Errno, Result};

#[cfg(any(target_os = "linux",
target_os = "android"))]
use sys::ptrace::ptrace::{PTRACE_EVENT_FORK, PTRACE_EVENT_VFORK, PTRACE_EVENT_CLONE, PTRACE_EVENT_EXEC, PTRACE_EVENT_VFORK_DONE, PTRACE_EVENT_EXIT, PTRACE_EVENT_SECCOMP, PTRACE_EVENT_STOP};
use sys::signal::Signal;

mod ffi {
Expand Down Expand Up @@ -39,19 +42,54 @@ bitflags!(
target_os = "android"))]
const WSTOPPED: WaitPidFlag = WUNTRACED;

#[cfg(any(target_os = "linux",
target_os = "android"))]
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
#[repr(i32)]
pub enum PtraceEvent {
Fork = PTRACE_EVENT_FORK,
Vfork = PTRACE_EVENT_VFORK,
Clone = PTRACE_EVENT_CLONE,
Exec = PTRACE_EVENT_EXEC,
VforkDone = PTRACE_EVENT_VFORK_DONE,
Exit = PTRACE_EVENT_EXIT,
Seccomp = PTRACE_EVENT_SECCOMP,
Stop = PTRACE_EVENT_STOP,
}

#[cfg(any(target_os = "linux",
target_os = "android"))]
impl PtraceEvent {
#[inline]
pub fn from_c_int(event: libc::c_int) -> Option<PtraceEvent> {
use std::mem;

if (event >= PTRACE_EVENT_FORK && event <= PTRACE_EVENT_SECCOMP) || event == PTRACE_EVENT_STOP {
Some(unsafe { mem::transmute(event) })
} else {
None
}
}
}

#[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum WaitStatus {
Exited(pid_t, i8),
Signaled(pid_t, Signal, bool),
Stopped(pid_t, Signal),
#[cfg(any(target_os = "linux",
target_os = "android"))]
StoppedPtraceEvent(pid_t, PtraceEvent),
Continued(pid_t),
StillAlive
}

#[cfg(any(target_os = "linux",
target_os = "android"))]
mod status {
use libc::pid_t;
use sys::signal::Signal;
use super::{PtraceEvent, WaitStatus};

pub fn exited(status: i32) -> bool {
(status & 0x7F) == 0
Expand All @@ -76,11 +114,19 @@ mod status {
pub fn stopped(status: i32) -> bool {
(status & 0xff) == 0x7f
}

pub fn stop_signal(status: i32) -> Signal {
Signal::from_c_int((status & 0xFF00) >> 8).unwrap()
}

pub fn decode_ptrace_event(pid: pid_t, status: i32) -> Option<WaitStatus> {
if stop_signal(status) == Signal::SIGTRAP {
PtraceEvent::from_c_int((status & 0xFF0000) >> 16)
.map(|event| WaitStatus::StoppedPtraceEvent(pid, event))
} else {
None
}
}

pub fn continued(status: i32) -> bool {
status == 0xFFFF
}
Expand All @@ -89,6 +135,7 @@ mod status {
#[cfg(any(target_os = "macos",
target_os = "ios"))]
mod status {
use libc::pid_t;
use sys::signal::{Signal,SIGCONT};

const WCOREFLAG: i32 = 0x80;
Expand All @@ -114,6 +161,10 @@ mod status {
wstatus(status) == WSTOPPED && stop_signal(status) != SIGCONT
}

pub fn decode_ptrace_event(pid: pid_t, status: i32) -> Option<WaitStatus> {
None
}

pub fn exited(status: i32) -> bool {
wstatus(status) == 0
}
Expand All @@ -136,6 +187,7 @@ mod status {
target_os = "dragonfly",
target_os = "netbsd"))]
mod status {
use libc::pid_t;
use sys::signal::Signal;

const WCOREFLAG: i32 = 0x80;
Expand All @@ -153,6 +205,10 @@ mod status {
Signal::from_c_int(status >> 8).unwrap()
}

pub fn decode_ptrace_event(pid: pid_t, status: i32) -> Option<WaitStatus> {
None
}

pub fn signaled(status: i32) -> bool {
wstatus(status) != WSTOPPED && wstatus(status) != 0 && status != 0x13
}
Expand Down Expand Up @@ -184,7 +240,8 @@ fn decode(pid : pid_t, status: i32) -> WaitStatus {
} else if status::signaled(status) {
WaitStatus::Signaled(pid, status::term_signal(status), status::dumped_core(status))
} else if status::stopped(status) {
WaitStatus::Stopped(pid, status::stop_signal(status))
status::decode_ptrace_event(pid, status)
.unwrap_or_else(|| WaitStatus::Stopped(pid, status::stop_signal(status)))
} else {
assert!(status::continued(status));
WaitStatus::Continued(pid)
Expand Down

0 comments on commit 92a3cf7

Please sign in to comment.