mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +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) {
|
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(÷ByZeroHandler)));
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -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() {
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1203,6 +1203,7 @@ class Machine {
|
|||||||
ShutdownHooks,
|
ShutdownHooks,
|
||||||
ObjectsToFinalize,
|
ObjectsToFinalize,
|
||||||
NullPointerException,
|
NullPointerException,
|
||||||
|
ArithmeticException,
|
||||||
ArrayIndexOutOfBoundsException,
|
ArrayIndexOutOfBoundsException,
|
||||||
VirtualFileFinders,
|
VirtualFileFinders,
|
||||||
VirtualFiles
|
VirtualFiles
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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
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.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
|
||||||
|
Loading…
Reference in New Issue
Block a user