From 5e44f2f94f0784c45f4b4d5ac77a60839aac9689 Mon Sep 17 00:00:00 2001 From: Matthew LeVan Date: Mon, 22 Jan 2024 21:49:24 -0500 Subject: [PATCH] wip: debugging --- rust/ares/src/interpreter.rs | 9 ++++----- rust/ares_guard/c-src/guard.c | 27 ++++++++++++++++++--------- rust/ares_guard/c-src/guard.h | 2 +- rust/ares_guard/src/lib.rs | 20 +++++++++++++++++++- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/rust/ares/src/interpreter.rs b/rust/ares/src/interpreter.rs index c12792e..2d79cec 100644 --- a/rust/ares/src/interpreter.rs +++ b/rust/ares/src/interpreter.rs @@ -375,11 +375,10 @@ extern "C" fn rust_callback(arg: *mut c_void) -> *mut c_void { pub fn call_with_guard Result>( f: F, - stack: *mut *mut c_void, - alloc: *mut *mut c_void, + stack: *const c_void, + alloc: *const c_void, ret: *mut *mut c_void, ) -> Result { - eprintln!("call_with_guard"); let boxed_f = Box::new(f); unsafe { @@ -988,8 +987,8 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res }; } }, - stack_p as *mut *mut c_void, - alloc_p as *mut *mut c_void, + stack_p as *const c_void, + alloc_p as *const c_void, std::ptr::null_mut() as *mut *mut c_void, ) }) diff --git a/rust/ares_guard/c-src/guard.c b/rust/ares_guard/c-src/guard.c index ffd2254..39e025a 100644 --- a/rust/ares_guard/c-src/guard.c +++ b/rust/ares_guard/c-src/guard.c @@ -21,12 +21,13 @@ volatile sig_atomic_t err = guard_sound; guard_err _focus_guard() { // Check for strange situations. if (stack_p == NULL || alloc_p == NULL) { + fprintf(stderr, "guard: stack or alloc pointer is null\r\n"); return guard_weird; } // Unmark the old guard page. void *old_guard_p = guard_p; - if (mprotect(old_guard_p, GD_PAGESIZE, PROT_READ | PROT_WRITE) == -1) { + if (old_guard_p != NULL && mprotect(old_guard_p, GD_PAGESIZE, PROT_READ | PROT_WRITE) == -1) { return guard_armor; } @@ -56,6 +57,7 @@ guard_err _focus_guard() { guard_err _slash_guard(void *si_addr) { if (si_addr >= guard_p && si_addr < guard_p + GD_PAGESIZE) { + fprintf(stderr, "guard: slash\r\n"); return _focus_guard(); } @@ -65,11 +67,11 @@ guard_err _slash_guard(void *si_addr) { void _signal_handler(int sig, siginfo_t *si, void *unused) { switch (sig) { case SIGSEGV: - fprintf(stderr, "guard: caught sigsegv\r\n"); + fprintf(stderr, "guard: segfault at %p\r\n", si->si_addr); + fprintf(stderr, "guard: guard at %p\r\n", guard_p); err = _slash_guard(si->si_addr); break; case SIGINT: - fprintf(stderr, "guard: caught sigint\r\n"); err = guard_erupt; break; default: @@ -91,19 +93,25 @@ guard_err _register_handler() { return guard_sound; } -void guard(void *(*f)(void *), void *arg, void *const *const stack, void *const *const alloc, void **ret) { - stack_p = *stack; - alloc_p = *alloc; +void guard(void *(*f)(void *), void *arg, void *const stack, void *const alloc, void **ret) { + stack_p = stack; + alloc_p = alloc; if (_register_handler() != guard_sound) { err = guard_weird; goto fail; } - fprintf(stderr, "guard: installing guard page\r\n"); - if (guard_p == NULL && (err = _focus_guard()) != guard_sound) { - goto fail; + if (guard_p == NULL) { + fprintf(stderr, "guard: installing guard page\r\n"); + guard_err install_err = _focus_guard(); + if (install_err != guard_sound) { + fprintf(stderr, "guard: failed to install guard page\r\n"); + err = install_err; + goto fail; + } } + fprintf(stderr, "guard: guard page installed at %p\r\n", guard_p); *ret = f(arg); @@ -114,6 +122,7 @@ void guard(void *(*f)(void *), void *arg, void *const *const stack, void *const return; fail: + fprintf(stderr, "guard: error %d\r\n", err); *ret = (void *) &err; return; } diff --git a/rust/ares_guard/c-src/guard.h b/rust/ares_guard/c-src/guard.h index 7e4b848..3492e77 100644 --- a/rust/ares_guard/c-src/guard.h +++ b/rust/ares_guard/c-src/guard.h @@ -30,7 +30,7 @@ * error will be written to the `ret` pointer. The caller is then responsible * for handling this error and aborting with a `bail:meme`. */ -void guard(void *(*f)(void *), void *arg, void *const *const stack, void *const *const alloc, void **ret); +void guard(void *(*f)(void *), void *arg, void *const stack, void *const alloc, void **ret); typedef enum { guard_sound = 0, // job's done diff --git a/rust/ares_guard/src/lib.rs b/rust/ares_guard/src/lib.rs index a38a13a..2698ade 100644 --- a/rust/ares_guard/src/lib.rs +++ b/rust/ares_guard/src/lib.rs @@ -2,4 +2,22 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] -include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +extern "C" { + #[doc = " Execute the given closure `f` within the memory arena between the\n `stack` and `alloc` pointers, with guard page protection. Write either\n `f`'s succesful result or a `guard_err` to the given `ret` pointer.\n\n Memory\n ------\n The free memory arena between the `stack` and `alloc` pointers is part of a\n NockStack frame, which may either face east or west. If the frame faces\n east, the `stack` pointer will be greater than the `alloc` pointer. If it\n faces west, the `stack` pointer will be less than the `alloc` pointer.\n\n All the pages in the memory arena are marked clean (`PROT_READ | PROT_WRITE`)\n by default, with the exception of a single guard page in the middle of the\n arena, which is marked with `PROT_NONE`.\n\n Guard\n -----\n This function protects the free memory arena between the `stack` and `alloc`\n pointers with a guard page. A guard page is simply a single page of memory\n which is marked with `PROT_NONE`. Since all other pages are marked clean by\n default, a SIGSEGV will only be raised if the `f` function attempts to write\n to the guard page. When it does, the signal handler will attempt to re-center\n the guard page in the remaining free space left in the arena. If there is no\n more free space, then memory exhaustion has occurred and the `guard_spent`\n error will be written to the `ret` pointer. The caller is then responsible\n for handling this error and aborting with a `bail:meme`."] + pub fn guard( + f: ::std::option::Option< + unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_void, + >, + arg: *mut ::std::os::raw::c_void, + stack: *const ::std::os::raw::c_void, + alloc: *const ::std::os::raw::c_void, + ret: *mut *mut ::std::os::raw::c_void, + ); +} +pub const guard_err_guard_sound: guard_err = 0; +pub const guard_err_guard_armor: guard_err = 1; +pub const guard_err_guard_weird: guard_err = 2; +pub const guard_err_guard_spent: guard_err = 3; +pub const guard_err_guard_erupt: guard_err = 4; +pub type guard_err = ::std::os::raw::c_uint; \ No newline at end of file