diff --git a/Cargo.lock b/Cargo.lock index 3b779406032ee7ae5c3b076400618cd006f787a1..0ff818745a76946e3fc5b3537a0e3882987e2f9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,7 +163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "redox_syscall" version = "0.1.56" -source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall?branch=ptrace-6#a0581db1fa26da148ad6bb35975be084d1504f58" +source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall?branch=ptrace-6#51f0ef2826ef2b0369766c8f23c8069ae0a56846" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index e57b8d5ca744427e6e4c9c801981bdf04ba6edab..0afc424d7c8409856f73fa4f3047ef55430698bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,7 @@ sc = "0.2.2" [target.'cfg(target_os = "redox")'.dependencies] redox_syscall = { git = "https://gitlab.redox-os.org/jD91mZM2/syscall", branch = "ptrace-6" } +# redox_syscall = { path = "/home/user/redox-nix/redox/kernel/syscall" } spin = "0.4.10" [features] diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 3b77c4fa5fb3ec8ea27034dd8476da818974e839..56c6b9e22280e556d1346c4deb0da77b5c7949d7 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -2,7 +2,7 @@ use core::{mem, ptr, result::Result as CoreResult, slice}; use syscall::{ self, data::{Map, Stat as redox_stat, StatVfs as redox_statvfs, TimeSpec as redox_timespec}, - Result, + PtraceEvent, Result, }; use crate::{ @@ -947,8 +947,10 @@ impl Pal for Sys { let mut sessions = state.sessions.lock(); if let Ok(session) = ptrace::get_session(&mut sessions, pid) { if options & sys_wait::WNOHANG != sys_wait::WNOHANG { - let _ = - (&mut &session.tracer).write(&syscall::PTRACE_FLAG_WAIT.bits().to_ne_bytes()); + let _ = (&mut &session.tracer).write(&syscall::PTRACE_FLAG_WAIT); + let mut _event = PtraceEvent::default(); + let _ = (&mut &session.tracer).read(&mut _event); + res = Some(e(inner( &mut status, options | sys_wait::WNOHANG | sys_wait::WUNTRACED, diff --git a/src/platform/redox/ptrace.rs b/src/platform/redox/ptrace.rs index 2e20f144909197e8c7c8cc27f52d4baaa7b0c045..9672f32707021410ff25c313d1fb436cfe84dd99 100644 --- a/src/platform/redox/ptrace.rs +++ b/src/platform/redox/ptrace.rs @@ -17,10 +17,11 @@ use core::mem; use syscall; pub struct Session { - pub tracer: File, + pub first: bool, + pub fpregs: File, pub mem: File, pub regs: File, - pub fpregs: File, + pub tracer: File, } pub struct State { pub sessions: Mutex<BTreeMap<pid_t, Session>>, @@ -45,13 +46,17 @@ pub fn is_traceme(pid: pid_t) -> bool { ) .is_ok() } -pub fn get_session(sessions: &mut BTreeMap<pid_t, Session>, pid: pid_t) -> io::Result<&Session> { +pub fn get_session( + sessions: &mut BTreeMap<pid_t, Session>, + pid: pid_t, +) -> io::Result<&mut Session> { const NEW_FLAGS: c_int = fcntl::O_RDWR | fcntl::O_CLOEXEC; match sessions.entry(pid) { Entry::Vacant(entry) => { if is_traceme(pid) { Ok(entry.insert(Session { + first: true, tracer: File::open( &CString::new(format!("proc:{}/trace", pid)).unwrap(), NEW_FLAGS | fcntl::O_NONBLOCK, @@ -110,21 +115,25 @@ fn inner_ptrace( Sys::kill(pid, signal::SIGCONT as _); // TODO: Translate errors - let syscall = - syscall::PTRACE_STOP_PRE_SYSCALL.bits() | syscall::PTRACE_STOP_POST_SYSCALL.bits(); - (&mut &session.tracer).write( - &match request { - sys_ptrace::PTRACE_CONT => 0, - sys_ptrace::PTRACE_SINGLESTEP => syscall::PTRACE_STOP_SINGLESTEP.bits(), - sys_ptrace::PTRACE_SYSCALL => syscall, - sys_ptrace::PTRACE_SYSEMU => syscall::PTRACE_FLAG_SYSEMU.bits() | syscall, - sys_ptrace::PTRACE_SYSEMU_SINGLESTEP => { - syscall::PTRACE_FLAG_SYSEMU.bits() | syscall::PTRACE_STOP_SINGLESTEP.bits() - } - _ => unreachable!("unhandled ptrace request type {}", request), + let syscall = syscall::PTRACE_STOP_PRE_SYSCALL | syscall::PTRACE_STOP_POST_SYSCALL; + (&mut &session.tracer).write(&match request { + sys_ptrace::PTRACE_CONT => syscall::PtraceFlags::empty(), + sys_ptrace::PTRACE_SINGLESTEP => syscall::PTRACE_STOP_SINGLESTEP, + // Skip the first post-syscall when connected + sys_ptrace::PTRACE_SYSCALL if session.first => syscall::PTRACE_STOP_PRE_SYSCALL, + sys_ptrace::PTRACE_SYSCALL => syscall, + // Skip the first post-syscall when connected + sys_ptrace::PTRACE_SYSEMU if session.first => { + syscall::PTRACE_FLAG_SYSEMU | syscall::PTRACE_STOP_PRE_SYSCALL + } + sys_ptrace::PTRACE_SYSEMU => syscall::PTRACE_FLAG_SYSEMU | syscall, + sys_ptrace::PTRACE_SYSEMU_SINGLESTEP => { + syscall::PTRACE_FLAG_SYSEMU | syscall::PTRACE_STOP_SINGLESTEP } - .to_ne_bytes(), - )?; + _ => unreachable!("unhandled ptrace request type {}", request), + })?; + + session.first = false; Ok(0) } sys_ptrace::PTRACE_GETREGS => { diff --git a/tests/ptrace.c b/tests/ptrace.c index 4a5c5d4d78e328276f26064992181c405875c2c7..bb918d1112e267530e57f54c5b40759bd60fc204 100644 --- a/tests/ptrace.c +++ b/tests/ptrace.c @@ -48,28 +48,32 @@ int main() { int status; while (true) { - // Pre-syscall: + puts("----- Pre-syscall -----"); result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL); ERROR_IF(ptrace, result, == -1); UNEXP_IF(ptrace, result, != 0); + puts("Wait..."); result = waitpid(pid, &status, 0); ERROR_IF(waitpid, result, == -1); if (WIFEXITED(status)) { break; } struct user_regs_struct regs; + puts("Get regs"); result = ptrace(PTRACE_GETREGS, pid, NULL, ®s); ERROR_IF(ptrace, result, == -1); if (regs.orig_rax == SYS_write || regs.orig_rax == SYS_write) { regs.rdi = 2; + puts("Set regs"); result = ptrace(PTRACE_SETREGS, pid, NULL, ®s); ERROR_IF(ptrace, result, == -1); } - // Post-syscall: + puts("Post-syscall"); result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL); ERROR_IF(ptrace, result, == -1); UNEXP_IF(ptrace, result, != 0); + puts("Wait..."); result = waitpid(pid, &status, 0); ERROR_IF(waitpid, result, == -1); if (WIFEXITED(status)) { break; }