From 06d952979f0c426b4f6d16ee828e9221d2876ce4 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Mon, 22 Aug 2022 08:41:35 -0600
Subject: [PATCH] Implement debugger for x86

---
 src/debugger.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/src/debugger.rs b/src/debugger.rs
index c141ffa7..98ce65e4 100644
--- a/src/debugger.rs
+++ b/src/debugger.rs
@@ -1,11 +1,84 @@
 use crate::paging::{RmmA, RmmArch, TableKind};
 
-#[cfg(not(target_arch = "x86_64"))]
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
 pub unsafe fn debugger(target_id: Option<crate::context::ContextId>) {
     println!("DEBUGGER TODO");
     println!();
 }
 
+// Super unsafe due to page table switching and raw pointers!
+#[cfg(target_arch = "x86")]
+pub unsafe fn debugger(target_id: Option<crate::context::ContextId>) {
+    println!("DEBUGGER START");
+    println!();
+
+    let old_table = RmmA::table(TableKind::User);
+
+    for (id, context_lock) in crate::context::contexts().iter() {
+        if target_id.map_or(false, |target_id| *id != target_id) { continue; }
+        let context = context_lock.read();
+        println!("{}: {}", (*id).into(), context.name.read());
+
+        // Switch to context page table to ensure syscall debug and stack dump will work
+        if let Some(ref space) = context.addr_space {
+            RmmA::set_table(TableKind::User, space.read().table.utable.table().phys());
+            //TODO check_consistency(&mut space.write());
+        }
+
+        println!("status: {:?}", context.status);
+        if ! context.status_reason.is_empty() {
+            println!("reason: {}", context.status_reason);
+        }
+        if let Some((a, b, c, d, e, f)) = context.syscall {
+            println!("syscall: {}", crate::syscall::debug::format_call(a, b, c, d, e, f));
+        }
+        if let Some(ref addr_space) = context.addr_space {
+            let addr_space = addr_space.read();
+            if ! addr_space.grants.is_empty() {
+                println!("grants:");
+                for grant in addr_space.grants.iter() {
+                    let region = grant.region();
+                    println!(
+                        "    virt 0x{:08x}:0x{:08x} size 0x{:08x} {}",
+                        region.start_address().data(), region.final_address().data(), region.size(),
+                        if grant.is_owned() { "owned" } else { "borrowed" },
+                    );
+                }
+            }
+        }
+        if let Some(regs) = crate::ptrace::regs_for(&context) {
+            println!("regs:");
+            regs.dump();
+
+            let mut sp = regs.iret.esp;
+            println!("stack: {:>08x}", sp);
+            //Maximum 64 dwords
+            for _ in 0..64 {
+                if context.addr_space.as_ref().map_or(false, |space| space.read().table.utable.translate(crate::paging::VirtualAddress::new(sp)).is_some()) {
+                    let value = *(sp as *const usize);
+                    println!("    {:>08x}: {:>08x}", sp, value);
+                    if let Some(next_sp) = sp.checked_add(core::mem::size_of::<usize>()) {
+                        sp = next_sp;
+                    } else {
+                        println!("    {:>08x}: OVERFLOW", sp);
+                        break;
+                    }
+                } else {
+                    println!("    {:>08x}: GUARD PAGE", sp);
+                    break;
+                }
+            }
+        }
+
+        // Switch to original page table
+        RmmA::set_table(TableKind::User, old_table);
+
+        println!();
+    }
+
+    println!("DEBUGGER END");
+}
+
 // Super unsafe due to page table switching and raw pointers!
 #[cfg(target_arch = "x86_64")]
 pub unsafe fn debugger(target_id: Option<crate::context::ContextId>) {
@@ -79,6 +152,7 @@ pub unsafe fn debugger(target_id: Option<crate::context::ContextId>) {
     println!("DEBUGGER END");
 }
 
+#[cfg(target_arch = "x86_64")]
 pub unsafe fn check_consistency(addr_space: &mut crate::context::memory::AddrSpace) {
     use crate::paging::*;
 
-- 
GitLab