fix up access violation handling on windows; refactor posix segv handling to match API change needed for windows

This commit is contained in:
Joel Dice 2008-01-01 10:08:47 -07:00
parent 100fc304ad
commit bdd62011eb
7 changed files with 91 additions and 46 deletions

View File

@ -59,13 +59,6 @@ test:
popq %rbp
ret
.globl vmJump
vmJump:
movq %rsi,%rbp
movq %rdx,%rsp
movq %rcx,%rbx
jmp *%rdi
#elif defined __i386__
# if defined __APPLE__ || defined __MINGW32__
@ -135,19 +128,6 @@ exit:
movl %ebp,%esp
popl %ebp
ret
# if defined __APPLE__ || defined __MINGW32__
.globl _vmJump
_vmJump:
# else
.globl vmJump
vmJump:
# endif
movl 4(%esp),%eax
movl 8(%esp),%ebp
movl 16(%esp),%ebx
movl 12(%esp),%esp
jmp *%eax
#else
# error unsupported platform

View File

@ -3,6 +3,7 @@
#include "vector.h"
#include "process.h"
#include "compiler.h"
#include "x86.h"
using namespace vm;
@ -13,9 +14,6 @@ vmInvoke(void* thread, void* function, void* stack, unsigned stackSize,
extern "C" void
vmCall();
extern "C" void NO_RETURN
vmJump(void* address, void* base, void* stack, void* thread);
namespace {
const bool Verbose = false;
@ -996,8 +994,9 @@ class Frame {
unsigned sp;
};
void NO_RETURN
unwind(MyThread* t)
void
findUnwindTarget(MyThread* t, void** targetIp, void** targetBase,
void** targetStack)
{
void* ip = t->ip;
void* base = t->base;
@ -1008,7 +1007,8 @@ unwind(MyThread* t)
ip = *stack;
}
while (true) {
*targetIp = 0;
while (*targetIp == 0) {
object node = findTraceNode(t, ip);
if (node) {
object method = traceNodeMethod(t, node);
@ -1028,7 +1028,9 @@ unwind(MyThread* t)
*(--stack) = t->exception;
t->exception = 0;
vmJump(compiled + exceptionHandlerIp(handler), base, stack, t);
*targetIp = compiled + exceptionHandlerIp(handler);
*targetBase = base;
*targetStack = stack;
} else {
if (methodFlags(t, method) & ACC_SYNCHRONIZED) {
object lock;
@ -1046,11 +1048,23 @@ unwind(MyThread* t)
base = *static_cast<void**>(base);
}
} else {
vmJump(ip, base, stack + 1, 0);
*targetIp = ip;
*targetBase = base;
*targetStack = stack + 1;
}
}
}
void NO_RETURN
unwind(MyThread* t)
{
void* ip;
void* base;
void* stack;
findUnwindTarget(t, &ip, &base, &stack);
vmJump(ip, base, stack, t);
}
void
insertTraceNode(MyThread* t, object method, object target, bool virtualCall,
uintptr_t* map, void* address)
@ -3997,15 +4011,22 @@ class SegFaultHandler: public System::SignalHandler {
public:
SegFaultHandler(): m(0) { }
virtual void handleSignal(void* ip, void* base, void* stack) {
virtual bool handleSignal(void** ip, void** base, void** stack,
void** thread)
{
MyThread* t = static_cast<MyThread*>(m->localThread->get());
object node = findTraceNode(t, ip);
object node = findTraceNode(t, *ip);
if (node) {
t->ip = ip;
t->base = base;
t->stack = stack;
t->ip = *ip;
t->base = *base;
t->stack = *stack;
t->exception = makeNullPointerException(t);
unwind(t);
findUnwindTarget(t, ip, base, stack);
*thread = t;
return true;
} else {
return false;
}
}

View File

@ -9,6 +9,7 @@
#include "unistd.h"
#include "pthread.h"
#include "signal.h"
#include "ucontext.h"
#include "stdint.h"
#include "x86.h"
@ -43,10 +44,12 @@ const int InterruptSignal = SIGUSR2;
const int IpRegister = REG_RIP;
const int BaseRegister = REG_RBP;
const int StackRegister = REG_RSP;
const int ThreadRegister = REG_RBX;
#elif defined __i386__
const int IpRegister = REG_EIP;
const int BaseRegister = REG_EBP;
const int StackRegister = REG_ESP;
const int ThreadRegister = REG_EBX;
#else
# error unsupported architecture
#endif
@ -61,15 +64,26 @@ handleSignal(int signal, siginfo_t* info, void* context)
sigaddset(&set, SIGSEGV);
sigprocmask(SIG_UNBLOCK, &set, 0);
greg_t* registers
= static_cast<ucontext_t*>(context)->uc_mcontext.gregs;
ucontext_t* c = static_cast<ucontext_t*>(context);
segFaultHandler->handleSignal
(reinterpret_cast<void*>(registers[IpRegister]),
reinterpret_cast<void*>(registers[BaseRegister]),
reinterpret_cast<void*>(registers[StackRegister]));
greg_t* registers = c->uc_mcontext.gregs;
bool jump = segFaultHandler->handleSignal
(reinterpret_cast<void**>(registers + IpRegister),
reinterpret_cast<void**>(registers + BaseRegister),
reinterpret_cast<void**>(registers + StackRegister),
reinterpret_cast<void**>(registers + ThreadRegister));
if (oldSegFaultHandler.sa_flags & SA_SIGINFO) {
if (jump) {
// I'd like to use setcontext here (and get rid of the
// sigprocmask call above), but it doesn't work on my system,
// and I can't tell from the documentation if it's even supposed
// to work.
vmJump(reinterpret_cast<void*>(registers[IpRegister]),
reinterpret_cast<void*>(registers[BaseRegister]),
reinterpret_cast<void*>(registers[StackRegister]),
reinterpret_cast<void*>(registers[ThreadRegister]));
} else if (oldSegFaultHandler.sa_flags & SA_SIGINFO) {
oldSegFaultHandler.sa_sigaction(signal, info, context);
} else if (oldSegFaultHandler.sa_handler) {
oldSegFaultHandler.sa_handler(signal);

View File

@ -84,7 +84,8 @@ class System: public Allocator {
public:
virtual ~SignalHandler() { }
virtual void handleSignal(void* ip, void* base, void* stack) = 0;
virtual bool handleSignal(void** ip, void** base, void** stack,
void** thread) = 0;
};
virtual ~System() { }

View File

@ -20,10 +20,15 @@ LONG CALLBACK
handleException(LPEXCEPTION_POINTERS e)
{
if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
segFaultHandler->handleSignal
(reinterpret_cast<void*>(e->ContextRecord->Eip),
reinterpret_cast<void*>(e->ContextRecord->Ebp),
reinterpret_cast<void*>(e->ContextRecord->Esp));
bool jump = segFaultHandler->handleSignal
(reinterpret_cast<void**>(&(e->ContextRecord->Eip)),
reinterpret_cast<void**>(&(e->ContextRecord->Ebp)),
reinterpret_cast<void**>(&(e->ContextRecord->Esp)),
reinterpret_cast<void**>(&(e->ContextRecord->Ebx)));
if (jump) {
return EXCEPTION_CONTINUE_EXECUTION;
}
}
return EXCEPTION_CONTINUE_SEARCH;
}

View File

@ -106,6 +106,13 @@ exit:
popq %rbp
ret
.globl vmJump
vmJump:
movq %rsi,%rbp
movq %rdx,%rsp
movq %rcx,%rbx
jmp *%rdi
#elif defined __i386__
# if defined __APPLE__ || defined __MINGW32__
@ -184,6 +191,19 @@ exit:
movl %ebp,%esp
popl %ebp
ret
# if defined __APPLE__ || defined __MINGW32__
.globl _vmJump
_vmJump:
# else
.globl vmJump
vmJump:
# endif
movl 4(%esp),%eax
movl 8(%esp),%ebp
movl 16(%esp),%ebx
movl 12(%esp),%esp
jmp *%eax
#else
# error unsupported platform

View File

@ -3,6 +3,10 @@
#include "types.h"
#include "stdint.h"
#include "common.h"
extern "C" void NO_RETURN
vmJump(void* address, void* base, void* stack, void* thread);
#ifdef __i386__