diff --git a/rust/ares/src/guard.rs b/rust/ares/src/guard.rs index c9cc4ed..5977495 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 *mut u64, - alloc_pp: *const *mut u64, + stack_pp: *const *const u64, + alloc_pp: *const *const u64, closure: &mut F, ) -> Result { let cb = CCallback::new(closure); @@ -100,7 +100,8 @@ 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 *mut u64; - let alloc_pp = context.stack.get_alloc_pointer_pointer() as *const *mut u64; + 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; + 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 e6b50a2..210e897 100644 --- a/rust/ares/src/mem.rs +++ b/rust/ares/src/mem.rs @@ -32,13 +32,6 @@ 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 */ @@ -94,20 +87,6 @@ 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 28a6bff..ac37c05 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 jmp_buf env_buffer; +static BufListNode *buffer_list = NULL; 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(env_buffer, guard_signal); + siglongjmp(buffer_list->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(env_buffer, err); + siglongjmp(buffer_list->buffer, err); } } else { @@ -173,10 +173,11 @@ int32_t guard( callback f, void *closure, - const uintptr_t *s_pp, - const uintptr_t *a_pp, + const uintptr_t *const s_pp, + const uintptr_t *const a_pp, void ** ret ) { + BufListNode *new_buffer; int32_t err = 0; int32_t td_err = 0; @@ -184,6 +185,8 @@ 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; @@ -198,26 +201,58 @@ 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(env_buffer, 1))) { + if (!(err = sigsetjmp(buffer_list->buffer, 1))) { *ret = f(closure); } -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; + // 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; + } + } + 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 06d3698..a2f610f 100644 --- a/rust/ares_guard/c-src/guard.h +++ b/rust/ares_guard/c-src/guard.h @@ -4,6 +4,14 @@ #include #include +/** + * + */ +typedef struct _buf_list_node { + jmp_buf buffer; + struct _buf_list_node *next; +} BufListNode; + /** * Error codes and flags. * @@ -52,8 +60,8 @@ int32_t guard( callback f, void *closure, - const uintptr_t *s_pp, - const uintptr_t *a_pp, + const uintptr_t *const s_pp, + const uintptr_t *const a_pp, void **ret );