#include "../factor.h" #include "mach_signal.h" // this function tests if a given faulting location is in a poison page. The // page address is taken from area + round_up_to_page_size(area_size) + // pagesize*offset static bool in_page(void *fault, void *i_area, CELL area_size, int offset) { const int pagesize = getpagesize(); intptr_t area = (intptr_t) i_area; area += pagesize * ((area_size + (pagesize - 1)) / pagesize); area += offset * pagesize; const int page = area / pagesize; const int fault_page = (intptr_t)fault / pagesize; return page == fault_page; } void signal_handler(int signal, siginfo_t* siginfo, void* uap) { if(nursery.here > nursery.limit) { fprintf(stderr,"Nursery space exhausted\n"); factorbug(); } else if(compiling.here + sizeof(CELL) > compiling.limit) { fprintf(stderr,"Code space exhausted\n"); factorbug(); } /* we wish to catch the case where we underflow/overflow the data or // return stacks. These stacks have poison pages above and below the // memory so we just need to test if the faulting addresss is in one of // these pages */ /* first, underflowing the data stack */ else if(in_page(siginfo->si_addr, (void *) ds_bot, 0, -1)) { signal_stack_error(false, false); } else if(in_page(siginfo->si_addr, (void *) ds_bot, ds_size, 0)) { signal_stack_error(false, true); } else if(in_page(siginfo->si_addr, (void *) cs_bot, 0, -1)) { signal_stack_error(true, false); } else if(in_page(siginfo->si_addr, (void *) cs_bot, cs_size, 0)) { signal_stack_error(true, true); } else signal_error(signal); } static void sigaction_safe(int signum, const struct sigaction *act, struct sigaction *oldact) { int ret; do { ret = sigaction(signum, act, oldact); } while(ret == -1 && errno == EINTR); } void init_signals(void) { struct sigaction custom_sigaction; struct sigaction ign_sigaction; sigemptyset(&custom_sigaction.sa_mask); custom_sigaction.sa_sigaction = signal_handler; custom_sigaction.sa_flags = SA_SIGINFO; sigaction_safe(SIGABRT,&custom_sigaction,NULL); sigaction_safe(SIGFPE,&custom_sigaction,NULL); sigaction_safe(SIGBUS,&custom_sigaction,NULL); sigaction_safe(SIGQUIT,&custom_sigaction,NULL); sigaction_safe(SIGSEGV,&custom_sigaction,NULL); sigemptyset(&ign_sigaction.sa_mask); ign_sigaction.sa_handler = SIG_IGN; sigaction_safe(SIGPIPE,&ign_sigaction,NULL); #ifdef __APPLE__ mach_initialize(); #endif }