throw ArithmeticException on divide-by-zero

This commit is contained in:
Joel Dice 2010-12-19 17:47:21 -07:00
parent d18240cbd6
commit 306f1282d0
12 changed files with 386 additions and 74 deletions

View File

@ -1017,14 +1017,20 @@ class Context {
} }
} }
virtual intptr_t getThunk(TernaryOperation op, unsigned size, unsigned) { virtual intptr_t getThunk(TernaryOperation op, unsigned size, unsigned,
bool* threadParameter)
{
*threadParameter = false;
if (size == 8) { if (size == 8) {
switch (op) { switch (op) {
case Divide: case Divide:
*threadParameter = true;
return local::getThunk(t, divideLongThunk); return local::getThunk(t, divideLongThunk);
case Remainder: case Remainder:
return local::getThunk(t, moduloLongThunk); *threadParameter = true;
return local::getThunk(t, moduloLongThunk);
case FloatAdd: case FloatAdd:
return local::getThunk(t, addDoubleThunk); return local::getThunk(t, addDoubleThunk);
@ -1061,9 +1067,11 @@ class Context {
assert(t, size == 4); assert(t, size == 4);
switch (op) { switch (op) {
case Divide: case Divide:
*threadParameter = true;
return local::getThunk(t, divideIntThunk); return local::getThunk(t, divideIntThunk);
case Remainder: case Remainder:
*threadParameter = true;
return local::getThunk(t, moduloIntThunk); return local::getThunk(t, moduloIntThunk);
case FloatAdd: case FloatAdd:
@ -2358,26 +2366,47 @@ absoluteInt(int32_t a)
} }
int64_t int64_t
divideLong(int64_t b, int64_t a) divideLong(MyThread* t, int64_t b, int64_t a)
{ {
return a / b; if (LIKELY(b)) {
return a / b;
} else {
t->exception = makeThrowable(t, Machine::ArithmeticExceptionType);
unwind(t);
}
} }
int64_t int64_t
divideInt(int32_t b, int32_t a) divideInt(MyThread* t, int32_t b, int32_t a)
{ {
return a / b; if (LIKELY(b)) {
return a / b;
} else {
t->exception = makeThrowable(t, Machine::ArithmeticExceptionType);
unwind(t);
}
} }
int64_t int64_t
moduloLong(int64_t b, int64_t a) moduloLong(MyThread* t, int64_t b, int64_t a)
{ {
return a % b; if (LIKELY(b)) {
return a % b;
} else {
t->exception = makeThrowable(t, Machine::ArithmeticExceptionType);
unwind(t);
}
} }
int64_t int64_t
moduloInt(int32_t b, int32_t a) { moduloInt(MyThread* t, int32_t b, int32_t a)
return a % b; {
if (LIKELY(b)) {
return a % b;
} else {
t->exception = makeThrowable(t, Machine::ArithmeticExceptionType);
unwind(t);
}
} }
uint64_t uint64_t
@ -3949,6 +3978,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case idiv: { case idiv: {
Compiler::Operand* a = frame->popInt(); Compiler::Operand* a = frame->popInt();
Compiler::Operand* b = frame->popInt(); Compiler::Operand* b = frame->popInt();
if (inTryBlock(t, code, ip - 1)) {
c->saveLocals();
frame->trace(0, 0);
}
frame->pushInt(c->div(4, a, b)); frame->pushInt(c->div(4, a, b));
} break; } break;
@ -4262,6 +4297,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case irem: { case irem: {
Compiler::Operand* a = frame->popInt(); Compiler::Operand* a = frame->popInt();
Compiler::Operand* b = frame->popInt(); Compiler::Operand* b = frame->popInt();
if (inTryBlock(t, code, ip - 1)) {
c->saveLocals();
frame->trace(0, 0);
}
frame->pushInt(c->rem(4, a, b)); frame->pushInt(c->rem(4, a, b));
} break; } break;
@ -4459,6 +4500,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case ldiv_: { case ldiv_: {
Compiler::Operand* a = frame->popLong(); Compiler::Operand* a = frame->popLong();
Compiler::Operand* b = frame->popLong(); Compiler::Operand* b = frame->popLong();
if (inTryBlock(t, code, ip - 1)) {
c->saveLocals();
frame->trace(0, 0);
}
frame->pushLong(c->div(8, a, b)); frame->pushLong(c->div(8, a, b));
} break; } break;
@ -4564,6 +4611,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case lrem: { case lrem: {
Compiler::Operand* a = frame->popLong(); Compiler::Operand* a = frame->popLong();
Compiler::Operand* b = frame->popLong(); Compiler::Operand* b = frame->popLong();
if (inTryBlock(t, code, ip - 1)) {
c->saveLocals();
frame->trace(0, 0);
}
frame->pushLong(c->rem(8, a, b)); frame->pushLong(c->rem(8, a, b));
} break; } break;
@ -7186,9 +7239,10 @@ invoke(Thread* thread, object method, ArgumentList* arguments)
return r; return r;
} }
class SegFaultHandler: public System::SignalHandler { class SignalHandler: public System::SignalHandler {
public: public:
SegFaultHandler(): m(0) { } SignalHandler(Machine::Type type, Machine::Root root, unsigned fixedSize):
m(0), type(type), root(root), fixedSize(fixedSize) { }
virtual bool handleSignal(void** ip, void** base, void** stack, virtual bool handleSignal(void** ip, void** base, void** stack,
void** thread) void** thread)
@ -7204,14 +7258,14 @@ class SegFaultHandler: public System::SignalHandler {
static_cast<void**>(*stack) - t->arch->frameReturnAddressSize(), static_cast<void**>(*stack) - t->arch->frameReturnAddressSize(),
*base, t->continuation, t->trace); *base, t->continuation, t->trace);
if (ensure(t, FixedSizeOfNullPointerException + traceSize(t))) { if (ensure(t, fixedSize + traceSize(t))) {
atomicOr(&(t->flags), Thread::TracingFlag); atomicOr(&(t->flags), Thread::TracingFlag);
t->exception = makeThrowable(t, Machine::NullPointerExceptionType); t->exception = makeThrowable(t, type);
atomicAnd(&(t->flags), ~Thread::TracingFlag); atomicAnd(&(t->flags), ~Thread::TracingFlag);
} else { } else {
// not enough memory available for a new NPE and stack trace // not enough memory available for a new exception and stack
// -- use a preallocated instance instead // trace -- use a preallocated instance instead
t->exception = root(t, Machine::NullPointerException); t->exception = vm::root(t, root);
} }
// printTrace(t, t->exception); // printTrace(t, t->exception);
@ -7235,6 +7289,9 @@ class SegFaultHandler: public System::SignalHandler {
} }
Machine* m; Machine* m;
Machine::Type type;
Machine::Root root;
unsigned fixedSize;
}; };
bool bool
@ -7289,6 +7346,12 @@ class MyProcessor: public Processor {
allocator(allocator), allocator(allocator),
roots(0), roots(0),
bootImage(0), bootImage(0),
segFaultHandler(Machine::NullPointerExceptionType,
Machine::NullPointerException,
FixedSizeOfNullPointerException),
divideByZeroHandler(Machine::ArithmeticExceptionType,
Machine::ArithmeticException,
FixedSizeOfArithmeticException),
codeAllocator(s, 0, 0), codeAllocator(s, 0, 0),
callTableSize(0), callTableSize(0),
useNativeFeatures(useNativeFeatures) useNativeFeatures(useNativeFeatures)
@ -7744,6 +7807,10 @@ class MyProcessor: public Processor {
segFaultHandler.m = t->m; segFaultHandler.m = t->m;
expect(t, t->m->system->success expect(t, t->m->system->success
(t->m->system->handleSegFault(&segFaultHandler))); (t->m->system->handleSegFault(&segFaultHandler)));
divideByZeroHandler.m = t->m;
expect(t, t->m->system->success
(t->m->system->handleDivideByZero(&divideByZeroHandler)));
} }
virtual void callWithCurrentContinuation(Thread* t, object receiver) { virtual void callWithCurrentContinuation(Thread* t, object receiver) {
@ -7798,7 +7865,8 @@ class MyProcessor: public Processor {
Allocator* allocator; Allocator* allocator;
object roots; object roots;
BootImage* bootImage; BootImage* bootImage;
SegFaultHandler segFaultHandler; SignalHandler segFaultHandler;
SignalHandler divideByZeroHandler;
FixedAllocator codeAllocator; FixedAllocator codeAllocator;
ThunkCollection thunks; ThunkCollection thunks;
ThunkCollection bootThunks; ThunkCollection bootThunks;

View File

@ -4336,6 +4336,19 @@ loadLocal(Context* c, unsigned footprint, unsigned index)
return c->locals[index].value; return c->locals[index].value;
} }
Value*
register_(Context* c, int number)
{
assert(c, (1 << number) & (c->arch->generalRegisterMask()
| c->arch->floatRegisterMask()));
Site* s = registerSite(c, number);
ValueType type = ((1 << number) & c->arch->floatRegisterMask())
? ValueFloat: ValueGeneral;
return value(c, type, s, s);
}
void void
appendCombine(Context* c, TernaryOperation type, appendCombine(Context* c, TernaryOperation type,
unsigned firstSize, Value* first, unsigned firstSize, Value* first,
@ -4349,25 +4362,34 @@ appendCombine(Context* c, TernaryOperation type,
uint64_t secondRegisterMask; uint64_t secondRegisterMask;
c->arch->planSource(type, firstSize, &firstTypeMask, &firstRegisterMask, c->arch->planSource(type, firstSize, &firstTypeMask, &firstRegisterMask,
secondSize, &secondTypeMask, &secondRegisterMask, secondSize, &secondTypeMask, &secondRegisterMask,
resultSize, &thunk); resultSize, &thunk);
if (thunk) { if (thunk) {
Stack* oldStack = c->stack; Stack* oldStack = c->stack;
bool threadParameter;
intptr_t handler = c->client->getThunk
(type, firstSize, resultSize, &threadParameter);
unsigned stackSize = ceiling(secondSize, BytesPerWord)
+ ceiling(firstSize, BytesPerWord);
local::push(c, ceiling(secondSize, BytesPerWord), second); local::push(c, ceiling(secondSize, BytesPerWord), second);
local::push(c, ceiling(firstSize, BytesPerWord), first); local::push(c, ceiling(firstSize, BytesPerWord), first);
if (threadParameter) {
++ stackSize;
local::push(c, 1, register_(c, c->arch->thread()));
}
Stack* argumentStack = c->stack; Stack* argumentStack = c->stack;
c->stack = oldStack; c->stack = oldStack;
appendCall appendCall
(c, value (c, value(c, ValueGeneral, constantSite(c, handler)), 0, 0, result,
(c, ValueGeneral, constantSite resultSize, argumentStack, stackSize, 0);
(c, c->client->getThunk(type, firstSize, resultSize))),
0, 0, result, resultSize, argumentStack,
ceiling(secondSize, BytesPerWord) + ceiling(firstSize, BytesPerWord),
0);
} else { } else {
append append
(c, new (c->zone->allocate(sizeof(CombineEvent))) (c, new (c->zone->allocate(sizeof(CombineEvent)))
@ -4792,6 +4814,12 @@ appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first,
if (thunk) { if (thunk) {
Stack* oldStack = c->stack; Stack* oldStack = c->stack;
bool threadParameter;
intptr_t handler = c->client->getThunk
(type, size, size, &threadParameter);
assert(c, not threadParameter);
local::push(c, ceiling(size, BytesPerWord), second); local::push(c, ceiling(size, BytesPerWord), second);
local::push(c, ceiling(size, BytesPerWord), first); local::push(c, ceiling(size, BytesPerWord), first);
@ -4801,9 +4829,8 @@ appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first,
Value* result = value(c, ValueGeneral); Value* result = value(c, ValueGeneral);
appendCall appendCall
(c, value (c, value
(c, ValueGeneral, constantSite(c, c->client->getThunk(type, size, 4))), (c, ValueGeneral, constantSite(c, handler)), 0, 0, result, 4,
0, 0, result, 4, argumentStack, argumentStack, ceiling(size, BytesPerWord) * 2, 0);
ceiling(size, BytesPerWord) * 2, 0);
appendBranch(c, thunkBranch(c, type), 4, value appendBranch(c, thunkBranch(c, type), 4, value
(c, ValueGeneral, constantSite(c, static_cast<int64_t>(0))), (c, ValueGeneral, constantSite(c, static_cast<int64_t>(0))),
@ -6167,14 +6194,7 @@ class MyCompiler: public Compiler {
} }
virtual Operand* register_(int number) { virtual Operand* register_(int number) {
assert(&c, (1 << number) & (c.arch->generalRegisterMask() return local::register_(&c, number);
| c.arch->floatRegisterMask()));
Site* s = registerSite(&c, number);
ValueType type = ((1 << number) & c.arch->floatRegisterMask())
? ValueFloat: ValueGeneral;
return value(&c, type, s, s);
} }
Promise* machineIp() { Promise* machineIp() {

View File

@ -30,7 +30,7 @@ class Compiler {
virtual intptr_t getThunk(BinaryOperation op, unsigned size, virtual intptr_t getThunk(BinaryOperation op, unsigned size,
unsigned resultSize) = 0; unsigned resultSize) = 0;
virtual intptr_t getThunk(TernaryOperation op, unsigned size, virtual intptr_t getThunk(TernaryOperation op, unsigned size,
unsigned resultSize) = 0; unsigned resultSize, bool* threadParameter) = 0;
}; };
static const unsigned Aligned = 1 << 0; static const unsigned Aligned = 1 << 0;

View File

@ -1665,6 +1665,11 @@ interpret(Thread* t)
case idiv: { case idiv: {
int32_t b = popInt(t); int32_t b = popInt(t);
int32_t a = popInt(t); int32_t a = popInt(t);
if (UNLIKELY(b == 0)) {
exception = makeThrowable(t, Machine::ArithmeticExceptionType);
goto throw_;
}
pushInt(t, a / b); pushInt(t, a / b);
} goto loop; } goto loop;
@ -1968,6 +1973,11 @@ interpret(Thread* t)
int32_t b = popInt(t); int32_t b = popInt(t);
int32_t a = popInt(t); int32_t a = popInt(t);
if (UNLIKELY(b == 0)) {
exception = makeThrowable(t, Machine::ArithmeticExceptionType);
goto throw_;
}
pushInt(t, a % b); pushInt(t, a % b);
} goto loop; } goto loop;
@ -2187,6 +2197,11 @@ interpret(Thread* t)
int64_t b = popLong(t); int64_t b = popLong(t);
int64_t a = popLong(t); int64_t a = popLong(t);
if (UNLIKELY(b == 0)) {
exception = makeThrowable(t, Machine::ArithmeticExceptionType);
goto throw_;
}
pushLong(t, a / b); pushLong(t, a / b);
} goto loop; } goto loop;
@ -2269,6 +2284,11 @@ interpret(Thread* t)
int64_t b = popLong(t); int64_t b = popLong(t);
int64_t a = popLong(t); int64_t a = popLong(t);
if (UNLIKELY(b == 0)) {
exception = makeThrowable(t, Machine::ArithmeticExceptionType);
goto throw_;
}
pushLong(t, a % b); pushLong(t, a % b);
} goto loop; } goto loop;

View File

@ -2035,8 +2035,13 @@ boot(Thread* t)
(t, Machine::NullPointerExceptionType)); (t, Machine::NullPointerExceptionType));
if (t->exception == 0) { if (t->exception == 0) {
setRoot(t, Machine::ArrayIndexOutOfBoundsException, setRoot(t, Machine::ArithmeticException,
makeThrowable(t, Machine::ArrayIndexOutOfBoundsExceptionType)); makeThrowable(t, Machine::ArithmeticExceptionType));
if (t->exception == 0) {
setRoot(t, Machine::ArrayIndexOutOfBoundsException,
makeThrowable(t, Machine::ArrayIndexOutOfBoundsExceptionType));
}
} }
} }

View File

@ -1203,6 +1203,7 @@ class Machine {
ShutdownHooks, ShutdownHooks,
ObjectsToFinalize, ObjectsToFinalize,
NullPointerException, NullPointerException,
ArithmeticException,
ArrayIndexOutOfBoundsException, ArrayIndexOutOfBoundsException,
VirtualFileFinders, VirtualFileFinders,
VirtualFiles VirtualFiles

View File

@ -69,14 +69,17 @@ const int AltSegFaultSignal = InvalidSignal;
const unsigned AltSegFaultSignalIndex = 3; const unsigned AltSegFaultSignalIndex = 3;
const int PipeSignal = SIGPIPE; const int PipeSignal = SIGPIPE;
const unsigned PipeSignalIndex = 4; const unsigned PipeSignalIndex = 4;
const int DivideByZeroSignal = SIGFPE;
const unsigned DivideByZeroSignalIndex = 5;
const int signals[] = { VisitSignal, const int signals[] = { VisitSignal,
SegFaultSignal, SegFaultSignal,
InterruptSignal, InterruptSignal,
AltSegFaultSignal, AltSegFaultSignal,
PipeSignal }; PipeSignal,
DivideByZeroSignal };
const unsigned SignalCount = 5; const unsigned SignalCount = 6;
class MySystem; class MySystem;
MySystem* system; MySystem* system;
@ -530,6 +533,8 @@ class MySystem: public System {
expect(this, system == 0); expect(this, system == 0);
system = this; system = this;
memset(handlers, 0, sizeof(handlers));
registerHandler(&nullHandler, InterruptSignalIndex); registerHandler(&nullHandler, InterruptSignalIndex);
registerHandler(&nullHandler, PipeSignalIndex); registerHandler(&nullHandler, PipeSignalIndex);
registerHandler(&nullHandler, VisitSignalIndex); registerHandler(&nullHandler, VisitSignalIndex);
@ -631,6 +636,10 @@ class MySystem: public System {
return s; return s;
} }
virtual Status handleDivideByZero(SignalHandler* handler) {
return registerHandler(handler, DivideByZeroSignalIndex);
}
virtual Status visit(System::Thread* st, System::Thread* sTarget, virtual Status visit(System::Thread* st, System::Thread* sTarget,
ThreadVisitor* visitor) ThreadVisitor* visitor)
{ {
@ -847,12 +856,25 @@ handleSignal(int signal, siginfo_t* info, void* context)
} break; } break;
case SegFaultSignal: case SegFaultSignal:
case AltSegFaultSignal: { case AltSegFaultSignal:
if (signal == SegFaultSignal) { case DivideByZeroSignal: {
switch (signal) {
case SegFaultSignal:
index = SegFaultSignalIndex; index = SegFaultSignalIndex;
} else { break;
case AltSegFaultSignal:
index = AltSegFaultSignalIndex; index = AltSegFaultSignalIndex;
break;
case DivideByZeroSignal:
index = DivideByZeroSignalIndex;
break;
default:
abort();
} }
bool jump = system->handlers[index]->handleSignal bool jump = system->handlers[index]->handleSignal
(&ip, &base, &stack, &thread); (&ip, &base, &stack, &thread);

View File

@ -126,6 +126,7 @@ class System {
virtual Status make(Monitor**) = 0; virtual Status make(Monitor**) = 0;
virtual Status make(Local**) = 0; virtual Status make(Local**) = 0;
virtual Status handleSegFault(SignalHandler* handler) = 0; virtual Status handleSegFault(SignalHandler* handler) = 0;
virtual Status handleDivideByZero(SignalHandler* handler) = 0;
virtual Status visit(Thread* thread, Thread* target, virtual Status visit(Thread* thread, Thread* target,
ThreadVisitor* visitor) = 0; ThreadVisitor* visitor) = 0;
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types, virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,

View File

@ -205,6 +205,8 @@
(type nullPointerException java/lang/NullPointerException) (type nullPointerException java/lang/NullPointerException)
(type arithmeticException java/lang/ArithmeticException)
(type illegalStateException java/lang/IllegalStateException) (type illegalStateException java/lang/IllegalStateException)
(type illegalArgumentException java/lang/IllegalArgumentException) (type illegalArgumentException java/lang/IllegalArgumentException)

View File

@ -49,6 +49,11 @@ class MutexResource {
HANDLE m; HANDLE m;
}; };
const unsigned SegFaultIndex = 0;
const unsigned DivideByZeroIndex = 1;
const unsigned HandlerCount = 2;
class MySystem; class MySystem;
MySystem* system; MySystem* system;
@ -510,17 +515,57 @@ class MySystem: public System {
}; };
MySystem(const char* crashDumpDirectory): MySystem(const char* crashDumpDirectory):
segFaultHandler(0), oldHandler(0),
oldSegFaultHandler(0),
crashDumpDirectory(crashDumpDirectory) crashDumpDirectory(crashDumpDirectory)
{ {
expect(this, system == 0); expect(this, system == 0);
system = this; system = this;
memset(handlers, 0, sizeof(handlers));
mutex = CreateMutex(0, false, 0); mutex = CreateMutex(0, false, 0);
assert(this, mutex); assert(this, mutex);
} }
bool findHandler() {
for (unsigned i = 0; i < HandlerCount; ++i) {
if (handlers[i]) return true;
}
return false;
}
int registerHandler(System::SignalHandler* handler, int index) {
if (handler) {
handlers[index] = handler;
if (oldHandler == 0) {
#ifdef ARCH_x86_32
oldHandler = SetUnhandledExceptionFilter(handleException);
#elif defined ARCH_x86_64
AddVectoredExceptionHandler(1, handleException);
oldHandler = reinterpret_cast<LPTOP_LEVEL_EXCEPTION_FILTER>(1);
#endif
}
return 0;
} else if (handlers[index]) {
handlers[index] = 0;
if (not findHandler()) {
#ifdef ARCH_x86_32
SetUnhandledExceptionFilter(oldHandler);
oldHandler = 0;
#elif defined ARCH_x86_64
// do nothing, handlers are never "unregistered" anyway
#endif
}
return 0;
} else {
return 1;
}
}
virtual void* tryAllocate(unsigned sizeInBytes) { virtual void* tryAllocate(unsigned sizeInBytes) {
return malloc(sizeInBytes); return malloc(sizeInBytes);
} }
@ -578,27 +623,11 @@ class MySystem: public System {
} }
virtual Status handleSegFault(SignalHandler* handler) { virtual Status handleSegFault(SignalHandler* handler) {
if (handler) { return registerHandler(handler, SegFaultIndex);
segFaultHandler = handler; }
#ifdef ARCH_x86_32 virtual Status handleDivideByZero(SignalHandler* handler) {
oldSegFaultHandler = SetUnhandledExceptionFilter(handleException); return registerHandler(handler, DivideByZeroIndex);
#elif defined ARCH_x86_64
AddVectoredExceptionHandler(1, handleException);
oldSegFaultHandler = 0;
#endif
return 0;
} else if (segFaultHandler) {
segFaultHandler = 0;
#ifdef ARCH_x86_32
SetUnhandledExceptionFilter(oldSegFaultHandler);
#elif defined ARCH_x86_64
//do nothing, handlers are never "unregistered" anyway
#endif
return 0;
} else {
return 1;
}
} }
virtual Status visit(System::Thread* st UNUSED, System::Thread* sTarget, virtual Status visit(System::Thread* st UNUSED, System::Thread* sTarget,
@ -795,8 +824,8 @@ class MySystem: public System {
} }
HANDLE mutex; HANDLE mutex;
System::SignalHandler* segFaultHandler; SignalHandler* handlers[HandlerCount];
LPTOP_LEVEL_EXCEPTION_FILTER oldSegFaultHandler; LPTOP_LEVEL_EXCEPTION_FILTER oldHandler;
const char* crashDumpDirectory; const char* crashDumpDirectory;
}; };
@ -867,7 +896,15 @@ dump(LPEXCEPTION_POINTERS e, const char* directory)
LONG CALLBACK LONG CALLBACK
handleException(LPEXCEPTION_POINTERS e) handleException(LPEXCEPTION_POINTERS e)
{ {
System::SignalHandler* handler = 0;
if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
handler = system->handlers[SegFaultIndex];
} else if (e->ExceptionRecord->ExceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO)
{
handler = system->handlers[DivideByZeroIndex];
}
if (handler) {
#ifdef ARCH_x86_32 #ifdef ARCH_x86_32
void* ip = reinterpret_cast<void*>(e->ContextRecord->Eip); void* ip = reinterpret_cast<void*>(e->ContextRecord->Eip);
void* base = reinterpret_cast<void*>(e->ContextRecord->Ebp); void* base = reinterpret_cast<void*>(e->ContextRecord->Ebp);
@ -880,8 +917,8 @@ handleException(LPEXCEPTION_POINTERS e)
void* thread = reinterpret_cast<void*>(e->ContextRecord->Rbx); void* thread = reinterpret_cast<void*>(e->ContextRecord->Rbx);
#endif #endif
bool jump = system->segFaultHandler->handleSignal bool jump = handler->handleSignal(&ip, &base, &stack, &thread);
(&ip, &base, &stack, &thread);
#ifdef ARCH_x86_32 #ifdef ARCH_x86_32
e->ContextRecord->Eip = reinterpret_cast<DWORD>(ip); e->ContextRecord->Eip = reinterpret_cast<DWORD>(ip);
e->ContextRecord->Ebp = reinterpret_cast<DWORD>(base); e->ContextRecord->Ebp = reinterpret_cast<DWORD>(base);
@ -897,10 +934,10 @@ handleException(LPEXCEPTION_POINTERS e)
if (jump) { if (jump) {
return EXCEPTION_CONTINUE_EXECUTION; return EXCEPTION_CONTINUE_EXECUTION;
} }
}
if (system->crashDumpDirectory) { if (system->crashDumpDirectory) {
dump(e, system->crashDumpDirectory); dump(e, system->crashDumpDirectory);
}
} }
return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_SEARCH;

135
test/DivideByZero.java Normal file
View File

@ -0,0 +1,135 @@
public class DivideByZero {
private static int divide(int n, int d) {
return n / d;
}
private static int modulo(int n, int d) {
return n % d;
}
private static long divide(long n, long d) {
return n / d;
}
private static long modulo(long n, long d) {
return n % d;
}
private static float divide(float n, float d) {
return n / d;
}
private static float modulo(float n, float d) {
return n % d;
}
private static double divide(double n, double d) {
return n / d;
}
private static double modulo(double n, double d) {
return n % d;
}
public static void main(String[] args) {
try {
int x = 1 / 0;
throw new RuntimeException();
} catch (ArithmeticException e) {
e.printStackTrace();
}
try {
int x = 1 % 0;
throw new RuntimeException();
} catch (ArithmeticException e) {
e.printStackTrace();
}
try {
int y = 2;
int x = y / 0;
throw new RuntimeException();
} catch (ArithmeticException e) {
e.printStackTrace();
}
try {
int y = 2;
int x = y % 0;
throw new RuntimeException();
} catch (ArithmeticException e) {
e.printStackTrace();
}
try {
int z = 0;
int y = 2;
int x = y / z;
throw new RuntimeException();
} catch (ArithmeticException e) {
e.printStackTrace();
}
try {
int z = 0;
int y = 2;
int x = y % z;
throw new RuntimeException();
} catch (ArithmeticException e) {
e.printStackTrace();
}
try {
long z = 0;
long y = 2;
long x = y / z;
throw new RuntimeException();
} catch (ArithmeticException e) {
e.printStackTrace();
}
try {
long z = 0;
long y = 2;
long x = y % z;
throw new RuntimeException();
} catch (ArithmeticException e) {
e.printStackTrace();
}
try {
divide(5, 0);
throw new RuntimeException();
} catch (ArithmeticException e) {
e.printStackTrace();
}
try {
modulo(6, 0);
throw new RuntimeException();
} catch (ArithmeticException e) {
e.printStackTrace();
}
try {
divide(5L, 0L);
throw new RuntimeException();
} catch (ArithmeticException e) {
e.printStackTrace();
}
try {
modulo(6L, 0L);
throw new RuntimeException();
} catch (ArithmeticException e) {
e.printStackTrace();
}
divide(5F, 0F);
modulo(6F, 0F);
divide(5D, 0D);
modulo(6D, 0D);
}
}

1
vm.pro
View File

@ -57,6 +57,7 @@
-keep public class java.lang.ClassCastException -keep public class java.lang.ClassCastException
-keep public class java.lang.ClassNotFoundException -keep public class java.lang.ClassNotFoundException
-keep public class java.lang.NullPointerException -keep public class java.lang.NullPointerException
-keep public class java.lang.ArithmeticException
-keep public class java.lang.InterruptedException -keep public class java.lang.InterruptedException
-keep public class java.lang.StackOverflowError -keep public class java.lang.StackOverflowError
-keep public class java.lang.NoSuchFieldError -keep public class java.lang.NoSuchFieldError