Verified Commit ed1536d6 authored by jD91mZM2's avatar jD91mZM2
Browse files

WIP(ptrace): Test event system

parent 532621cb
......@@ -206,7 +206,7 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.1.56"
source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace#49dd22260bd8bada8b835d12ee8e460a5a1c4af4"
source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace#eddcb80eb7c2d43dedf0ba2ee514b54b0b8fafc7"
[[package]]
name = "rustc-serialize"
......@@ -238,7 +238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "strace"
version = "0.1.0"
source = "git+https://gitlab.redox-os.org/redox-os/strace-redox#e64d9fb900c825e6f370da7d4bef89f10adff475"
source = "git+https://gitlab.redox-os.org/redox-os/strace-redox#b5740938279dbc8334e361d3a8bfc9a4ca64c9ce"
dependencies = [
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace)",
......
......@@ -6,6 +6,7 @@ edition = "2018"
[dependencies]
x86 = "0.7"
# redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" }
redox_syscall = { git = "https://gitlab.redox-os.org/jD91mZM2/syscall.git", branch = "ptrace" }
# redox_syscall = { path = "/home/user/redox-nix/redox/kernel/syscall" }
strace = { git = "https://gitlab.redox-os.org/redox-os/strace-redox" }
......
......@@ -56,6 +56,7 @@ fn page_fault_test() -> Result<(), String> {
pub fn ptrace() -> Result<(), String> {
use std::{
fs::File,
io,
mem,
os::unix::io::{AsRawFd, FromRawFd, RawFd}
};
......@@ -98,12 +99,39 @@ pub fn ptrace() -> Result<(), String> {
fsqrt
add rsp, 8 // pop 1 item, ignore value
// Make sure event is raised when child forks
mov rax, 120 // SYS_CLONE
xor rdi, rdi
syscall
test rax, rax
je .exit
// Wait for child process, to make sure an ignored process is continued
mov rdi, rax
mov rax, 7
push 0
mov rsi, rsp
add rsp, 8
xor rdx, rdx
syscall
// Another fork attempt, but test what happens when not ignored
mov rax, 120 // SYS_CLONE
xor rdi, rdi
syscall
test rax, rax
je .exit
// Test behavior if tracer aborts a breakpoint before it's reached
call wait_for_a_while
mov rax, 158 // SYS_YIELD
syscall
mov rax, 20 // GETPID
syscall
mov rdi, rax
mov rax, 37 // SYS_KILL
mov rsi, 19 // SIGSTOP
syscall
......@@ -111,20 +139,22 @@ pub fn ptrace() -> Result<(), String> {
// Test nonblock & sysemu
call wait_for_a_while
.exit:
mov rax, 20 // GETPID
syscall
mov rdi, rax
mov rax, 1 // SYS_EXIT
syscall
ud2
// Without a jump, this code is unreachable. Therefore function definitions go here.
wait_for_a_while:
mov rax, 4294967295
.loop:
.wait_for_a_while_loop:
sub rax, 1
jne .loop
jne .wait_for_a_while_loop
ret
"
: : : : "intel", "volatile"
......@@ -202,6 +232,36 @@ pub fn ptrace() -> Result<(), String> {
assert_eq!(fs, [f, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]);
assert!((f - 5.65685424949238).abs() < std::f64::EPSILON);
println!("Testing fork event");
let mut handler = e(tracer.next_event(Stop::COMPLETION))?.ok_or("Program completed without yielding fork event")?;
let events = e(handler.iter().collect::<io::Result<Vec<_>>>())?;
assert_eq!(events.len(), 1);
match events[0] {
PtraceEvent::Clone(pid) => println!("Got clone: {}", pid),
ref e => return Err(format!("Wrong event type: {:?}", e))
}
println!("Testing fork event - but actually handling the fork");
handler = e(handler.retry())?.ok_or("Program completed without yielding fork event")?;
let events = e(handler.iter().collect::<io::Result<Vec<_>>>())?;
assert_eq!(events.len(), 1);
match events[0] {
PtraceEvent::Clone(pid) => {
let mut child = e(Tracer::attach(pid))?;
println!("-> Fork attached (PID {})", pid);
assert_eq!(e(e(child.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_GETPID);
e(child.next(Stop::SYSCALL))?;
println!("-> Fork executed GETPID");
assert_eq!(e(e(child.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_EXIT);
assert_eq!(child.next(Stop::COMPLETION).unwrap_err().raw_os_error(), Some(syscall::ESRCH));
println!("-> Fork executed EXIT");
},
ref e => return Err(format!("Wrong event type: {:?}", e))
}
// Activate nonblock
let mut tracer = e(tracer.nonblocking())?;
......@@ -224,8 +284,12 @@ pub fn ptrace() -> Result<(), String> {
println!("Tracee RAX: {}", e(tracer.regs.get_int())?.rax);
}
println!("Waiting... Five times. To make sure it doesn't get stuck forever");
for _ in 0..5 {
e(tracer.wait())?;
}
println!("Overriding GETPID call...");
e(tracer.wait())?;
let mut regs = e(tracer.regs.get_int())?;
assert_eq!(regs.rax, syscall::SYS_GETPID);
regs.rax = 123;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment