From cf0a7620df02d5f0faacbe2dbbc83c51bb73f81b Mon Sep 17 00:00:00 2001
From: jD91mZM2 <me@krake.one>
Date: Thu, 15 Aug 2019 14:23:54 +0200
Subject: [PATCH] Add ptrace exit breakpoint

This will let you stop at process exit and inspect it right before the
process dies.
---
 src/context/signal.rs  | 1 -
 src/lib.rs             | 1 -
 src/ptrace.rs          | 8 +++++---
 src/scheme/mod.rs      | 6 +++---
 src/scheme/sys/mod.rs  | 2 +-
 src/syscall/process.rs | 9 ++++++---
 syscall                | 2 +-
 7 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/src/context/signal.rs b/src/context/signal.rs
index 942fb28c..78e165af 100644
--- a/src/context/signal.rs
+++ b/src/context/signal.rs
@@ -1,6 +1,5 @@
 use alloc::sync::Arc;
 use core::mem;
-use syscall::data::PtraceEvent;
 use syscall::flag::{PTRACE_FLAG_IGNORE, PTRACE_STOP_SIGNAL, SIG_DFL, SIG_IGN, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU};
 use syscall::ptrace_event;
 
diff --git a/src/lib.rs b/src/lib.rs
index 24b265af..b7acc714 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -13,7 +13,6 @@
 #![cfg_attr(feature = "clippy", allow(or_fun_call))]
 #![cfg_attr(feature = "clippy", allow(too_many_arguments))]
 #![deny(unreachable_patterns)]
-#![feature(alloc)]
 #![feature(allocator_api)]
 #![feature(asm)]
 #![feature(concat_idents)]
diff --git a/src/ptrace.rs b/src/ptrace.rs
index a720ea3e..b3631969 100644
--- a/src/ptrace.rs
+++ b/src/ptrace.rs
@@ -209,8 +209,8 @@ pub fn set_breakpoint(pid: ContextId, flags: PtraceFlags) {
 /// Wait for the tracee to stop. If an event occurs, it returns a copy
 /// of that. It will still be available for read using recv_event.
 ///
-/// Note: Don't call while holding any locks, this will switch
-/// contexts
+/// Note: Don't call while holding any locks or allocated data, this
+/// will switch contexts and may in fact just never terminate.
 pub fn wait(pid: ContextId) -> Result<()> {
     let tracer: Arc<WaitCondition> = {
         let sessions = sessions();
@@ -238,7 +238,9 @@ pub fn wait(pid: ContextId) -> Result<()> {
 }
 
 /// Notify the tracer and await green flag to continue.
-/// Note: Don't call while holding any locks, this will switch contexts
+///
+/// Note: Don't call while holding any locks or allocated data, this
+/// will switch contexts and may in fact just never terminate.
 pub fn breakpoint_callback(match_flags: PtraceFlags, event: Option<PtraceEvent>) -> Option<PtraceFlags> {
     // Can't hold any locks when executing wait()
     let (tracee, flags) = {
diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs
index 8d2e345e..fbdaba62 100644
--- a/src/scheme/mod.rs
+++ b/src/scheme/mod.rs
@@ -173,7 +173,7 @@ impl SchemeList {
         Ok(to)
     }
 
-    pub fn iter(&self) -> ::alloc::collections::btree_map::Iter<SchemeId, Arc<Box<Scheme + Send + Sync>>> {
+    pub fn iter(&self) -> ::alloc::collections::btree_map::Iter<SchemeId, Arc<Box<dyn Scheme + Send + Sync>>> {
         self.map.iter()
     }
 
@@ -188,7 +188,7 @@ impl SchemeList {
         self.map.get(&id)
     }
 
-    pub fn get_name(&self, ns: SchemeNamespace, name: &[u8]) -> Option<(SchemeId, &Arc<Box<Scheme + Send + Sync>>)> {
+    pub fn get_name(&self, ns: SchemeNamespace, name: &[u8]) -> Option<(SchemeId, &Arc<Box<dyn Scheme + Send + Sync>>)> {
         if let Some(names) = self.names.get(&ns) {
             if let Some(&id) = names.get(name) {
                 return self.get(id).map(|scheme| (id, scheme));
@@ -199,7 +199,7 @@ impl SchemeList {
 
     /// Create a new scheme.
     pub fn insert<F>(&mut self, ns: SchemeNamespace, name: Box<[u8]>, scheme_fn: F) -> Result<SchemeId>
-        where F: Fn(SchemeId) -> Arc<Box<Scheme + Send + Sync>>
+        where F: Fn(SchemeId) -> Arc<Box<dyn Scheme + Send + Sync>>
     {
         if let Some(names) = self.names.get(&ns) {
             if names.contains_key(&name) {
diff --git a/src/scheme/sys/mod.rs b/src/scheme/sys/mod.rs
index ee995117..d12729d7 100644
--- a/src/scheme/sys/mod.rs
+++ b/src/scheme/sys/mod.rs
@@ -27,7 +27,7 @@ struct Handle {
     seek: usize
 }
 
-type SysFn = Fn() -> Result<Vec<u8>> + Send + Sync;
+type SysFn = dyn Fn() -> Result<Vec<u8>> + Send + Sync;
 
 /// System information scheme
 pub struct SysScheme {
diff --git a/src/syscall/process.rs b/src/syscall/process.rs
index 646db9a1..45baf3b1 100644
--- a/src/syscall/process.rs
+++ b/src/syscall/process.rs
@@ -21,12 +21,13 @@ use crate::paging::{ActivePageTable, InactivePageTable, Page, VirtualAddress, PA
 use crate::{ptrace, syscall};
 use crate::scheme::FileHandle;
 use crate::start::usermode;
-use crate::syscall::data::{PtraceEvent, SigAction, Stat};
+use crate::syscall::data::{SigAction, Stat};
 use crate::syscall::error::*;
 use crate::syscall::flag::{CloneFlags, CLONE_VFORK, CLONE_VM, CLONE_FS, CLONE_FILES, CLONE_SIGHAND,
                            CLONE_STACK, MapFlags, PROT_EXEC, PROT_READ, PROT_WRITE, PTRACE_EVENT_CLONE,
-                           SigActionFlags, SIG_DFL, SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK, SIGCONT, SIGTERM,
-                           WaitFlags, WCONTINUED, WNOHANG, WUNTRACED, wifcontinued, wifstopped};
+                           PTRACE_STOP_EXIT, SigActionFlags, SIG_DFL, SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK,
+                           SIGCONT, SIGTERM, WaitFlags, WCONTINUED, WNOHANG, WUNTRACED, wifcontinued,
+                           wifstopped};
 use crate::syscall::ptrace_event;
 use crate::syscall::validate::{validate_slice, validate_slice_mut};
 
@@ -1064,6 +1065,8 @@ pub fn exit(status: usize) -> ! {
             Arc::clone(&context_lock)
         };
 
+        ptrace::breakpoint_callback(PTRACE_STOP_EXIT, Some(ptrace_event!(PTRACE_STOP_EXIT, status)));
+
         let mut close_files = Vec::new();
         let pid = {
             let mut context = context_lock.write();
diff --git a/syscall b/syscall
index 0e1e7d5d..6ba71e7e 160000
--- a/syscall
+++ b/syscall
@@ -1 +1 @@
-Subproject commit 0e1e7d5d36f8c6f045e30c37515d366350eb2122
+Subproject commit 6ba71e7e065d37309b7d5c4fc86835dd350f61b7
-- 
GitLab