blob: 1f2d99938e15eb9fa4a758ed72aa005987c05476 [file] [log] [blame]
//===----------- Sigsegv.cc - Sigsegv default handling --------------------===//
//
// The Micro Virtual Machine
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MvmGC.h"
#include "mvm/Sigsegv.h"
#include "mvm/Threads/Thread.h"
#include <signal.h>
#include <stdio.h>
using namespace mvm;
void (*client_sigsegv_handler)(int, void *) = 0;
#if defined(__MACH__) && defined(__i386__)
#include "ucontext.h"
#endif
void sigsegv_handler(int n, siginfo_t *_info, void *context) {
void *addr = _info->si_addr;
#if defined(__i386__)
struct frame {
struct frame *caller;
void *ip;
};
/* my frame */
struct frame *fp;
/* get it */
asm ("mov %%ebp, %0" : "=&r"(fp));
/* my caller */
struct frame *caller = fp->caller;
/* preserve my caller if I return from the handler */
void *caller_ip = caller->ip;
#if defined(__MACH__)
//.gregs[REG_EIP]; /* just like it's on the stack.. */
caller->ip = (void *)((ucontext_t*)context)->uc_mcontext->__ss.__eip;
#else
/* just like it's on the stack... */
caller->ip = (void *)((ucontext_t*)context)->uc_mcontext.gregs[REG_EIP];
#endif
#endif
/* Free the GC if it sisgegv'd. No other collection is possible */
#ifndef MULTIPLE_GC
Collector::die_if_sigsegv_occured_during_collection(addr);
#else
mvm::Thread::get()->GC->die_if_sigsegv_occured_during_collection(addr);
#endif
// sys_exit(0);
if(client_sigsegv_handler)
client_sigsegv_handler(n, addr);
else
signal(SIGSEGV, SIG_DFL);
#if defined(__i386__)
caller->ip = caller_ip; /* restore the caller ip */
#endif
}