From cdcb34486b6bea4923d1e257f90ce0756c6ac7e4 Mon Sep 17 00:00:00 2001
From: jD91mZM2 <me@krake.one>
Date: Tue, 7 Jul 2020 13:32:10 +0200
Subject: [PATCH] Keep singlestep across signals

---
 src/arch/x86_64/macros.rs |  4 ++++
 src/context/switch.rs     | 12 ++++++++++--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/arch/x86_64/macros.rs b/src/arch/x86_64/macros.rs
index 22fe5a3..5e9002f 100644
--- a/src/arch/x86_64/macros.rs
+++ b/src/arch/x86_64/macros.rs
@@ -323,6 +323,10 @@ impl InterruptStack {
             self.iret.rflags &= !(1 << 8);
         }
     }
+    /// Checks if the trap flag is enabled, see `set_singlestep`
+    pub fn is_singlestep(&self) -> bool {
+        self.iret.rflags & 1 << 8 == 1 << 8
+    }
 }
 
 macro_rules! interrupt_push {
diff --git a/src/context/switch.rs b/src/context/switch.rs
index 6e10825..8516557 100644
--- a/src/context/switch.rs
+++ b/src/context/switch.rs
@@ -1,10 +1,11 @@
 use core::sync::atomic::Ordering;
 
-use crate::context::{arch, contexts, Context, Status, CONTEXT_ID};
 use crate::context::signal::signal_handler;
+use crate::context::{arch, contexts, Context, Status, CONTEXT_ID};
 use crate::gdt;
-use crate::interrupt;
 use crate::interrupt::irq::PIT_TICKS;
+use crate::interrupt;
+use crate::ptrace;
 use crate::time;
 
 unsafe fn update(context: &mut Context, cpu_id: usize) {
@@ -16,6 +17,8 @@ unsafe fn update(context: &mut Context, cpu_id: usize) {
 
     // Restore from signal, must only be done from another context to avoid overwriting the stack!
     if context.ksig_restore && ! context.running {
+        let was_singlestep = ptrace::regs_for(context).map(|s| s.is_singlestep()).unwrap_or(false);
+
         let ksig = context.ksig.take().expect("context::switch: ksig not set with ksig_restore");
         context.arch = ksig.0;
 
@@ -33,6 +36,11 @@ unsafe fn update(context: &mut Context, cpu_id: usize) {
 
         context.ksig_restore = false;
 
+        // Keep singlestep flag across jumps
+        if let Some(regs) = ptrace::regs_for_mut(context) {
+            regs.set_singlestep(was_singlestep);
+        }
+
         context.unblock();
     }
 
-- 
GitLab