diff --git a/src/arch/x86_64/interrupt/syscall.rs b/src/arch/x86_64/interrupt/syscall.rs index ebc3c528c1e72294dd5fc4ade15fa499e9f32729..6b9dfe615db217d6f51180a3dc9f23d84f1998fd 100644 --- a/src/arch/x86_64/interrupt/syscall.rs +++ b/src/arch/x86_64/interrupt/syscall.rs @@ -21,7 +21,8 @@ macro_rules! with_interrupt_stack { unsafe fn $wrapped(stack: *mut InterruptStack) { let _guard = ptrace::set_process_regs(stack); - let is_sysemu = ptrace::breakpoint_callback(::syscall::PTRACE_SYSCALL); + let is_sysemu = ptrace::breakpoint_callback(syscall::flag::PTRACE_SYSCALL) + .map(|fl| fl & syscall::flag::PTRACE_SYSEMU == syscall::flag::PTRACE_SYSEMU); if !is_sysemu.unwrap_or(false) { // If not on a sysemu breakpoint let $stack = &mut *stack; diff --git a/src/context/signal.rs b/src/context/signal.rs index f7db1ae3fc31774ce81d3bc968d42022e1fe7a65..d5d2ff18cb3e48918ca16cb2532148fa6856b648 100644 --- a/src/context/signal.rs +++ b/src/context/signal.rs @@ -3,8 +3,9 @@ use core::mem; use crate::context::{contexts, switch, Status, WaitpidKey}; use crate::start::usermode; -use crate::syscall; -use crate::syscall::flag::{SIG_DFL, SIG_IGN, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU}; +use crate::{ptrace, syscall}; +use crate::syscall::flag::{PTRACE_EVENT_SIGNAL, PTRACE_SIGNAL, SIG_DFL, SIG_IGN, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU}; +use crate::syscall::data::{PtraceEvent, PtraceEventData}; pub fn is_user_handled(handler: Option<extern "C" fn(usize)>) -> bool { let handler = handler.map(|ptr| ptr as usize).unwrap_or(0); @@ -20,6 +21,11 @@ pub extern "C" fn signal_handler(sig: usize) { actions[sig] }; + ptrace::send_event(PtraceEvent { + tag: PTRACE_EVENT_SIGNAL, + data: PtraceEventData { signal: sig } + }); + let handler = action.sa_handler.map(|ptr| ptr as usize).unwrap_or(0); if handler == SIG_DFL { match sig { @@ -94,6 +100,8 @@ pub extern "C" fn signal_handler(sig: usize) { } else { // println!("Call {:X}", handler); + ptrace::breakpoint_callback(PTRACE_SIGNAL); + unsafe { let mut sp = crate::USER_SIGSTACK_OFFSET + crate::USER_SIGSTACK_SIZE - 256; diff --git a/src/ptrace.rs b/src/ptrace.rs index ae7d9b18a2c480bb53451804df134ec59f1daec5..3f3390f492b7a6ee1b4bdb32737a3723f35c44dc 100644 --- a/src/ptrace.rs +++ b/src/ptrace.rs @@ -114,7 +114,7 @@ pub fn close_session(pid: ContextId) { } /// Trigger a notification to the event: scheme -pub fn proc_trigger_event(file_id: usize, flags: usize) { +fn proc_trigger_event(file_id: usize, flags: usize) { event::trigger(proc::PROC_SCHEME_ID.load(Ordering::SeqCst), file_id, flags); } @@ -244,9 +244,9 @@ pub fn wait(pid: ContextId) -> Result<Option<PtraceEvent>> { /// Notify the tracer and await green flag to continue. /// Note: Don't call while holding any locks, this will switch contexts -pub fn breakpoint_callback(flags: u8) -> Option<bool> { +pub fn breakpoint_callback(match_flags: u8) -> Option<u8> { // Can't hold any locks when executing wait() - let (tracee, sysemu) = { + let (tracee, flags) = { let contexts = context::contexts(); let context = contexts.current()?; let context = context.read(); @@ -258,7 +258,7 @@ pub fn breakpoint_callback(flags: u8) -> Option<bool> { // TODO: How should singlesteps interact with syscalls? How // does Linux handle this? - if breakpoint.flags & PTRACE_OPERATIONMASK != flags & PTRACE_OPERATIONMASK { + if breakpoint.flags & PTRACE_OPERATIONMASK != match_flags & PTRACE_OPERATIONMASK { return None; } @@ -271,13 +271,13 @@ pub fn breakpoint_callback(flags: u8) -> Option<bool> { ( Arc::clone(&breakpoint.tracee), - breakpoint.flags & PTRACE_SYSEMU == PTRACE_SYSEMU + breakpoint.flags ) }; while !tracee.wait() {} - Some(sysemu) + Some(flags) } /// Call when a context is closed to alert any tracers diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index 3e7d34a115650c3c6cb08785b1fad1a05897e864..5a04f9d55479a2b881ae11307eefb059c93d5ff4 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -374,7 +374,7 @@ impl Scheme for ProcScheme { match op & PTRACE_OPERATIONMASK { PTRACE_CONT => { ptrace::cont(pid); }, - PTRACE_SYSCALL | PTRACE_SINGLESTEP => { // <- not a bitwise OR + PTRACE_SYSCALL | PTRACE_SINGLESTEP | PTRACE_SIGNAL => { // <- not a bitwise OR singlestep = op & PTRACE_OPERATIONMASK == PTRACE_SINGLESTEP; ptrace::set_breakpoint(pid, op); }, diff --git a/src/syscall/process.rs b/src/syscall/process.rs index 9a74c0a23ac3d45c9f62b2975e79354d4e62af9f..e683b4cfc644beeaff9d50765ad20fd31fcbbbd7 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -21,7 +21,7 @@ use crate::paging::{ActivePageTable, InactivePageTable, Page, VirtualAddress, PA use crate::ptrace; use crate::scheme::FileHandle; use crate::start::usermode; -use crate::syscall::data::{PtraceEvent, PtraceEventContent, SigAction, Stat}; +use crate::syscall::data::{PtraceEvent, PtraceEventData, SigAction, Stat}; use crate::syscall::error::*; use crate::syscall::flag::{CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, CLONE_SIGHAND, CLONE_STACK, PROT_EXEC, PROT_READ, PROT_WRITE, PTRACE_EVENT_CLONE, @@ -587,7 +587,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> { let ptrace_event = PtraceEvent { tag: PTRACE_EVENT_CLONE, - data: PtraceEventContent { + data: PtraceEventData { clone: pid.into() } }; @@ -1124,9 +1124,6 @@ pub fn exit(status: usize) -> ! { (vfork, children) }; - // Alert any tracers waiting for process (important: AFTER sending waitpid event) - ptrace::close_tracee(pid); - { let contexts = context::contexts(); if let Some(parent_lock) = contexts.get(ppid) { @@ -1153,6 +1150,9 @@ pub fn exit(status: usize) -> ! { } } + // Alert any tracers waiting for process (important: AFTER sending waitpid event) + ptrace::close_tracee(pid); + if pid == ContextId::from(1) { println!("Main kernel thread exited with status {:X}", status); diff --git a/syscall b/syscall index f3bb1f7b68bc8e5544857781de9eb8729b2843f4..844650c4fb9725cd9029de6277826bfe0fb19909 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit f3bb1f7b68bc8e5544857781de9eb8729b2843f4 +Subproject commit 844650c4fb9725cd9029de6277826bfe0fb19909