use of org.hotswap.agent.javassist.bytecode.BadBytecode in project HotswapAgent by HotswapProjects.
the class FieldInitLink method modifyClassConstructor.
private void modifyClassConstructor(ClassFile cf, Bytecode code, int stacksize, int localsize) throws CannotCompileException {
MethodInfo m = cf.getStaticInitializer();
if (m == null) {
code.add(Bytecode.RETURN);
code.setMaxStack(stacksize);
code.setMaxLocals(localsize);
m = new MethodInfo(cf.getConstPool(), "<clinit>", "()V");
m.setAccessFlags(AccessFlag.STATIC);
m.setCodeAttribute(code.toCodeAttribute());
cf.addMethod(m);
CtMember.Cache cache = hasMemberCache();
if (cache != null)
cache.addConstructor(new CtConstructor(m, this));
} else {
CodeAttribute codeAttr = m.getCodeAttribute();
if (codeAttr == null)
throw new CannotCompileException("empty <clinit>");
try {
CodeIterator it = codeAttr.iterator();
int pos = it.insertEx(code.get());
it.insert(code.getExceptionTable(), pos);
int maxstack = codeAttr.getMaxStack();
if (maxstack < stacksize)
codeAttr.setMaxStack(stacksize);
int maxlocals = codeAttr.getMaxLocals();
if (maxlocals < localsize)
codeAttr.setMaxLocals(localsize);
} catch (BadBytecode e) {
throw new CannotCompileException(e);
}
}
try {
m.rebuildStackMapIf6(classPool, cf);
} catch (BadBytecode e) {
throw new CannotCompileException(e);
}
}
use of org.hotswap.agent.javassist.bytecode.BadBytecode in project HotswapAgent by HotswapProjects.
the class Analyzer method analyzeNextEntry.
private void analyzeNextEntry(MethodInfo method, CodeIterator iter, IntQueue queue, Executor executor) throws BadBytecode {
int pos = queue.take();
iter.move(pos);
iter.next();
Frame frame = frames[pos].copy();
Subroutine subroutine = subroutines[pos];
try {
executor.execute(method, pos, iter, frame, subroutine);
} catch (RuntimeException e) {
throw new BadBytecode(e.getMessage() + "[pos = " + pos + "]", e);
}
int opcode = iter.byteAt(pos);
if (opcode == TABLESWITCH) {
mergeTableSwitch(queue, pos, iter, frame);
} else if (opcode == LOOKUPSWITCH) {
mergeLookupSwitch(queue, pos, iter, frame);
} else if (opcode == RET) {
mergeRet(queue, iter, pos, frame, subroutine);
} else if (Util.isJumpInstruction(opcode)) {
int target = Util.getJumpTarget(pos, iter);
if (Util.isJsr(opcode)) {
// Merge the state before the jsr into the next instruction
mergeJsr(queue, frames[pos], subroutines[target], pos, lookAhead(iter, pos));
} else if (!Util.isGoto(opcode)) {
merge(queue, frame, lookAhead(iter, pos));
}
merge(queue, frame, target);
} else if (opcode != ATHROW && !Util.isReturn(opcode)) {
// Can advance to next instruction
merge(queue, frame, lookAhead(iter, pos));
}
// Merge all exceptions that are reachable from this instruction.
// The redundancy is intentional, since the state must be based
// on the current instruction frame.
mergeExceptionHandlers(queue, method, pos, frame);
}
use of org.hotswap.agent.javassist.bytecode.BadBytecode in project HotswapAgent by HotswapProjects.
the class Executor method execute.
/**
* Execute the instruction, modeling the effects on the specified frame and subroutine.
* If a subroutine is passed, the access flags will be modified if this instruction accesses
* the local variable table.
*
* @param method the method containing the instruction
* @param pos the position of the instruction in the method
* @param iter the code iterator used to find the instruction
* @param frame the frame to modify to represent the result of the instruction
* @param subroutine the optional subroutine this instruction belongs to.
* @throws BadBytecode if the bytecode violates the jvm spec
*/
public void execute(MethodInfo method, int pos, CodeIterator iter, Frame frame, Subroutine subroutine) throws BadBytecode {
this.lastPos = pos;
int opcode = iter.byteAt(pos);
// Declared opcode in order
switch(opcode) {
case NOP:
break;
case ACONST_NULL:
frame.push(Type.UNINIT);
break;
case ICONST_M1:
case ICONST_0:
case ICONST_1:
case ICONST_2:
case ICONST_3:
case ICONST_4:
case ICONST_5:
frame.push(Type.INTEGER);
break;
case LCONST_0:
case LCONST_1:
frame.push(Type.LONG);
frame.push(Type.TOP);
break;
case FCONST_0:
case FCONST_1:
case FCONST_2:
frame.push(Type.FLOAT);
break;
case DCONST_0:
case DCONST_1:
frame.push(Type.DOUBLE);
frame.push(Type.TOP);
break;
case BIPUSH:
case SIPUSH:
frame.push(Type.INTEGER);
break;
case LDC:
evalLDC(iter.byteAt(pos + 1), frame);
break;
case LDC_W:
case LDC2_W:
evalLDC(iter.u16bitAt(pos + 1), frame);
break;
case ILOAD:
evalLoad(Type.INTEGER, iter.byteAt(pos + 1), frame, subroutine);
break;
case LLOAD:
evalLoad(Type.LONG, iter.byteAt(pos + 1), frame, subroutine);
break;
case FLOAD:
evalLoad(Type.FLOAT, iter.byteAt(pos + 1), frame, subroutine);
break;
case DLOAD:
evalLoad(Type.DOUBLE, iter.byteAt(pos + 1), frame, subroutine);
break;
case ALOAD:
evalLoad(Type.OBJECT, iter.byteAt(pos + 1), frame, subroutine);
break;
case ILOAD_0:
case ILOAD_1:
case ILOAD_2:
case ILOAD_3:
evalLoad(Type.INTEGER, opcode - ILOAD_0, frame, subroutine);
break;
case LLOAD_0:
case LLOAD_1:
case LLOAD_2:
case LLOAD_3:
evalLoad(Type.LONG, opcode - LLOAD_0, frame, subroutine);
break;
case FLOAD_0:
case FLOAD_1:
case FLOAD_2:
case FLOAD_3:
evalLoad(Type.FLOAT, opcode - FLOAD_0, frame, subroutine);
break;
case DLOAD_0:
case DLOAD_1:
case DLOAD_2:
case DLOAD_3:
evalLoad(Type.DOUBLE, opcode - DLOAD_0, frame, subroutine);
break;
case ALOAD_0:
case ALOAD_1:
case ALOAD_2:
case ALOAD_3:
evalLoad(Type.OBJECT, opcode - ALOAD_0, frame, subroutine);
break;
case IALOAD:
evalArrayLoad(Type.INTEGER, frame);
break;
case LALOAD:
evalArrayLoad(Type.LONG, frame);
break;
case FALOAD:
evalArrayLoad(Type.FLOAT, frame);
break;
case DALOAD:
evalArrayLoad(Type.DOUBLE, frame);
break;
case AALOAD:
evalArrayLoad(Type.OBJECT, frame);
break;
case BALOAD:
case CALOAD:
case SALOAD:
evalArrayLoad(Type.INTEGER, frame);
break;
case ISTORE:
evalStore(Type.INTEGER, iter.byteAt(pos + 1), frame, subroutine);
break;
case LSTORE:
evalStore(Type.LONG, iter.byteAt(pos + 1), frame, subroutine);
break;
case FSTORE:
evalStore(Type.FLOAT, iter.byteAt(pos + 1), frame, subroutine);
break;
case DSTORE:
evalStore(Type.DOUBLE, iter.byteAt(pos + 1), frame, subroutine);
break;
case ASTORE:
evalStore(Type.OBJECT, iter.byteAt(pos + 1), frame, subroutine);
break;
case ISTORE_0:
case ISTORE_1:
case ISTORE_2:
case ISTORE_3:
evalStore(Type.INTEGER, opcode - ISTORE_0, frame, subroutine);
break;
case LSTORE_0:
case LSTORE_1:
case LSTORE_2:
case LSTORE_3:
evalStore(Type.LONG, opcode - LSTORE_0, frame, subroutine);
break;
case FSTORE_0:
case FSTORE_1:
case FSTORE_2:
case FSTORE_3:
evalStore(Type.FLOAT, opcode - FSTORE_0, frame, subroutine);
break;
case DSTORE_0:
case DSTORE_1:
case DSTORE_2:
case DSTORE_3:
evalStore(Type.DOUBLE, opcode - DSTORE_0, frame, subroutine);
break;
case ASTORE_0:
case ASTORE_1:
case ASTORE_2:
case ASTORE_3:
evalStore(Type.OBJECT, opcode - ASTORE_0, frame, subroutine);
break;
case IASTORE:
evalArrayStore(Type.INTEGER, frame);
break;
case LASTORE:
evalArrayStore(Type.LONG, frame);
break;
case FASTORE:
evalArrayStore(Type.FLOAT, frame);
break;
case DASTORE:
evalArrayStore(Type.DOUBLE, frame);
break;
case AASTORE:
evalArrayStore(Type.OBJECT, frame);
break;
case BASTORE:
case CASTORE:
case SASTORE:
evalArrayStore(Type.INTEGER, frame);
break;
case POP:
if (frame.pop() == Type.TOP)
throw new BadBytecode("POP can not be used with a category 2 value, pos = " + pos);
break;
case POP2:
frame.pop();
frame.pop();
break;
case DUP:
{
Type type = frame.peek();
if (type == Type.TOP)
throw new BadBytecode("DUP can not be used with a category 2 value, pos = " + pos);
frame.push(frame.peek());
break;
}
case DUP_X1:
case DUP_X2:
{
Type type = frame.peek();
if (type == Type.TOP)
throw new BadBytecode("DUP can not be used with a category 2 value, pos = " + pos);
int end = frame.getTopIndex();
int insert = end - (opcode - DUP_X1) - 1;
frame.push(type);
while (end > insert) {
frame.setStack(end, frame.getStack(end - 1));
end--;
}
frame.setStack(insert, type);
break;
}
case DUP2:
frame.push(frame.getStack(frame.getTopIndex() - 1));
frame.push(frame.getStack(frame.getTopIndex() - 1));
break;
case DUP2_X1:
case DUP2_X2:
{
int end = frame.getTopIndex();
int insert = end - (opcode - DUP2_X1) - 1;
Type type1 = frame.getStack(frame.getTopIndex() - 1);
Type type2 = frame.peek();
frame.push(type1);
frame.push(type2);
while (end > insert) {
frame.setStack(end, frame.getStack(end - 2));
end--;
}
frame.setStack(insert, type2);
frame.setStack(insert - 1, type1);
break;
}
case SWAP:
{
Type type1 = frame.pop();
Type type2 = frame.pop();
if (type1.getSize() == 2 || type2.getSize() == 2)
throw new BadBytecode("Swap can not be used with category 2 values, pos = " + pos);
frame.push(type1);
frame.push(type2);
break;
}
// Math
case IADD:
evalBinaryMath(Type.INTEGER, frame);
break;
case LADD:
evalBinaryMath(Type.LONG, frame);
break;
case FADD:
evalBinaryMath(Type.FLOAT, frame);
break;
case DADD:
evalBinaryMath(Type.DOUBLE, frame);
break;
case ISUB:
evalBinaryMath(Type.INTEGER, frame);
break;
case LSUB:
evalBinaryMath(Type.LONG, frame);
break;
case FSUB:
evalBinaryMath(Type.FLOAT, frame);
break;
case DSUB:
evalBinaryMath(Type.DOUBLE, frame);
break;
case IMUL:
evalBinaryMath(Type.INTEGER, frame);
break;
case LMUL:
evalBinaryMath(Type.LONG, frame);
break;
case FMUL:
evalBinaryMath(Type.FLOAT, frame);
break;
case DMUL:
evalBinaryMath(Type.DOUBLE, frame);
break;
case IDIV:
evalBinaryMath(Type.INTEGER, frame);
break;
case LDIV:
evalBinaryMath(Type.LONG, frame);
break;
case FDIV:
evalBinaryMath(Type.FLOAT, frame);
break;
case DDIV:
evalBinaryMath(Type.DOUBLE, frame);
break;
case IREM:
evalBinaryMath(Type.INTEGER, frame);
break;
case LREM:
evalBinaryMath(Type.LONG, frame);
break;
case FREM:
evalBinaryMath(Type.FLOAT, frame);
break;
case DREM:
evalBinaryMath(Type.DOUBLE, frame);
break;
// Unary
case INEG:
verifyAssignable(Type.INTEGER, simplePeek(frame));
break;
case LNEG:
verifyAssignable(Type.LONG, simplePeek(frame));
break;
case FNEG:
verifyAssignable(Type.FLOAT, simplePeek(frame));
break;
case DNEG:
verifyAssignable(Type.DOUBLE, simplePeek(frame));
break;
// Shifts
case ISHL:
evalShift(Type.INTEGER, frame);
break;
case LSHL:
evalShift(Type.LONG, frame);
break;
case ISHR:
evalShift(Type.INTEGER, frame);
break;
case LSHR:
evalShift(Type.LONG, frame);
break;
case IUSHR:
evalShift(Type.INTEGER, frame);
break;
case LUSHR:
evalShift(Type.LONG, frame);
break;
// Bitwise Math
case IAND:
evalBinaryMath(Type.INTEGER, frame);
break;
case LAND:
evalBinaryMath(Type.LONG, frame);
break;
case IOR:
evalBinaryMath(Type.INTEGER, frame);
break;
case LOR:
evalBinaryMath(Type.LONG, frame);
break;
case IXOR:
evalBinaryMath(Type.INTEGER, frame);
break;
case LXOR:
evalBinaryMath(Type.LONG, frame);
break;
case IINC:
{
int index = iter.byteAt(pos + 1);
verifyAssignable(Type.INTEGER, frame.getLocal(index));
access(index, Type.INTEGER, subroutine);
break;
}
// Conversion
case I2L:
verifyAssignable(Type.INTEGER, simplePop(frame));
simplePush(Type.LONG, frame);
break;
case I2F:
verifyAssignable(Type.INTEGER, simplePop(frame));
simplePush(Type.FLOAT, frame);
break;
case I2D:
verifyAssignable(Type.INTEGER, simplePop(frame));
simplePush(Type.DOUBLE, frame);
break;
case L2I:
verifyAssignable(Type.LONG, simplePop(frame));
simplePush(Type.INTEGER, frame);
break;
case L2F:
verifyAssignable(Type.LONG, simplePop(frame));
simplePush(Type.FLOAT, frame);
break;
case L2D:
verifyAssignable(Type.LONG, simplePop(frame));
simplePush(Type.DOUBLE, frame);
break;
case F2I:
verifyAssignable(Type.FLOAT, simplePop(frame));
simplePush(Type.INTEGER, frame);
break;
case F2L:
verifyAssignable(Type.FLOAT, simplePop(frame));
simplePush(Type.LONG, frame);
break;
case F2D:
verifyAssignable(Type.FLOAT, simplePop(frame));
simplePush(Type.DOUBLE, frame);
break;
case D2I:
verifyAssignable(Type.DOUBLE, simplePop(frame));
simplePush(Type.INTEGER, frame);
break;
case D2L:
verifyAssignable(Type.DOUBLE, simplePop(frame));
simplePush(Type.LONG, frame);
break;
case D2F:
verifyAssignable(Type.DOUBLE, simplePop(frame));
simplePush(Type.FLOAT, frame);
break;
case I2B:
case I2C:
case I2S:
verifyAssignable(Type.INTEGER, frame.peek());
break;
case LCMP:
verifyAssignable(Type.LONG, simplePop(frame));
verifyAssignable(Type.LONG, simplePop(frame));
frame.push(Type.INTEGER);
break;
case FCMPL:
case FCMPG:
verifyAssignable(Type.FLOAT, simplePop(frame));
verifyAssignable(Type.FLOAT, simplePop(frame));
frame.push(Type.INTEGER);
break;
case DCMPL:
case DCMPG:
verifyAssignable(Type.DOUBLE, simplePop(frame));
verifyAssignable(Type.DOUBLE, simplePop(frame));
frame.push(Type.INTEGER);
break;
// Control flow
case IFEQ:
case IFNE:
case IFLT:
case IFGE:
case IFGT:
case IFLE:
verifyAssignable(Type.INTEGER, simplePop(frame));
break;
case IF_ICMPEQ:
case IF_ICMPNE:
case IF_ICMPLT:
case IF_ICMPGE:
case IF_ICMPGT:
case IF_ICMPLE:
verifyAssignable(Type.INTEGER, simplePop(frame));
verifyAssignable(Type.INTEGER, simplePop(frame));
break;
case IF_ACMPEQ:
case IF_ACMPNE:
verifyAssignable(Type.OBJECT, simplePop(frame));
verifyAssignable(Type.OBJECT, simplePop(frame));
break;
case GOTO:
break;
case JSR:
frame.push(Type.RETURN_ADDRESS);
break;
case RET:
verifyAssignable(Type.RETURN_ADDRESS, frame.getLocal(iter.byteAt(pos + 1)));
break;
case TABLESWITCH:
case LOOKUPSWITCH:
case IRETURN:
verifyAssignable(Type.INTEGER, simplePop(frame));
break;
case LRETURN:
verifyAssignable(Type.LONG, simplePop(frame));
break;
case FRETURN:
verifyAssignable(Type.FLOAT, simplePop(frame));
break;
case DRETURN:
verifyAssignable(Type.DOUBLE, simplePop(frame));
break;
case ARETURN:
try {
CtClass returnType = Descriptor.getReturnType(method.getDescriptor(), classPool);
verifyAssignable(Type.get(returnType), simplePop(frame));
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
break;
case RETURN:
break;
case GETSTATIC:
evalGetField(opcode, iter.u16bitAt(pos + 1), frame);
break;
case PUTSTATIC:
evalPutField(opcode, iter.u16bitAt(pos + 1), frame);
break;
case GETFIELD:
evalGetField(opcode, iter.u16bitAt(pos + 1), frame);
break;
case PUTFIELD:
evalPutField(opcode, iter.u16bitAt(pos + 1), frame);
break;
case INVOKEVIRTUAL:
case INVOKESPECIAL:
case INVOKESTATIC:
evalInvokeMethod(opcode, iter.u16bitAt(pos + 1), frame);
break;
case INVOKEINTERFACE:
evalInvokeIntfMethod(opcode, iter.u16bitAt(pos + 1), frame);
break;
case INVOKEDYNAMIC:
evalInvokeDynamic(opcode, iter.u16bitAt(pos + 1), frame);
break;
case NEW:
frame.push(resolveClassInfo(constPool.getClassInfo(iter.u16bitAt(pos + 1))));
break;
case NEWARRAY:
evalNewArray(pos, iter, frame);
break;
case ANEWARRAY:
evalNewObjectArray(pos, iter, frame);
break;
case ARRAYLENGTH:
{
Type array = simplePop(frame);
if (!array.isArray() && array != Type.UNINIT)
throw new BadBytecode("Array length passed a non-array [pos = " + pos + "]: " + array);
frame.push(Type.INTEGER);
break;
}
case ATHROW:
verifyAssignable(THROWABLE_TYPE, simplePop(frame));
break;
case CHECKCAST:
verifyAssignable(Type.OBJECT, simplePop(frame));
frame.push(typeFromDesc(constPool.getClassInfoByDescriptor(iter.u16bitAt(pos + 1))));
break;
case INSTANCEOF:
verifyAssignable(Type.OBJECT, simplePop(frame));
frame.push(Type.INTEGER);
break;
case MONITORENTER:
case MONITOREXIT:
verifyAssignable(Type.OBJECT, simplePop(frame));
break;
case WIDE:
evalWide(pos, iter, frame, subroutine);
break;
case MULTIANEWARRAY:
evalNewObjectArray(pos, iter, frame);
break;
case IFNULL:
case IFNONNULL:
verifyAssignable(Type.OBJECT, simplePop(frame));
break;
case GOTO_W:
break;
case JSR_W:
frame.push(Type.RETURN_ADDRESS);
break;
}
}
use of org.hotswap.agent.javassist.bytecode.BadBytecode in project HotswapAgent by HotswapProjects.
the class Executor method evalArrayLoad.
private void evalArrayLoad(Type expectedComponent, Frame frame) throws BadBytecode {
Type index = frame.pop();
Type array = frame.pop();
// TODO - we might need to be more inteligent about this
if (array == Type.UNINIT) {
verifyAssignable(Type.INTEGER, index);
if (expectedComponent == Type.OBJECT) {
simplePush(Type.UNINIT, frame);
} else {
simplePush(expectedComponent, frame);
}
return;
}
Type component = array.getComponent();
if (component == null)
throw new BadBytecode("Not an array! [pos = " + lastPos + "]: " + component);
component = zeroExtend(component);
verifyAssignable(expectedComponent, component);
verifyAssignable(Type.INTEGER, index);
simplePush(component, frame);
}
use of org.hotswap.agent.javassist.bytecode.BadBytecode in project HotswapAgent by HotswapProjects.
the class Executor method evalArrayStore.
private void evalArrayStore(Type expectedComponent, Frame frame) throws BadBytecode {
Type value = simplePop(frame);
Type index = frame.pop();
Type array = frame.pop();
if (array == Type.UNINIT) {
verifyAssignable(Type.INTEGER, index);
return;
}
Type component = array.getComponent();
if (component == null)
throw new BadBytecode("Not an array! [pos = " + lastPos + "]: " + component);
component = zeroExtend(component);
verifyAssignable(expectedComponent, component);
verifyAssignable(Type.INTEGER, index);
// // but will throw arraystoreexception
if (expectedComponent == Type.OBJECT) {
verifyAssignable(expectedComponent, value);
} else {
verifyAssignable(component, value);
}
}
Aggregations