mirror of
https://github.com/corda/corda.git
synced 2025-01-01 02:36:44 +00:00
throw ArithmeticException on divide-by-zero
This commit is contained in:
parent
d18240cbd6
commit
306f1282d0
104
src/compile.cpp
104
src/compile.cpp
@ -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) {
|
||||
switch (op) {
|
||||
case Divide:
|
||||
*threadParameter = true;
|
||||
return local::getThunk(t, divideLongThunk);
|
||||
|
||||
case Remainder:
|
||||
return local::getThunk(t, moduloLongThunk);
|
||||
*threadParameter = true;
|
||||
return local::getThunk(t, moduloLongThunk);
|
||||
|
||||
case FloatAdd:
|
||||
return local::getThunk(t, addDoubleThunk);
|
||||
@ -1061,9 +1067,11 @@ class Context {
|
||||
assert(t, size == 4);
|
||||
switch (op) {
|
||||
case Divide:
|
||||
*threadParameter = true;
|
||||
return local::getThunk(t, divideIntThunk);
|
||||
|
||||
case Remainder:
|
||||
*threadParameter = true;
|
||||
return local::getThunk(t, moduloIntThunk);
|
||||
|
||||
case FloatAdd:
|
||||
@ -2358,26 +2366,47 @@ absoluteInt(int32_t a)
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
moduloInt(int32_t b, int32_t a) {
|
||||
return a % b;
|
||||
moduloInt(MyThread* t, int32_t b, int32_t a)
|
||||
{
|
||||
if (LIKELY(b)) {
|
||||
return a % b;
|
||||
} else {
|
||||
t->exception = makeThrowable(t, Machine::ArithmeticExceptionType);
|
||||
unwind(t);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t
|
||||
@ -3949,6 +3978,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
case idiv: {
|
||||
Compiler::Operand* a = 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));
|
||||
} break;
|
||||
|
||||
@ -4262,6 +4297,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
case irem: {
|
||||
Compiler::Operand* a = 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));
|
||||
} break;
|
||||
|
||||
@ -4459,6 +4500,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
case ldiv_: {
|
||||
Compiler::Operand* a = 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));
|
||||
} break;
|
||||
|
||||
@ -4564,6 +4611,12 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
|
||||
case lrem: {
|
||||
Compiler::Operand* a = 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));
|
||||
} break;
|
||||
|
||||
@ -7186,9 +7239,10 @@ invoke(Thread* thread, object method, ArgumentList* arguments)
|
||||
return r;
|
||||
}
|
||||
|
||||
class SegFaultHandler: public System::SignalHandler {
|
||||
class SignalHandler: public System::SignalHandler {
|
||||
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,
|
||||
void** thread)
|
||||
@ -7204,14 +7258,14 @@ class SegFaultHandler: public System::SignalHandler {
|
||||
static_cast<void**>(*stack) - t->arch->frameReturnAddressSize(),
|
||||
*base, t->continuation, t->trace);
|
||||
|
||||
if (ensure(t, FixedSizeOfNullPointerException + traceSize(t))) {
|
||||
if (ensure(t, fixedSize + traceSize(t))) {
|
||||
atomicOr(&(t->flags), Thread::TracingFlag);
|
||||
t->exception = makeThrowable(t, Machine::NullPointerExceptionType);
|
||||
t->exception = makeThrowable(t, type);
|
||||
atomicAnd(&(t->flags), ~Thread::TracingFlag);
|
||||
} else {
|
||||
// not enough memory available for a new NPE and stack trace
|
||||
// -- use a preallocated instance instead
|
||||
t->exception = root(t, Machine::NullPointerException);
|
||||
// not enough memory available for a new exception and stack
|
||||
// trace -- use a preallocated instance instead
|
||||
t->exception = vm::root(t, root);
|
||||
}
|
||||
|
||||
// printTrace(t, t->exception);
|
||||
@ -7235,6 +7289,9 @@ class SegFaultHandler: public System::SignalHandler {
|
||||
}
|
||||
|
||||
Machine* m;
|
||||
Machine::Type type;
|
||||
Machine::Root root;
|
||||
unsigned fixedSize;
|
||||
};
|
||||
|
||||
bool
|
||||
@ -7289,6 +7346,12 @@ class MyProcessor: public Processor {
|
||||
allocator(allocator),
|
||||
roots(0),
|
||||
bootImage(0),
|
||||
segFaultHandler(Machine::NullPointerExceptionType,
|
||||
Machine::NullPointerException,
|
||||
FixedSizeOfNullPointerException),
|
||||
divideByZeroHandler(Machine::ArithmeticExceptionType,
|
||||
Machine::ArithmeticException,
|
||||
FixedSizeOfArithmeticException),
|
||||
codeAllocator(s, 0, 0),
|
||||
callTableSize(0),
|
||||
useNativeFeatures(useNativeFeatures)
|
||||
@ -7744,6 +7807,10 @@ class MyProcessor: public Processor {
|
||||
segFaultHandler.m = t->m;
|
||||
expect(t, t->m->system->success
|
||||
(t->m->system->handleSegFault(&segFaultHandler)));
|
||||
|
||||
divideByZeroHandler.m = t->m;
|
||||
expect(t, t->m->system->success
|
||||
(t->m->system->handleDivideByZero(÷ByZeroHandler)));
|
||||
}
|
||||
|
||||
virtual void callWithCurrentContinuation(Thread* t, object receiver) {
|
||||
@ -7798,7 +7865,8 @@ class MyProcessor: public Processor {
|
||||
Allocator* allocator;
|
||||
object roots;
|
||||
BootImage* bootImage;
|
||||
SegFaultHandler segFaultHandler;
|
||||
SignalHandler segFaultHandler;
|
||||
SignalHandler divideByZeroHandler;
|
||||
FixedAllocator codeAllocator;
|
||||
ThunkCollection thunks;
|
||||
ThunkCollection bootThunks;
|
||||
|
@ -4336,6 +4336,19 @@ loadLocal(Context* c, unsigned footprint, unsigned index)
|
||||
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
|
||||
appendCombine(Context* c, TernaryOperation type,
|
||||
unsigned firstSize, Value* first,
|
||||
@ -4349,25 +4362,34 @@ appendCombine(Context* c, TernaryOperation type,
|
||||
uint64_t secondRegisterMask;
|
||||
|
||||
c->arch->planSource(type, firstSize, &firstTypeMask, &firstRegisterMask,
|
||||
secondSize, &secondTypeMask, &secondRegisterMask,
|
||||
resultSize, &thunk);
|
||||
secondSize, &secondTypeMask, &secondRegisterMask,
|
||||
resultSize, &thunk);
|
||||
|
||||
if (thunk) {
|
||||
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(firstSize, BytesPerWord), first);
|
||||
|
||||
if (threadParameter) {
|
||||
++ stackSize;
|
||||
|
||||
local::push(c, 1, register_(c, c->arch->thread()));
|
||||
}
|
||||
|
||||
Stack* argumentStack = c->stack;
|
||||
c->stack = oldStack;
|
||||
|
||||
appendCall
|
||||
(c, value
|
||||
(c, ValueGeneral, constantSite
|
||||
(c, c->client->getThunk(type, firstSize, resultSize))),
|
||||
0, 0, result, resultSize, argumentStack,
|
||||
ceiling(secondSize, BytesPerWord) + ceiling(firstSize, BytesPerWord),
|
||||
0);
|
||||
(c, value(c, ValueGeneral, constantSite(c, handler)), 0, 0, result,
|
||||
resultSize, argumentStack, stackSize, 0);
|
||||
} else {
|
||||
append
|
||||
(c, new (c->zone->allocate(sizeof(CombineEvent)))
|
||||
@ -4792,6 +4814,12 @@ appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first,
|
||||
if (thunk) {
|
||||
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), first);
|
||||
|
||||
@ -4801,9 +4829,8 @@ appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first,
|
||||
Value* result = value(c, ValueGeneral);
|
||||
appendCall
|
||||
(c, value
|
||||
(c, ValueGeneral, constantSite(c, c->client->getThunk(type, size, 4))),
|
||||
0, 0, result, 4, argumentStack,
|
||||
ceiling(size, BytesPerWord) * 2, 0);
|
||||
(c, ValueGeneral, constantSite(c, handler)), 0, 0, result, 4,
|
||||
argumentStack, ceiling(size, BytesPerWord) * 2, 0);
|
||||
|
||||
appendBranch(c, thunkBranch(c, type), 4, value
|
||||
(c, ValueGeneral, constantSite(c, static_cast<int64_t>(0))),
|
||||
@ -6167,14 +6194,7 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
virtual Operand* register_(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);
|
||||
return local::register_(&c, number);
|
||||
}
|
||||
|
||||
Promise* machineIp() {
|
||||
|
@ -30,7 +30,7 @@ class Compiler {
|
||||
virtual intptr_t getThunk(BinaryOperation op, unsigned size,
|
||||
unsigned resultSize) = 0;
|
||||
virtual intptr_t getThunk(TernaryOperation op, unsigned size,
|
||||
unsigned resultSize) = 0;
|
||||
unsigned resultSize, bool* threadParameter) = 0;
|
||||
};
|
||||
|
||||
static const unsigned Aligned = 1 << 0;
|
||||
|
@ -1665,6 +1665,11 @@ interpret(Thread* t)
|
||||
case idiv: {
|
||||
int32_t b = popInt(t);
|
||||
int32_t a = popInt(t);
|
||||
|
||||
if (UNLIKELY(b == 0)) {
|
||||
exception = makeThrowable(t, Machine::ArithmeticExceptionType);
|
||||
goto throw_;
|
||||
}
|
||||
|
||||
pushInt(t, a / b);
|
||||
} goto loop;
|
||||
@ -1968,6 +1973,11 @@ interpret(Thread* t)
|
||||
int32_t b = popInt(t);
|
||||
int32_t a = popInt(t);
|
||||
|
||||
if (UNLIKELY(b == 0)) {
|
||||
exception = makeThrowable(t, Machine::ArithmeticExceptionType);
|
||||
goto throw_;
|
||||
}
|
||||
|
||||
pushInt(t, a % b);
|
||||
} goto loop;
|
||||
|
||||
@ -2187,6 +2197,11 @@ interpret(Thread* t)
|
||||
int64_t b = popLong(t);
|
||||
int64_t a = popLong(t);
|
||||
|
||||
if (UNLIKELY(b == 0)) {
|
||||
exception = makeThrowable(t, Machine::ArithmeticExceptionType);
|
||||
goto throw_;
|
||||
}
|
||||
|
||||
pushLong(t, a / b);
|
||||
} goto loop;
|
||||
|
||||
@ -2269,6 +2284,11 @@ interpret(Thread* t)
|
||||
int64_t b = popLong(t);
|
||||
int64_t a = popLong(t);
|
||||
|
||||
if (UNLIKELY(b == 0)) {
|
||||
exception = makeThrowable(t, Machine::ArithmeticExceptionType);
|
||||
goto throw_;
|
||||
}
|
||||
|
||||
pushLong(t, a % b);
|
||||
} goto loop;
|
||||
|
||||
|
@ -2035,8 +2035,13 @@ boot(Thread* t)
|
||||
(t, Machine::NullPointerExceptionType));
|
||||
|
||||
if (t->exception == 0) {
|
||||
setRoot(t, Machine::ArrayIndexOutOfBoundsException,
|
||||
makeThrowable(t, Machine::ArrayIndexOutOfBoundsExceptionType));
|
||||
setRoot(t, Machine::ArithmeticException,
|
||||
makeThrowable(t, Machine::ArithmeticExceptionType));
|
||||
|
||||
if (t->exception == 0) {
|
||||
setRoot(t, Machine::ArrayIndexOutOfBoundsException,
|
||||
makeThrowable(t, Machine::ArrayIndexOutOfBoundsExceptionType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1203,6 +1203,7 @@ class Machine {
|
||||
ShutdownHooks,
|
||||
ObjectsToFinalize,
|
||||
NullPointerException,
|
||||
ArithmeticException,
|
||||
ArrayIndexOutOfBoundsException,
|
||||
VirtualFileFinders,
|
||||
VirtualFiles
|
||||
|
@ -69,14 +69,17 @@ const int AltSegFaultSignal = InvalidSignal;
|
||||
const unsigned AltSegFaultSignalIndex = 3;
|
||||
const int PipeSignal = SIGPIPE;
|
||||
const unsigned PipeSignalIndex = 4;
|
||||
const int DivideByZeroSignal = SIGFPE;
|
||||
const unsigned DivideByZeroSignalIndex = 5;
|
||||
|
||||
const int signals[] = { VisitSignal,
|
||||
SegFaultSignal,
|
||||
InterruptSignal,
|
||||
AltSegFaultSignal,
|
||||
PipeSignal };
|
||||
PipeSignal,
|
||||
DivideByZeroSignal };
|
||||
|
||||
const unsigned SignalCount = 5;
|
||||
const unsigned SignalCount = 6;
|
||||
|
||||
class MySystem;
|
||||
MySystem* system;
|
||||
@ -530,6 +533,8 @@ class MySystem: public System {
|
||||
expect(this, system == 0);
|
||||
system = this;
|
||||
|
||||
memset(handlers, 0, sizeof(handlers));
|
||||
|
||||
registerHandler(&nullHandler, InterruptSignalIndex);
|
||||
registerHandler(&nullHandler, PipeSignalIndex);
|
||||
registerHandler(&nullHandler, VisitSignalIndex);
|
||||
@ -631,6 +636,10 @@ class MySystem: public System {
|
||||
return s;
|
||||
}
|
||||
|
||||
virtual Status handleDivideByZero(SignalHandler* handler) {
|
||||
return registerHandler(handler, DivideByZeroSignalIndex);
|
||||
}
|
||||
|
||||
virtual Status visit(System::Thread* st, System::Thread* sTarget,
|
||||
ThreadVisitor* visitor)
|
||||
{
|
||||
@ -847,12 +856,25 @@ handleSignal(int signal, siginfo_t* info, void* context)
|
||||
} break;
|
||||
|
||||
case SegFaultSignal:
|
||||
case AltSegFaultSignal: {
|
||||
if (signal == SegFaultSignal) {
|
||||
case AltSegFaultSignal:
|
||||
case DivideByZeroSignal: {
|
||||
switch (signal) {
|
||||
case SegFaultSignal:
|
||||
index = SegFaultSignalIndex;
|
||||
} else {
|
||||
break;
|
||||
|
||||
case AltSegFaultSignal:
|
||||
index = AltSegFaultSignalIndex;
|
||||
break;
|
||||
|
||||
case DivideByZeroSignal:
|
||||
index = DivideByZeroSignalIndex;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
bool jump = system->handlers[index]->handleSignal
|
||||
(&ip, &base, &stack, &thread);
|
||||
|
||||
|
@ -126,6 +126,7 @@ class System {
|
||||
virtual Status make(Monitor**) = 0;
|
||||
virtual Status make(Local**) = 0;
|
||||
virtual Status handleSegFault(SignalHandler* handler) = 0;
|
||||
virtual Status handleDivideByZero(SignalHandler* handler) = 0;
|
||||
virtual Status visit(Thread* thread, Thread* target,
|
||||
ThreadVisitor* visitor) = 0;
|
||||
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
|
||||
|
@ -205,6 +205,8 @@
|
||||
|
||||
(type nullPointerException java/lang/NullPointerException)
|
||||
|
||||
(type arithmeticException java/lang/ArithmeticException)
|
||||
|
||||
(type illegalStateException java/lang/IllegalStateException)
|
||||
|
||||
(type illegalArgumentException java/lang/IllegalArgumentException)
|
||||
|
@ -49,6 +49,11 @@ class MutexResource {
|
||||
HANDLE m;
|
||||
};
|
||||
|
||||
const unsigned SegFaultIndex = 0;
|
||||
const unsigned DivideByZeroIndex = 1;
|
||||
|
||||
const unsigned HandlerCount = 2;
|
||||
|
||||
class MySystem;
|
||||
MySystem* system;
|
||||
|
||||
@ -510,17 +515,57 @@ class MySystem: public System {
|
||||
};
|
||||
|
||||
MySystem(const char* crashDumpDirectory):
|
||||
segFaultHandler(0),
|
||||
oldSegFaultHandler(0),
|
||||
oldHandler(0),
|
||||
crashDumpDirectory(crashDumpDirectory)
|
||||
{
|
||||
expect(this, system == 0);
|
||||
system = this;
|
||||
|
||||
memset(handlers, 0, sizeof(handlers));
|
||||
|
||||
mutex = CreateMutex(0, false, 0);
|
||||
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) {
|
||||
return malloc(sizeInBytes);
|
||||
}
|
||||
@ -578,27 +623,11 @@ class MySystem: public System {
|
||||
}
|
||||
|
||||
virtual Status handleSegFault(SignalHandler* handler) {
|
||||
if (handler) {
|
||||
segFaultHandler = handler;
|
||||
return registerHandler(handler, SegFaultIndex);
|
||||
}
|
||||
|
||||
#ifdef ARCH_x86_32
|
||||
oldSegFaultHandler = SetUnhandledExceptionFilter(handleException);
|
||||
#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 handleDivideByZero(SignalHandler* handler) {
|
||||
return registerHandler(handler, DivideByZeroIndex);
|
||||
}
|
||||
|
||||
virtual Status visit(System::Thread* st UNUSED, System::Thread* sTarget,
|
||||
@ -795,8 +824,8 @@ class MySystem: public System {
|
||||
}
|
||||
|
||||
HANDLE mutex;
|
||||
System::SignalHandler* segFaultHandler;
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER oldSegFaultHandler;
|
||||
SignalHandler* handlers[HandlerCount];
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER oldHandler;
|
||||
const char* crashDumpDirectory;
|
||||
};
|
||||
|
||||
@ -867,7 +896,15 @@ dump(LPEXCEPTION_POINTERS e, const char* directory)
|
||||
LONG CALLBACK
|
||||
handleException(LPEXCEPTION_POINTERS e)
|
||||
{
|
||||
System::SignalHandler* handler = 0;
|
||||
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
|
||||
void* ip = reinterpret_cast<void*>(e->ContextRecord->Eip);
|
||||
void* base = reinterpret_cast<void*>(e->ContextRecord->Ebp);
|
||||
@ -880,8 +917,8 @@ handleException(LPEXCEPTION_POINTERS e)
|
||||
void* thread = reinterpret_cast<void*>(e->ContextRecord->Rbx);
|
||||
#endif
|
||||
|
||||
bool jump = system->segFaultHandler->handleSignal
|
||||
(&ip, &base, &stack, &thread);
|
||||
bool jump = handler->handleSignal(&ip, &base, &stack, &thread);
|
||||
|
||||
#ifdef ARCH_x86_32
|
||||
e->ContextRecord->Eip = reinterpret_cast<DWORD>(ip);
|
||||
e->ContextRecord->Ebp = reinterpret_cast<DWORD>(base);
|
||||
@ -897,10 +934,10 @@ handleException(LPEXCEPTION_POINTERS e)
|
||||
if (jump) {
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
}
|
||||
|
||||
if (system->crashDumpDirectory) {
|
||||
dump(e, system->crashDumpDirectory);
|
||||
}
|
||||
if (system->crashDumpDirectory) {
|
||||
dump(e, system->crashDumpDirectory);
|
||||
}
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
|
135
test/DivideByZero.java
Normal file
135
test/DivideByZero.java
Normal 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
1
vm.pro
@ -57,6 +57,7 @@
|
||||
-keep public class java.lang.ClassCastException
|
||||
-keep public class java.lang.ClassNotFoundException
|
||||
-keep public class java.lang.NullPointerException
|
||||
-keep public class java.lang.ArithmeticException
|
||||
-keep public class java.lang.InterruptedException
|
||||
-keep public class java.lang.StackOverflowError
|
||||
-keep public class java.lang.NoSuchFieldError
|
||||
|
Loading…
Reference in New Issue
Block a user