From 1dc31d133b3fa58fafeb01a8e3649ba7525fd506 Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Thu, 20 Oct 2011 20:55:55 -0700 Subject: [PATCH] vm: clean up signal handler dispatch Remove the weird and broken functions fix_callstack_top and scrub_return_address. Instead, simply decrement the SP and store the PC from the front end of the signal handler so that the back end can return back into the original context normally. Currently aborts for leaf procedure frames pending a more robust solution. --- vm/callstack.cpp | 23 ----------------------- vm/errors.cpp | 3 --- vm/mach_signal.cpp | 6 +++++- vm/os-unix.cpp | 7 ++++++- 4 files changed, 11 insertions(+), 28 deletions(-) diff --git a/vm/callstack.cpp b/vm/callstack.cpp index a0bbae8709..134a7c78b2 100755 --- a/vm/callstack.cpp +++ b/vm/callstack.cpp @@ -18,22 +18,6 @@ callstack *factor_vm::allot_callstack(cell size) return stack; } -/* If 'stack' points into the middle of the frame, find the nearest valid stack -pointer where we can resume execution and hope to capture the call trace without -crashing. Also, make sure we have at least 'stack_reserved' bytes available so -that we don't run out of callstack space while handling the error. */ -stack_frame *factor_vm::fix_callstack_top(stack_frame *stack) -{ - stack_frame *frame = ctx->callstack_bottom - 1; - - while(frame >= stack - && frame >= ctx->callstack_top - && (cell)frame >= ctx->callstack_seg->start + stack_reserved) - frame = frame_successor(frame); - - return frame + 1; -} - /* We ignore the two topmost frames, the 'callstack' primitive frame itself, and the frame calling the 'callstack' primitive, so that set-callstack doesn't get stuck in an infinite loop. @@ -127,13 +111,6 @@ void factor_vm::set_frame_offset(stack_frame *frame, cell offset) FRAME_RETURN_ADDRESS(frame,this) = entry_point + offset; } -void factor_vm::scrub_return_address() -{ - stack_frame *frame = innermost_stack_frame(ctx->callstack_bottom, - ctx->callstack_top); - set_frame_offset(frame,0); -} - cell factor_vm::frame_scan(stack_frame *frame) { switch(frame_type(frame)) diff --git a/vm/errors.cpp b/vm/errors.cpp index f0df0acbb8..23924df4e5 100755 --- a/vm/errors.cpp +++ b/vm/errors.cpp @@ -125,7 +125,6 @@ void factor_vm::primitive_unimplemented() void factor_vm::memory_signal_handler_impl() { - scrub_return_address(); memory_protection_error(signal_fault_addr); } @@ -136,7 +135,6 @@ void memory_signal_handler_impl() void factor_vm::synchronous_signal_handler_impl() { - scrub_return_address(); signal_error(signal_number); } @@ -150,7 +148,6 @@ void factor_vm::fp_signal_handler_impl() /* Clear pending exceptions to avoid getting stuck in a loop */ set_fpu_state(get_fpu_state()); - scrub_return_address(); fp_trap_error(signal_fpu_status); } diff --git a/vm/mach_signal.cpp b/vm/mach_signal.cpp index 469b9f2ef6..1ad07791cc 100755 --- a/vm/mach_signal.cpp +++ b/vm/mach_signal.cpp @@ -35,7 +35,11 @@ void factor_vm::call_fault_handler( MACH_THREAD_STATE_TYPE *thread_state, MACH_FLOAT_STATE_TYPE *float_state) { - MACH_STACK_POINTER(thread_state) = (cell)fix_callstack_top((stack_frame *)MACH_STACK_POINTER(thread_state)); + cell offset = MACH_STACK_POINTER(thread_state) % 16; + if (offset != 0) + fatal_error("fault in unaligned frame with offset", offset); + MACH_STACK_POINTER(thread_state) -= sizeof(cell); + *(cell*)MACH_STACK_POINTER(thread_state) = MACH_PROGRAM_COUNTER(thread_state); ctx->callstack_top = (stack_frame *)MACH_STACK_POINTER(thread_state); diff --git a/vm/os-unix.cpp b/vm/os-unix.cpp index a198f10a1e..efd3e03bb2 100755 --- a/vm/os-unix.cpp +++ b/vm/os-unix.cpp @@ -138,7 +138,12 @@ void code_heap::unguard_safepoint() void factor_vm::dispatch_signal(void *uap, void (handler)()) { - UAP_STACK_POINTER(uap) = (UAP_STACK_POINTER_TYPE)fix_callstack_top((stack_frame *)UAP_STACK_POINTER(uap)); + cell sp = (cell)UAP_STACK_POINTER(uap); + cell offset = sp % 16; + if (offset != 0) + fatal_error("fault in unaligned frame with offset", offset); + UAP_STACK_POINTER(uap) = (UAP_STACK_POINTER_TYPE)(sp - sizeof(cell)); + *(cell*)(UAP_STACK_POINTER(uap)) = (cell)UAP_PROGRAM_COUNTER(uap); UAP_PROGRAM_COUNTER(uap) = (cell)FUNCTION_CODE_POINTER(handler); UAP_SET_TOC_POINTER(uap, (cell)FUNCTION_TOC_POINTER(handler)); ctx->callstack_top = (stack_frame *)UAP_STACK_POINTER(uap);