vm: clean up signal handling and add EXC_BAD_INSTRUCTION Mach exception handler for OS X, since signal handlers cannot change the stack pointer
parent
6c1a70c218
commit
f24942e063
|
@ -47,7 +47,7 @@ void factor_vm::call_fault_handler(
|
|||
else
|
||||
signal_callstack_top = NULL;
|
||||
|
||||
MACH_STACK_POINTER(thread_state) = fix_stack_pointer(MACH_STACK_POINTER(thread_state));
|
||||
MACH_STACK_POINTER(thread_state) = align_stack_pointer(MACH_STACK_POINTER(thread_state));
|
||||
|
||||
/* Now we point the program counter at the right handler function. */
|
||||
if(exception == EXC_BAD_ACCESS)
|
||||
|
@ -63,7 +63,13 @@ void factor_vm::call_fault_handler(
|
|||
}
|
||||
else
|
||||
{
|
||||
signal_number = (exception == EXC_ARITHMETIC ? SIGFPE : SIGABRT);
|
||||
switch(exception)
|
||||
{
|
||||
case EXC_ARITHMETIC: signal_number = SIGFPE; break;
|
||||
case EXC_BAD_INSTRUCTION: signal_number = SIGILL; break;
|
||||
default: signal_number = SIGABRT; break;
|
||||
}
|
||||
|
||||
MACH_PROGRAM_COUNTER(thread_state) = (cell)factor::misc_signal_handler_impl;
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +232,7 @@ void mach_initialize ()
|
|||
fatal_error("mach_port_insert_right() failed",0);
|
||||
|
||||
/* The exceptions we want to catch. */
|
||||
mask = EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC;
|
||||
mask = EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC;
|
||||
|
||||
/* Create the thread listening on the exception port. */
|
||||
start_thread(mach_exception_thread,NULL);
|
||||
|
|
|
@ -4,12 +4,6 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
inline static void *ucontext_stack_pointer(void *uap)
|
||||
{
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
return (void *)ucontext->uc_mcontext.mc_esp;
|
||||
}
|
||||
|
||||
inline static unsigned int uap_fpu_status(void *uap)
|
||||
{
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
|
@ -43,6 +37,8 @@ inline static void uap_clear_fpu_status(void *uap)
|
|||
}
|
||||
}
|
||||
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)(ucontext))->uc_mcontext.mc_eip)
|
||||
|
||||
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.mc_esp)
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.mc_eip)
|
||||
|
||||
}
|
||||
|
|
|
@ -4,12 +4,6 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
inline static void *ucontext_stack_pointer(void *uap)
|
||||
{
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
return (void *)ucontext->uc_mcontext.mc_rsp;
|
||||
}
|
||||
|
||||
inline static unsigned int uap_fpu_status(void *uap)
|
||||
{
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
|
@ -33,6 +27,8 @@ inline static void uap_clear_fpu_status(void *uap)
|
|||
}
|
||||
}
|
||||
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)(ucontext))->uc_mcontext.mc_rip)
|
||||
|
||||
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.mc_rsp)
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.mc_rip)
|
||||
|
||||
}
|
||||
|
|
|
@ -10,4 +10,9 @@ void early_init();
|
|||
const char *vm_executable_path();
|
||||
const char *default_image_path();
|
||||
|
||||
inline static cell align_stack_pointer(cell sp)
|
||||
{
|
||||
return sp;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,15 +5,9 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
inline static void *ucontext_stack_pointer(void *uap)
|
||||
{
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
return (void *)ucontext->uc_mcontext.arm_sp;
|
||||
}
|
||||
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) \
|
||||
(((ucontext_t *)(ucontext))->uc_mcontext.arm_pc)
|
||||
|
||||
void flush_icache(cell start, cell len);
|
||||
|
||||
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.arm_sp)
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.arm_pc)
|
||||
|
||||
}
|
||||
|
|
|
@ -4,14 +4,7 @@ namespace factor
|
|||
{
|
||||
|
||||
#define FRAME_RETURN_ADDRESS(frame,vm) *((void **)(vm->frame_successor(frame) + 1) + 1)
|
||||
|
||||
inline static void *ucontext_stack_pointer(void *uap)
|
||||
{
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
return (void *)ucontext->uc_mcontext.uc_regs->gregs[PT_R1];
|
||||
}
|
||||
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) \
|
||||
(((ucontext_t *)(ucontext))->uc_mcontext.uc_regs->gregs[PT_NIP])
|
||||
#define UAP_STACK_POINTER(ucontext) ((ucontext_t *)ucontext)->uc_mcontext.uc_regs->gregs[PT_R1]
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.uc_regs->gregs[PT_NIP])
|
||||
|
||||
}
|
||||
|
|
|
@ -29,12 +29,6 @@ struct _fpstate {
|
|||
|
||||
#define X86_FXSR_MAGIC 0x0000
|
||||
|
||||
inline static void *ucontext_stack_pointer(void *uap)
|
||||
{
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
return (void *)ucontext->uc_mcontext.gregs[7];
|
||||
}
|
||||
|
||||
inline static unsigned int uap_fpu_status(void *uap)
|
||||
{
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
|
@ -54,7 +48,8 @@ inline static void uap_clear_fpu_status(void *uap)
|
|||
fpregs->mxcsr &= 0xffffffc0;
|
||||
}
|
||||
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) \
|
||||
(((ucontext_t *)(ucontext))->uc_mcontext.gregs[14])
|
||||
|
||||
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[7])
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[14])
|
||||
|
||||
}
|
||||
|
|
|
@ -3,12 +3,6 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
inline static void *ucontext_stack_pointer(void *uap)
|
||||
{
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
return (void *)ucontext->uc_mcontext.gregs[15];
|
||||
}
|
||||
|
||||
inline static unsigned int uap_fpu_status(void *uap)
|
||||
{
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
|
@ -23,7 +17,7 @@ inline static void uap_clear_fpu_status(void *uap)
|
|||
ucontext->uc_mcontext.fpregs->mxcsr &= 0xffffffc0;
|
||||
}
|
||||
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) \
|
||||
(((ucontext_t *)(ucontext))->uc_mcontext.gregs[16])
|
||||
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[15])
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[16])
|
||||
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ inline static unsigned int uap_fpu_status(void *uap)
|
|||
return mach_fpu_status(UAP_FS(uap));
|
||||
}
|
||||
|
||||
inline static cell fix_stack_pointer(cell sp)
|
||||
inline static cell align_stack_pointer(cell sp)
|
||||
{
|
||||
return sp;
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ inline static unsigned int uap_fpu_status(void *uap)
|
|||
return mach_fpu_status(UAP_FS(uap));
|
||||
}
|
||||
|
||||
inline static cell fix_stack_pointer(cell sp)
|
||||
inline static cell align_stack_pointer(cell sp)
|
||||
{
|
||||
return ((sp + 4) & ~15) - 4;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ inline static unsigned int uap_fpu_status(void *uap)
|
|||
return mach_fpu_status(UAP_FS(uap));
|
||||
}
|
||||
|
||||
inline static cell fix_stack_pointer(cell sp)
|
||||
inline static cell align_stack_pointer(cell sp)
|
||||
{
|
||||
return ((sp + 8) & ~15) - 8;
|
||||
}
|
||||
|
|
|
@ -11,12 +11,8 @@ void early_init();
|
|||
const char *vm_executable_path();
|
||||
const char *default_image_path();
|
||||
|
||||
inline static void *ucontext_stack_pointer(void *uap)
|
||||
{
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
return ucontext->uc_stack.ss_sp;
|
||||
}
|
||||
|
||||
void c_to_factor_toplevel(cell quot);
|
||||
|
||||
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_stack.ss_sp)
|
||||
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
#define ucontext_stack_pointer(uap) ((void *)_UC_MACHINE_SP((ucontext_t *)uap))
|
||||
|
||||
static inline unsigned int uap_fpu_status(void *uap) { return 0; }
|
||||
static inline void uap_clear_fpu_status(void *uap) { }
|
||||
static inline void uap_clear_fpu_status(void *uap) {}
|
||||
|
||||
#define UAP_STACK_POINTER(ucontext) (_UC_MACHINE_SP((ucontext_t *)ucontext))
|
||||
|
||||
}
|
||||
|
|
|
@ -3,10 +3,9 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
#define ucontext_stack_pointer(uap) \
|
||||
((void *)(((ucontext_t *)(uap))->uc_mcontext.__gregs[_REG_URSP]))
|
||||
|
||||
static inline unsigned int uap_fpu_status(void *uap) { return 0; }
|
||||
static inline void uap_clear_fpu_status(void *uap) { }
|
||||
static inline void uap_clear_fpu_status(void *uap) {}
|
||||
|
||||
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.__gregs[_REG_URSP])
|
||||
|
||||
}
|
||||
|
|
|
@ -3,16 +3,10 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
inline static void *openbsd_stack_pointer(void *uap)
|
||||
{
|
||||
struct sigcontext *sc = (struct sigcontext*) uap;
|
||||
return (void *)sc->sc_esp;
|
||||
}
|
||||
|
||||
#define ucontext_stack_pointer openbsd_stack_pointer
|
||||
#define UAP_PROGRAM_COUNTER(uap) (((struct sigcontext*)(uap))->sc_eip)
|
||||
|
||||
static inline unsigned int uap_fpu_status(void *uap) { return 0; }
|
||||
static inline void uap_clear_fpu_status(void *uap) { }
|
||||
static inline void uap_clear_fpu_status(void *uap) {}
|
||||
|
||||
#define UAP_STACK_POINTER(ucontext) (((struct sigcontext *)ucontext)->sc_esp)
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) (((struct sigcontext *)ucontext)->sc_eip)
|
||||
|
||||
}
|
||||
|
|
|
@ -3,16 +3,10 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
inline static void *openbsd_stack_pointer(void *uap)
|
||||
{
|
||||
struct sigcontext *sc = (struct sigcontext*) uap;
|
||||
return (void *)sc->sc_rsp;
|
||||
}
|
||||
|
||||
#define ucontext_stack_pointer openbsd_stack_pointer
|
||||
#define UAP_PROGRAM_COUNTER(uap) (((struct sigcontext*)(uap))->sc_rip)
|
||||
|
||||
static inline unsigned int uap_fpu_status(void *uap) { return 0; }
|
||||
static inline void uap_clear_fpu_status(void *uap) { }
|
||||
static inline void uap_clear_fpu_status(void *uap) {}
|
||||
|
||||
#define UAP_STACK_POINTER(ucontext) (((struct sigcontext *)ucontext)->sc_rsp)
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) (((struct sigcontext *)ucontext)->sc_rip)
|
||||
|
||||
}
|
||||
|
|
|
@ -3,13 +3,7 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
inline static void *ucontext_stack_pointer(void *uap)
|
||||
{
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
return (void *)ucontext->uc_mcontext.gregs[ESP];
|
||||
}
|
||||
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) \
|
||||
(((ucontext_t *)(ucontext))->uc_mcontext.gregs[EIP])
|
||||
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[ESP])
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[EIP])
|
||||
|
||||
}
|
||||
|
|
|
@ -3,13 +3,7 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
inline static void *ucontext_stack_pointer(void *uap)
|
||||
{
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
return (void *)ucontext->uc_mcontext.gregs[RSP];
|
||||
}
|
||||
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) \
|
||||
(((ucontext_t *)(ucontext))->uc_mcontext.gregs[RIP])
|
||||
#define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[RSP])
|
||||
#define UAP_PROGRAM_COUNTER(ucontext) (((ucontext_t *)ucontext)->uc_mcontext.gregs[RIP])
|
||||
|
||||
}
|
||||
|
|
|
@ -115,63 +115,47 @@ segment::~segment()
|
|||
if(retval)
|
||||
fatal_error("Segment deallocation failed",0);
|
||||
}
|
||||
|
||||
stack_frame *factor_vm::uap_stack_pointer(void *uap)
|
||||
|
||||
void factor_vm::dispatch_signal(void *uap, void (handler)())
|
||||
{
|
||||
/* There is a race condition here, but in practice a signal
|
||||
delivered during stack frame setup/teardown or while transitioning
|
||||
from Factor to C is a sign of things seriously gone wrong, not just
|
||||
a divide by zero or stack underflow in the listener */
|
||||
if(in_code_heap_p(UAP_PROGRAM_COUNTER(uap)))
|
||||
{
|
||||
stack_frame *ptr = (stack_frame *)ucontext_stack_pointer(uap);
|
||||
if(!ptr)
|
||||
critical_error("Invalid uap",(cell)uap);
|
||||
return ptr;
|
||||
stack_frame *ptr = (stack_frame *)UAP_STACK_POINTER(uap);
|
||||
assert(ptr);
|
||||
signal_callstack_top = ptr;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
signal_callstack_top = NULL;
|
||||
|
||||
void factor_vm::memory_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
||||
{
|
||||
signal_fault_addr = (cell)siginfo->si_addr;
|
||||
signal_callstack_top = uap_stack_pointer(uap);
|
||||
UAP_PROGRAM_COUNTER(uap) = (cell)factor::memory_signal_handler_impl;
|
||||
UAP_STACK_POINTER(uap) = (void *)align_stack_pointer((cell)UAP_STACK_POINTER(uap));
|
||||
UAP_PROGRAM_COUNTER(uap) = (cell)handler;
|
||||
}
|
||||
|
||||
void memory_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
||||
{
|
||||
tls_vm()->memory_signal_handler(signal,siginfo,uap);
|
||||
}
|
||||
|
||||
void factor_vm::misc_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
||||
{
|
||||
signal_number = signal;
|
||||
signal_callstack_top = uap_stack_pointer(uap);
|
||||
UAP_PROGRAM_COUNTER(uap) = (cell)factor::misc_signal_handler_impl;
|
||||
factor_vm *vm = tls_vm();
|
||||
vm->signal_fault_addr = (cell)siginfo->si_addr;
|
||||
vm->dispatch_signal(uap,factor::memory_signal_handler_impl);
|
||||
}
|
||||
|
||||
void misc_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
||||
{
|
||||
tls_vm()->misc_signal_handler(signal,siginfo,uap);
|
||||
}
|
||||
|
||||
void factor_vm::fpe_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
||||
{
|
||||
signal_number = signal;
|
||||
signal_callstack_top = uap_stack_pointer(uap);
|
||||
signal_fpu_status = fpu_status(uap_fpu_status(uap));
|
||||
uap_clear_fpu_status(uap);
|
||||
UAP_PROGRAM_COUNTER(uap) =
|
||||
(siginfo->si_code == FPE_INTDIV || siginfo->si_code == FPE_INTOVF)
|
||||
? (cell)factor::misc_signal_handler_impl
|
||||
: (cell)factor::fp_signal_handler_impl;
|
||||
factor_vm *vm = tls_vm();
|
||||
vm->signal_number = signal;
|
||||
vm->dispatch_signal(uap,factor::misc_signal_handler_impl);
|
||||
}
|
||||
|
||||
void fpe_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
||||
{
|
||||
tls_vm()->fpe_signal_handler(signal, siginfo, uap);
|
||||
factor_vm *vm = tls_vm();
|
||||
vm->signal_number = signal;
|
||||
vm->signal_fpu_status = fpu_status(uap_fpu_status(uap));
|
||||
uap_clear_fpu_status(uap);
|
||||
|
||||
vm->dispatch_signal(uap,
|
||||
(siginfo->si_code == FPE_INTDIV || siginfo->si_code == FPE_INTOVF)
|
||||
? factor::misc_signal_handler_impl
|
||||
: factor::fp_signal_handler_impl);
|
||||
}
|
||||
|
||||
static void sigaction_safe(int signum, const struct sigaction *act, struct sigaction *oldact)
|
||||
|
|
11
vm/vm.hpp
11
vm/vm.hpp
|
@ -689,17 +689,12 @@ struct factor_vm
|
|||
void windows_image_path(vm_char *full_path, vm_char *temp_path, unsigned int length);
|
||||
bool windows_stat(vm_char *path);
|
||||
|
||||
#if defined(WINNT)
|
||||
#if defined(WINNT)
|
||||
void open_console();
|
||||
LONG exception_handler(PEXCEPTION_POINTERS pe);
|
||||
// next method here:
|
||||
#endif
|
||||
#endif
|
||||
#else // UNIX
|
||||
void memory_signal_handler(int signal, siginfo_t *siginfo, void *uap);
|
||||
void misc_signal_handler(int signal, siginfo_t *siginfo, void *uap);
|
||||
void fpe_signal_handler(int signal, siginfo_t *siginfo, void *uap);
|
||||
stack_frame *uap_stack_pointer(void *uap);
|
||||
|
||||
void factor_vm::dispatch_signal(void *uap, void (handler)());
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
|
Loading…
Reference in New Issue