diff --git a/rust/ares/src/guard.rs b/rust/ares/src/guard.rs index 5977495..c9cc4ed 100644 --- a/rust/ares/src/guard.rs +++ b/rust/ares/src/guard.rs @@ -65,8 +65,8 @@ impl<'closure> CCallback<'closure> { } pub fn call_with_guard Result>( - stack_pp: *const *const u64, - alloc_pp: *const *const u64, + stack_pp: *const *mut u64, + alloc_pp: *const *mut u64, closure: &mut F, ) -> Result { let cb = CCallback::new(closure); @@ -100,8 +100,7 @@ pub fn call_with_guard Result>( } pub fn interpret_with_guard(context: &mut Context, eve: Noun, lyf: Noun) -> Result { - let stack_pp = context.stack.get_stack_pointer_pointer() as *const *const u64; - let alloc_pp = context.stack.get_alloc_pointer_pointer() as *const *const u64; - + let stack_pp = context.stack.get_stack_pointer_pointer() as *const *mut u64; + let alloc_pp = context.stack.get_alloc_pointer_pointer() as *const *mut u64; call_with_guard(stack_pp, alloc_pp, &mut || interpret(context, eve, lyf)) } diff --git a/rust/ares/src/mem.rs b/rust/ares/src/mem.rs index 210e897..e6b50a2 100644 --- a/rust/ares/src/mem.rs +++ b/rust/ares/src/mem.rs @@ -32,6 +32,13 @@ fn indirect_raw_size(atom: IndirectAtom) -> usize { atom.size() + 2 } +#[allow(dead_code)] +pub struct NockStackSnapshot { + frame_pointer: *mut u64, + stack_pointer: *mut u64, + alloc_pointer: *mut u64, +} + /** A stack for Nock computation, which supports stack allocation and delimited copying collection * for returned nouns */ @@ -87,6 +94,20 @@ impl NockStack { } } + pub fn save(&self) -> NockStackSnapshot { + NockStackSnapshot { + frame_pointer: self.frame_pointer, + stack_pointer: self.stack_pointer, + alloc_pointer: self.alloc_pointer, + } + } + + pub fn restore(&mut self, saved: &NockStackSnapshot) { + self.frame_pointer = saved.frame_pointer; + self.stack_pointer = saved.stack_pointer; + self.alloc_pointer = saved.alloc_pointer; + } + /** Resets the NockStack but flipping the top-frame polarity and unsetting PC. Sets the alloc * pointer to the "previous" alloc pointer stored in the top frame to keep things "preserved" * from the top frame. This allows us to do a copying GC on the top frame without erroneously diff --git a/rust/ares_guard/c-src/guard.c b/rust/ares_guard/c-src/guard.c index ac37c05..28a6bff 100644 --- a/rust/ares_guard/c-src/guard.c +++ b/rust/ares_guard/c-src/guard.c @@ -18,7 +18,7 @@ static uintptr_t guard_p = 0; static const uintptr_t *stack_pp = NULL; static const uintptr_t *alloc_pp = NULL; -static BufListNode *buffer_list = NULL; +static jmp_buf env_buffer; static struct sigaction prev_sa; static int32_t @@ -113,7 +113,7 @@ _signal_handler(int sig, siginfo_t *si, void *unused) if (sig != SIGSEGV) { fprintf(stderr, "guard: sig_handle: invalid signal\r\n"); // XX: do we even want to jump? if this is fatal error, maybe just die now - siglongjmp(buffer_list->buffer, guard_signal); + siglongjmp(env_buffer, guard_signal); } sig_addr = (uintptr_t)si->si_addr; @@ -126,7 +126,7 @@ _signal_handler(int sig, siginfo_t *si, void *unused) err = _focus_guard(); if (err) { fprintf(stderr, "guard: sig_handle: focus error\r\n"); - siglongjmp(buffer_list->buffer, err); + siglongjmp(env_buffer, err); } } else { @@ -173,11 +173,10 @@ int32_t guard( callback f, void *closure, - const uintptr_t *const s_pp, - const uintptr_t *const a_pp, + const uintptr_t *s_pp, + const uintptr_t *a_pp, void ** ret ) { - BufListNode *new_buffer; int32_t err = 0; int32_t td_err = 0; @@ -185,8 +184,6 @@ guard( fprintf(stderr, "guard: setup: alloc pointer at %p\r\n", (void *)(*a_pp)); if (guard_p == 0) { - assert(buffer_list == NULL); - stack_pp = s_pp; alloc_pp = a_pp; @@ -201,58 +198,26 @@ guard( fprintf(stderr, "guard: setup _register_handler error\r\n"); goto clean; } - } else { - assert(buffer_list != NULL); } - // Setup new longjmp buffer - new_buffer = (BufListNode *)malloc(sizeof(BufListNode)); - if (new_buffer == NULL) { - fprintf(stderr, "guard: malloc error\r\n"); - fprintf(stderr, "%s\r\n", strerror(errno)); - err = guard_malloc | errno; - goto skip; - } - new_buffer->next = buffer_list; - buffer_list = new_buffer; - // Run given closure fprintf(stderr, "guard: run\r\n"); - if (!(err = sigsetjmp(buffer_list->buffer, 1))) { + if (!(err = sigsetjmp(env_buffer, 1))) { *ret = f(closure); } - // Restore previous longjmp buffer - buffer_list = buffer_list->next; - free((void *)new_buffer); - -skip: - // If no more guarded closures, then... - if (buffer_list == NULL) { - // Remove new signal handler - if (sigaction(SIGSEGV, &prev_sa, NULL)) { - fprintf(stderr, "guard: sigaction error\r\n"); - fprintf(stderr, "%s\r\n", strerror(errno)); - td_err = guard_sigaction | errno; - - if (!err) { - err = td_err; - } - } - clean: - // Unmark guard page - assert(guard_p != 0); - td_err = _unmark_page((void *)guard_p); - if (td_err) { - fprintf(stderr, "guard: unmark error\r\n"); - fprintf(stderr, "%s\r\n", strerror(errno)); - if (!err) { - err = td_err; - } + // Unmark guard page + assert(guard_p != 0); + td_err = _unmark_page((void *)guard_p); + if (td_err) { + fprintf(stderr, "guard: unmark error\r\n"); + fprintf(stderr, "%s\r\n", strerror(errno)); + if (!err) { + err = td_err; } - guard_p = 0; } + guard_p = 0; exit: fprintf(stderr, "guard: return\r\n"); diff --git a/rust/ares_guard/c-src/guard.h b/rust/ares_guard/c-src/guard.h index a2f610f..06d3698 100644 --- a/rust/ares_guard/c-src/guard.h +++ b/rust/ares_guard/c-src/guard.h @@ -4,14 +4,6 @@ #include #include -/** - * - */ -typedef struct _buf_list_node { - jmp_buf buffer; - struct _buf_list_node *next; -} BufListNode; - /** * Error codes and flags. * @@ -60,8 +52,8 @@ int32_t guard( callback f, void *closure, - const uintptr_t *const s_pp, - const uintptr_t *const a_pp, + const uintptr_t *s_pp, + const uintptr_t *a_pp, void **ret );