vm: clean up signal handling and add EXC_BAD_INSTRUCTION Mach exception handler for OS X, since signal handlers cannot change the stack pointer

db4
Slava Pestov 2009-10-22 05:22:59 -05:00
parent 6c1a70c218
commit f24942e063
20 changed files with 79 additions and 150 deletions

View File

@ -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);

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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;
}
}

View File

@ -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)
}

View File

@ -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])
}

View File

@ -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])
}

View File

@ -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])
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)
}

View File

@ -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))
}

View File

@ -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])
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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])
}

View File

@ -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])
}

View File

@ -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)

View File

@ -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__