Skip to content

Commit 92a3cf7

Browse files
committed
support ptrace events for Linux. Fixes nix-rust#434
1 parent bf00bf2 commit 92a3cf7

File tree

3 files changed

+61
-4
lines changed

3 files changed

+61
-4
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
name = "nix"
44
description = "Rust friendly bindings to *nix APIs"
5-
version = "0.7.1-pre"
5+
version = "0.8.0-pre"
66
authors = ["Carl Lerche <me@carllerche.com>"]
77
homepage = "https://github.com/nix-rust/nix"
88
repository = "https://github.com/nix-rust/nix"

src/sys/ptrace.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub mod ptrace {
4949
pub const PTRACE_EVENT_EXEC: PtraceEvent = 4;
5050
pub const PTRACE_EVENT_VFORK_DONE: PtraceEvent = 5;
5151
pub const PTRACE_EVENT_EXIT: PtraceEvent = 6;
52-
pub const PTRACE_EVENT_SECCOMP: PtraceEvent = 6;
52+
pub const PTRACE_EVENT_SECCOMP: PtraceEvent = 7;
5353
pub const PTRACE_EVENT_STOP: PtraceEvent = 128;
5454

5555
pub type PtraceOptions = c_int;

src/sys/wait.rs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use libc::{self, pid_t, c_int};
22
use {Errno, Result};
33

4+
#[cfg(any(target_os = "linux",
5+
target_os = "android"))]
6+
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};
47
use sys::signal::Signal;
58

69
mod ffi {
@@ -39,19 +42,54 @@ bitflags!(
3942
target_os = "android"))]
4043
const WSTOPPED: WaitPidFlag = WUNTRACED;
4144

45+
#[cfg(any(target_os = "linux",
46+
target_os = "android"))]
47+
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
48+
#[repr(i32)]
49+
pub enum PtraceEvent {
50+
Fork = PTRACE_EVENT_FORK,
51+
Vfork = PTRACE_EVENT_VFORK,
52+
Clone = PTRACE_EVENT_CLONE,
53+
Exec = PTRACE_EVENT_EXEC,
54+
VforkDone = PTRACE_EVENT_VFORK_DONE,
55+
Exit = PTRACE_EVENT_EXIT,
56+
Seccomp = PTRACE_EVENT_SECCOMP,
57+
Stop = PTRACE_EVENT_STOP,
58+
}
59+
60+
#[cfg(any(target_os = "linux",
61+
target_os = "android"))]
62+
impl PtraceEvent {
63+
#[inline]
64+
pub fn from_c_int(event: libc::c_int) -> Option<PtraceEvent> {
65+
use std::mem;
66+
67+
if (event >= PTRACE_EVENT_FORK && event <= PTRACE_EVENT_SECCOMP) || event == PTRACE_EVENT_STOP {
68+
Some(unsafe { mem::transmute(event) })
69+
} else {
70+
None
71+
}
72+
}
73+
}
74+
4275
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
4376
pub enum WaitStatus {
4477
Exited(pid_t, i8),
4578
Signaled(pid_t, Signal, bool),
4679
Stopped(pid_t, Signal),
80+
#[cfg(any(target_os = "linux",
81+
target_os = "android"))]
82+
StoppedPtraceEvent(pid_t, PtraceEvent),
4783
Continued(pid_t),
4884
StillAlive
4985
}
5086

5187
#[cfg(any(target_os = "linux",
5288
target_os = "android"))]
5389
mod status {
90+
use libc::pid_t;
5491
use sys::signal::Signal;
92+
use super::{PtraceEvent, WaitStatus};
5593

5694
pub fn exited(status: i32) -> bool {
5795
(status & 0x7F) == 0
@@ -76,11 +114,19 @@ mod status {
76114
pub fn stopped(status: i32) -> bool {
77115
(status & 0xff) == 0x7f
78116
}
79-
80117
pub fn stop_signal(status: i32) -> Signal {
81118
Signal::from_c_int((status & 0xFF00) >> 8).unwrap()
82119
}
83120

121+
pub fn decode_ptrace_event(pid: pid_t, status: i32) -> Option<WaitStatus> {
122+
if stop_signal(status) == Signal::SIGTRAP {
123+
PtraceEvent::from_c_int((status & 0xFF0000) >> 16)
124+
.map(|event| WaitStatus::StoppedPtraceEvent(pid, event))
125+
} else {
126+
None
127+
}
128+
}
129+
84130
pub fn continued(status: i32) -> bool {
85131
status == 0xFFFF
86132
}
@@ -89,6 +135,7 @@ mod status {
89135
#[cfg(any(target_os = "macos",
90136
target_os = "ios"))]
91137
mod status {
138+
use libc::pid_t;
92139
use sys::signal::{Signal,SIGCONT};
93140

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

164+
pub fn decode_ptrace_event(pid: pid_t, status: i32) -> Option<WaitStatus> {
165+
None
166+
}
167+
117168
pub fn exited(status: i32) -> bool {
118169
wstatus(status) == 0
119170
}
@@ -136,6 +187,7 @@ mod status {
136187
target_os = "dragonfly",
137188
target_os = "netbsd"))]
138189
mod status {
190+
use libc::pid_t;
139191
use sys::signal::Signal;
140192

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

208+
pub fn decode_ptrace_event(pid: pid_t, status: i32) -> Option<WaitStatus> {
209+
None
210+
}
211+
156212
pub fn signaled(status: i32) -> bool {
157213
wstatus(status) != WSTOPPED && wstatus(status) != 0 && status != 0x13
158214
}
@@ -184,7 +240,8 @@ fn decode(pid : pid_t, status: i32) -> WaitStatus {
184240
} else if status::signaled(status) {
185241
WaitStatus::Signaled(pid, status::term_signal(status), status::dumped_core(status))
186242
} else if status::stopped(status) {
187-
WaitStatus::Stopped(pid, status::stop_signal(status))
243+
status::decode_ptrace_event(pid, status)
244+
.unwrap_or_else(|| WaitStatus::Stopped(pid, status::stop_signal(status)))
188245
} else {
189246
assert!(status::continued(status));
190247
WaitStatus::Continued(pid)

0 commit comments

Comments
 (0)