From a5379458cc384a8b50daf911099b994759114ce1 Mon Sep 17 00:00:00 2001
From: Alex Shelkovnykov
Date: Sat, 3 Feb 2024 10:54:45 +0900
Subject: [PATCH 1/3] stack: add debug helper functions to NockStack
---
rust/ares/src/mem.rs | 104 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 104 insertions(+)
diff --git a/rust/ares/src/mem.rs b/rust/ares/src/mem.rs
index 31f81c5..941d6ba 100644
--- a/rust/ares/src/mem.rs
+++ b/rust/ares/src/mem.rs
@@ -834,6 +834,110 @@ impl NockStack {
}
}
}
+
+ /**
+ * Debugging
+ *
+ * The below functions are useful for debugging NockStack issues. */
+
+
+ /**
+ * Walk down the NockStack, printing frames. Absolutely no safety checks are peformed, as the
+ * purpose is to discover garbage data; just print pointers until the bottom of the NockStack
+ * (i.e. a null frame pointer) is encountered. Possible to crash, if a frame pointer gets
+ * written over.
+ */
+ pub fn print_frames(&mut self) {
+ let mut fp = self.frame_pointer;
+ let mut sp = self.stack_pointer;
+ let mut ap = self.alloc_pointer;
+ let mut c = 0u64;
+
+ eprintln!("\r start = {:p}", self.start);
+
+ loop {
+ c += 1;
+
+ eprintln!("\r {}:", c);
+ eprintln!("\r frame_pointer = {:p}", fp);
+ eprintln!("\r stack_pointer = {:p}", sp);
+ eprintln!("\r alloc_pointer = {:p}", ap);
+
+ if fp.is_null() {
+ break;
+ }
+
+ unsafe {
+ if fp < ap {
+ sp = *(fp.sub(STACK + 1) as *mut *mut u64);
+ ap = *(fp.sub(ALLOC + 1) as *mut *mut u64);
+ fp = *(fp.sub(FRAME + 1) as *mut *mut u64);
+ } else {
+ sp = *(fp.add(STACK) as *mut *mut u64);
+ ap = *(fp.add(ALLOC) as *mut *mut u64);
+ fp = *(fp.add(FRAME) as *mut *mut u64);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sanity check every frame of the NockStack. Most useful paired with a gdb session set to
+ * catch rust_panic.
+ */
+ pub fn assert_sane(&mut self) {
+ let start = self.start;
+ let limit = unsafe { self.start.add(self.size) };
+ let mut fp = self.frame_pointer;
+ let mut sp = self.stack_pointer;
+ let mut ap = self.alloc_pointer;
+ let mut ought_west: bool = fp < ap;
+
+ loop {
+ // fp is null iff sp is null
+ assert!(!(fp.is_null() ^ sp.is_null()));
+
+ // ap should never be null
+ assert!(!ap.is_null());
+
+ if fp.is_null() {
+ break;
+ }
+
+ // all pointers must be between start and size
+ assert!(fp as *const u64 >= start);
+ assert!(fp as *const u64 <= limit);
+ assert!(sp as *const u64 >= start);
+ assert!(sp as *const u64 <= limit);
+ assert!(ap as *const u64 >= start);
+ assert!(ap as *const u64 <= limit);
+
+ // frames should flip between east-west correctly
+ assert!((fp < ap) == ought_west);
+
+ // sp should be between fp and ap
+ if ought_west {
+ assert!(sp >= fp);
+ assert!(sp < ap);
+ } else {
+ assert!(sp <= fp);
+ assert!(sp > ap);
+ }
+
+ unsafe {
+ if ought_west {
+ sp = *(fp.sub(STACK + 1) as *mut *mut u64);
+ ap = *(fp.sub(ALLOC + 1) as *mut *mut u64);
+ fp = *(fp.sub(FRAME + 1) as *mut *mut u64);
+ } else {
+ sp = *(fp.add(STACK) as *mut *mut u64);
+ ap = *(fp.add(ALLOC) as *mut *mut u64);
+ fp = *(fp.add(FRAME) as *mut *mut u64);
+ }
+ }
+ ought_west = !ought_west;
+ }
+ }
}
impl NounAllocator for NockStack {
From 2a040b565b16285183c21b8d50df5605b9785731 Mon Sep 17 00:00:00 2001
From: Alex Shelkovnykov
Date: Fri, 2 Feb 2024 21:22:35 -0600
Subject: [PATCH 2/3] style: fix cargo fmt complaints
---
rust/ares/src/mem.rs | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/rust/ares/src/mem.rs b/rust/ares/src/mem.rs
index 941d6ba..784124d 100644
--- a/rust/ares/src/mem.rs
+++ b/rust/ares/src/mem.rs
@@ -837,24 +837,23 @@ impl NockStack {
/**
* Debugging
- *
+ *
* The below functions are useful for debugging NockStack issues. */
-
- /**
- * Walk down the NockStack, printing frames. Absolutely no safety checks are peformed, as the
- * purpose is to discover garbage data; just print pointers until the bottom of the NockStack
- * (i.e. a null frame pointer) is encountered. Possible to crash, if a frame pointer gets
- * written over.
- */
+ /**
+ * Walk down the NockStack, printing frames. Absolutely no safety checks are peformed, as the
+ * purpose is to discover garbage data; just print pointers until the bottom of the NockStack
+ * (i.e. a null frame pointer) is encountered. Possible to crash, if a frame pointer gets
+ * written over.
+ */
pub fn print_frames(&mut self) {
let mut fp = self.frame_pointer;
let mut sp = self.stack_pointer;
let mut ap = self.alloc_pointer;
let mut c = 0u64;
-
+
eprintln!("\r start = {:p}", self.start);
-
+
loop {
c += 1;
@@ -896,7 +895,7 @@ impl NockStack {
loop {
// fp is null iff sp is null
assert!(!(fp.is_null() ^ sp.is_null()));
-
+
// ap should never be null
assert!(!ap.is_null());
From e02a232f2c43a38dbc0c5649ea1fc4cc2383fbfa Mon Sep 17 00:00:00 2001
From: Alex Shelkovnykov
Date: Fri, 2 Feb 2024 21:24:38 -0600
Subject: [PATCH 3/3] style: same as prev commit
---
rust/ares/src/mem.rs | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/rust/ares/src/mem.rs b/rust/ares/src/mem.rs
index 784124d..7b65033 100644
--- a/rust/ares/src/mem.rs
+++ b/rust/ares/src/mem.rs
@@ -841,11 +841,11 @@ impl NockStack {
* The below functions are useful for debugging NockStack issues. */
/**
- * Walk down the NockStack, printing frames. Absolutely no safety checks are peformed, as the
- * purpose is to discover garbage data; just print pointers until the bottom of the NockStack
- * (i.e. a null frame pointer) is encountered. Possible to crash, if a frame pointer gets
- * written over.
- */
+ * Walk down the NockStack, printing frames. Absolutely no safety checks are peformed, as the
+ * purpose is to discover garbage data; just print pointers until the bottom of the NockStack
+ * (i.e. a null frame pointer) is encountered. Possible to crash, if a frame pointer gets
+ * written over.
+ */
pub fn print_frames(&mut self) {
let mut fp = self.frame_pointer;
let mut sp = self.stack_pointer;