about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-06-11 22:44:55 -0700
committerBrian Anderson <banderson@mozilla.com>2012-06-11 22:44:55 -0700
commit07bba397c5b46c96cfb8de23c34b9bae47e07947 (patch)
tree1badf71f2fed70f1080d41cf156ee7cb2111e7e8
parent41df9cbb448ab7b4fd352d64776cdfd02ed83a56 (diff)
downloadrust-07bba397c5b46c96cfb8de23c34b9bae47e07947.tar.gz
rust-07bba397c5b46c96cfb8de23c34b9bae47e07947.zip
core: More stack walking
-rw-r--r--src/libcore/stackwalk.rs57
1 files changed, 48 insertions, 9 deletions
diff --git a/src/libcore/stackwalk.rs b/src/libcore/stackwalk.rs
index 6900509f213..321fa605f48 100644
--- a/src/libcore/stackwalk.rs
+++ b/src/libcore/stackwalk.rs
@@ -1,30 +1,69 @@
-import libc::uintptr_t;
+// NB: Don't rely on other core mods here as this has to move into the rt
+
+import unsafe::reinterpret_cast;
+import ptr::offset;
+import sys::size_of;
+
+type word = uint;
 
 class frame {
-    let fp: uintptr_t;
+    let fp: *word;
 
-    new(fp: uintptr_t) {
+    new(fp: *word) {
         self.fp = fp;
     }
 }
 
 fn walk_stack(visit: fn(frame) -> bool) {
+
+    #debug("beginning stack walk");
+
     frame_address { |frame_pointer|
-        let frame_address = unsafe {
-            unsafe::reinterpret_cast(frame_pointer)
+        let mut frame_address: *word = unsafe {
+            reinterpret_cast(frame_pointer)
         };
-        visit(frame(frame_address));
+        loop {
+            let frame = frame(frame_address);
+
+            #debug("frame: %x", unsafe { reinterpret_cast(frame.fp) });
+            visit(frame);
+
+            unsafe {
+                let next_fp: **word = reinterpret_cast(frame_address);
+                frame_address = *next_fp;
+                if *frame_address == 0u {
+                    #debug("encountered task_start_wrapper. ending walk");
+                    // This is the task_start_wrapper_frame. There is
+                    // no stack beneath it and it is a native frame.
+                    break;
+                }
+            }
+        }
     }
 }
 
 #[test]
-fn test() {
+fn test_simple() {
     for walk_stack { |frame|
-        #debug("frame: %x", frame.fp);
-        // breakpoint();
     }
 }
 
+#[test]
+fn test_simple_deep() {
+    fn run(i: int) {
+        if i == 0 { ret }
+
+        for walk_stack { |frame|
+            unsafe {
+                breakpoint();
+            }
+        }
+        run(i - 1);
+    }
+
+    run(10);
+}
+
 fn breakpoint() {
     rustrt::rust_dbg_breakpoint()
 }