Skip to content

Commit e8fc0f4

Browse files
committed
Add WaitStatus::PtraceSyscall for use with PTRACE_O_TRACESYSGOOD
The recommended way to trace syscalls with ptrace is to set the PTRACE_O_TRACESYSGOOD option, to distinguish syscall stops from receiving an actual SIGTRAP. In C, this would cause WSTOPSIG to return SIGTRAP | 0x80, but nix wants to parse that as an actual signal. Add another wait status type for syscall stops (in the language of the ptrace(2) manpage, "PTRACE_EVENT stops" and "Syscall-stops" are different things), and mask out bit 0x80 from signals before trying to parse it. Closes #550
1 parent 7b5dd78 commit e8fc0f4

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

src/sys/wait.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ pub enum WaitStatus {
4646
Stopped(pid_t, Signal),
4747
#[cfg(any(target_os = "linux", target_os = "android"))]
4848
PtraceEvent(pid_t, Signal, c_int),
49+
#[cfg(any(target_os = "linux", target_os = "android"))]
50+
PtraceSyscall(pid_t),
4951
Continued(pid_t),
5052
StillAlive
5153
}
@@ -55,6 +57,7 @@ pub enum WaitStatus {
5557
mod status {
5658
use sys::signal::Signal;
5759
use libc::c_int;
60+
use libc::SIGTRAP;
5861

5962
pub fn exited(status: i32) -> bool {
6063
(status & 0x7F) == 0
@@ -81,7 +84,11 @@ mod status {
8184
}
8285

8386
pub fn stop_signal(status: i32) -> Signal {
84-
Signal::from_c_int((status & 0xFF00) >> 8).unwrap()
87+
Signal::from_c_int((status & 0x7F00) >> 8).unwrap()
88+
}
89+
90+
pub fn syscall_stop(status: i32) -> bool {
91+
((status & 0xFF00) >> 8) == SIGTRAP | 0x80
8592
}
8693

8794
pub fn stop_additional(status: i32) -> c_int {
@@ -195,7 +202,9 @@ fn decode(pid : pid_t, status: i32) -> WaitStatus {
195202
if #[cfg(any(target_os = "linux", target_os = "android"))] {
196203
fn decode_stopped(pid: pid_t, status: i32) -> WaitStatus {
197204
let status_additional = status::stop_additional(status);
198-
if status_additional == 0 {
205+
if status::syscall_stop(status) {
206+
WaitStatus::PtraceSyscall(pid)
207+
} else if status_additional == 0 {
199208
WaitStatus::Stopped(pid, status::stop_signal(status))
200209
} else {
201210
WaitStatus::PtraceEvent(pid, status::stop_signal(status), status::stop_additional(status))

0 commit comments

Comments
 (0)