blob: 8587e41bd0b6f767d62f143c8a0023d07932d765 [file] [log] [blame]
//===----------- Sigsegv.cpp - Sigsegv default handling -------------------===//
//
// The VMKit project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "vmkit/MethodInfo.h"
#include "vmkit/System.h"
#include "vmkit/VirtualMachine.h"
#include "vmkit/Thread.h"
#include "vmkit/Locks.h"
#include <csignal>
#include <cstdio>
using namespace vmkit;
namespace {
class Handler {
void* context;
public:
Handler(void* ucontext): context(ucontext) {}
void UpdateRegistersForNPE();
void UpdateRegistersForStackOverflow();
};
}
#if defined(ARCH_X64) && defined(LINUX_OS)
#include "Sigsegv-linux-x64.inc"
#elif defined(ARCH_X86) && defined(LINUX_OS)
#include "Sigsegv-linux-x86.inc"
#elif defined(ARCH_X64) && defined(MACOS_OS)
#include "Sigsegv-macos-x64.inc"
#else
void Handler::UpdateRegistersForStackOverflow() {
UNREACHABLE();
}
void Handler::UpdateRegistersForNPE() {
UNREACHABLE();
}
bool System::SupportsHardwareNullCheck() {
return false;
}
bool System::SupportsHardwareStackOverflow() {
return false;
}
#endif
extern "C" void ThrowStackOverflowError(word_t ip) {
vmkit::Thread* th = vmkit::Thread::get();
vmkit::FrameInfo* FI = th->MyVM->IPToFrameInfo(ip);
if (FI->Metadata == NULL) {
fprintf(stderr, "Thread %p received a SIGSEGV: either the VM code or an external\n"
"native method is bogus. Aborting...\n", (void*)th);
abort();
} else {
vmkit::Thread::get()->MyVM->stackOverflowError();
}
UNREACHABLE();
}
extern "C" void ThrowNullPointerException(word_t ip) {
vmkit::Thread::get()->throwNullPointerException(ip);
}
void sigsegvHandler(int n, siginfo_t *info, void *context) {
Handler handler(context);
vmkit::Thread* th = vmkit::Thread::get();
word_t addr = (word_t)info->si_addr;
if (th->IsStackOverflowAddr(addr)) {
if (vmkit::System::SupportsHardwareStackOverflow()) {
handler.UpdateRegistersForStackOverflow();
} else {
fprintf(stderr, "Stack overflow in VM code or in JNI code. If it is from\n"
"the VM, it is either from the JIT, the GC or the runtime."
"\nThis has to be fixed in the VM: VMKit makes sure that\n"
"the bottom of the stack is always available when entering"
"\nthe VM.\n");
abort();
}
} else {
if (vmkit::System::SupportsHardwareNullCheck()) {
handler.UpdateRegistersForNPE();
} else {
fprintf(stderr, "Thread %p received a SIGSEGV: either the VM code or an external\n"
"native method is bogus. Aborting...\n", (void*)th);
abort();
}
}
}
void sigsTermHandler(int n, siginfo_t *info, void *context) {
//fprintf(stderr, "\nJVM termination because user request\n");
finishForCtrl_C = true;
condForCtrl_C.signal();
//lockForCtrl_C.Lock();
//lockForCtrl_C.unlock()
//Thread::get()->onVMTermination();
//UserClass* cl = vm->upcalls->SystemClass;
//vm -> upcalls->SystemExit->invokeIntStatic(vm,Class* cl, 0);
}