package janala.instrument; import janala.config.Config; import janala.logger.ClassNames; import janala.logger.ObjectInfo; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Label; import java.util.LinkedList; public class SnoopInstructionMethodAdapter extends MethodVisitor implements Opcodes { boolean isInit; boolean isSuperInitCalled; LinkedList<TryCatchBlock> tryCatchBlocks; boolean calledNew = false; private final Coverage coverage; private final GlobalStateForInstrumentation instrumentationState; private final ClassNames classNames; public SnoopInstructionMethodAdapter(MethodVisitor mv, boolean isInit, Coverage coverage, GlobalStateForInstrumentation instrumentationState, ClassNames classNames) { super(ASM5, mv); this.isInit = isInit; this.isSuperInitCalled = false; tryCatchBlocks = new LinkedList<TryCatchBlock>(); this.coverage = coverage; this.instrumentationState = instrumentationState; this.classNames = classNames; } @Override public void visitCode() { instrumentationState.incMid(); coverage.setCidmidToName(instrumentationState.getMid()); mv.visitCode(); } /** Push a value onto the stack. */ private static void addBipushInsn(MethodVisitor mv, int val) { Utils.addBipushInsn(mv, val); } /** Add a GETVALUE call to synchronize the top stack with that of the symbolic stack. */ private void addValueReadInsn(MethodVisitor mv, String desc, String methodNamePrefix) { Utils.addValueReadInsn(mv, desc, methodNamePrefix); } /** Add a special probe instruction. */ private void addSpecialInsn(MethodVisitor mv, int val) { Utils.addSpecialInsn(mv, val); } private void addInsn(MethodVisitor mv, String insn, int opcode) { addBipushInsn(mv, instrumentationState.incAndGetId()); addBipushInsn(mv, instrumentationState.getMid()); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, insn, "(II)V", false); mv.visitInsn(opcode); } /** Add var insn and its instrumentation code. */ private void addVarInsn(MethodVisitor mv, int var, String insn, int opcode) { addBipushInsn(mv, instrumentationState.incAndGetId()); addBipushInsn(mv, instrumentationState.getMid()); addBipushInsn(mv, var); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, insn, "(III)V", false); mv.visitVarInsn(opcode, var); } private void addTypeInsn(MethodVisitor mv, String type, int opcode, String name) { addBipushInsn(mv, instrumentationState.incAndGetId()); addBipushInsn(mv, instrumentationState.getMid()); mv.visitLdcInsn(type); mv.visitMethodInsn( INVOKESTATIC, Config.instance.analysisClass, name, "(IILjava/lang/String;)V", false); mv.visitTypeInsn(opcode, type); } @Override public void visitLineNumber(int lineNumber, Label label) { mv.visitLineNumber(lineNumber, label); } @Override public void visitInsn(int opcode) { switch (opcode) { case NOP: addInsn(mv, "NOP", opcode); break; case ACONST_NULL: addInsn(mv, "ACONST_NULL", opcode); break; case ICONST_M1: addInsn(mv, "ICONST_M1", opcode); break; case ICONST_0: addInsn(mv, "ICONST_0", opcode); break; case ICONST_1: addInsn(mv, "ICONST_1", opcode); break; case ICONST_2: addInsn(mv, "ICONST_2", opcode); break; case ICONST_3: addInsn(mv, "ICONST_3", opcode); break; case ICONST_4: addInsn(mv, "ICONST_4", opcode); break; case ICONST_5: addInsn(mv, "ICONST_5", opcode); break; case LCONST_0: addInsn(mv, "LCONST_0", opcode); break; case LCONST_1: addInsn(mv, "LCONST_1", opcode); break; case FCONST_0: addInsn(mv, "FCONST_0", opcode); break; case FCONST_1: addInsn(mv, "FCONST_1", opcode); break; case FCONST_2: addInsn(mv, "FCONST_2", opcode); break; case DCONST_0: addInsn(mv, "DCONST_0", opcode); break; case DCONST_1: addInsn(mv, "DCONST_1", opcode); break; case IALOAD: addInsn(mv, "IALOAD", opcode); addSpecialInsn(mv, 0); // for non-exceptional path addValueReadInsn(mv, "I", "GETVALUE_"); break; case LALOAD: addInsn(mv, "LALOAD", opcode); addSpecialInsn(mv, 0); // for non-exceptional path addValueReadInsn(mv, "J", "GETVALUE_"); break; case FALOAD: addInsn(mv, "FALOAD", opcode); addSpecialInsn(mv, 0); // for non-exceptional path addValueReadInsn(mv, "F", "GETVALUE_"); break; case DALOAD: addInsn(mv, "DALOAD", opcode); addSpecialInsn(mv, 0); // for non-exceptional path addValueReadInsn(mv, "D", "GETVALUE_"); break; case AALOAD: addInsn(mv, "AALOAD", opcode); addSpecialInsn(mv, 0); // for non-exceptional path addValueReadInsn(mv, "Ljava/lang/Object;", "GETVALUE_"); break; case BALOAD: addInsn(mv, "BALOAD", opcode); addSpecialInsn(mv, 0); // for non-exceptional path addValueReadInsn(mv, "B", "GETVALUE_"); break; case CALOAD: addInsn(mv, "CALOAD", opcode); addSpecialInsn(mv, 0); // for non-exceptional path addValueReadInsn(mv, "C", "GETVALUE_"); break; case SALOAD: addInsn(mv, "SALOAD", opcode); addSpecialInsn(mv, 0); // for non-exceptional path addValueReadInsn(mv, "S", "GETVALUE_"); break; case IASTORE: addInsn(mv, "IASTORE", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; case LASTORE: addInsn(mv, "LASTORE", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; case FASTORE: addInsn(mv, "FASTORE", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; case DASTORE: addInsn(mv, "DASTORE", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; case AASTORE: addInsn(mv, "AASTORE", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; case BASTORE: addInsn(mv, "BASTORE", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; case CASTORE: addInsn(mv, "CASTORE", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; case SASTORE: addInsn(mv, "SASTORE", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; case POP: addInsn(mv, "POP", opcode); break; case POP2: addInsn(mv, "POP2", opcode); break; case DUP: addInsn(mv, "DUP", opcode); break; case DUP_X1: addInsn(mv, "DUP_X1", opcode); break; case DUP_X2: addInsn(mv, "DUP_X2", opcode); break; case DUP2: addInsn(mv, "DUP2", opcode); break; case DUP2_X1: addInsn(mv, "DUP2_X1", opcode); break; case DUP2_X2: addInsn(mv, "DUP2_X2", opcode); break; case SWAP: addInsn(mv, "SWAP", opcode); break; case IADD: addInsn(mv, "IADD", opcode); break; case LADD: addInsn(mv, "LADD", opcode); break; case FADD: addInsn(mv, "FADD", opcode); break; case DADD: addInsn(mv, "DADD", opcode); break; case ISUB: addInsn(mv, "ISUB", opcode); break; case LSUB: addInsn(mv, "LSUB", opcode); break; case FSUB: addInsn(mv, "FSUB", opcode); break; case DSUB: addInsn(mv, "DSUB", opcode); break; case IMUL: addInsn(mv, "IMUL", opcode); break; case LMUL: addInsn(mv, "LMUL", opcode); break; case FMUL: addInsn(mv, "FMUL", opcode); break; case DMUL: addInsn(mv, "DMUL", opcode); break; case IDIV: addInsn(mv, "IDIV", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; case LDIV: addInsn(mv, "LDIV", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; case FDIV: addInsn(mv, "FDIV", opcode); break; case DDIV: addInsn(mv, "DDIV", opcode); break; case IREM: addInsn(mv, "IREM", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; case LREM: addInsn(mv, "LREM", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; case FREM: addInsn(mv, "FREM", opcode); break; case DREM: addInsn(mv, "DREM", opcode); break; case INEG: addInsn(mv, "INEG", opcode); break; case LNEG: addInsn(mv, "LNEG", opcode); break; case FNEG: addInsn(mv, "FNEG", opcode); break; case DNEG: addInsn(mv, "DNEG", opcode); break; case ISHL: addInsn(mv, "ISHL", opcode); break; case LSHL: addInsn(mv, "LSHL", opcode); break; case ISHR: addInsn(mv, "ISHR", opcode); break; case LSHR: addInsn(mv, "LSHR", opcode); break; case IUSHR: addInsn(mv, "IUSHR", opcode); break; case LUSHR: addInsn(mv, "LUSHR", opcode); break; case IAND: addInsn(mv, "IAND", opcode); break; case LAND: addInsn(mv, "LAND", opcode); break; case IOR: addInsn(mv, "IOR", opcode); break; case LOR: addInsn(mv, "LOR", opcode); break; case IXOR: addInsn(mv, "IXOR", opcode); break; case LXOR: addInsn(mv, "LXOR", opcode); break; case I2L: addInsn(mv, "I2L", opcode); break; case I2F: addInsn(mv, "I2F", opcode); break; case I2D: addInsn(mv, "I2D", opcode); break; case L2I: addInsn(mv, "L2I", opcode); break; case L2F: addInsn(mv, "L2F", opcode); break; case L2D: addInsn(mv, "L2D", opcode); break; case F2I: addInsn(mv, "F2I", opcode); break; case F2L: addInsn(mv, "F2L", opcode); break; case F2D: addInsn(mv, "F2D", opcode); break; case D2I: addInsn(mv, "D2I", opcode); break; case D2L: addInsn(mv, "D2L", opcode); break; case D2F: addInsn(mv, "D2F", opcode); break; case I2B: addInsn(mv, "I2B", opcode); break; case I2C: addInsn(mv, "I2C", opcode); break; case I2S: addInsn(mv, "I2S", opcode); break; case LCMP: addInsn(mv, "LCMP", opcode); break; case FCMPL: addInsn(mv, "FCMPL", opcode); break; case FCMPG: addInsn(mv, "FCMPG", opcode); break; case DCMPL: addInsn(mv, "DCMPL", opcode); break; case DCMPG: addInsn(mv, "DCMPG", opcode); break; case IRETURN: addInsn(mv, "IRETURN", opcode); break; case LRETURN: addInsn(mv, "LRETURN", opcode); break; case FRETURN: addInsn(mv, "FRETURN", opcode); break; case DRETURN: addInsn(mv, "DRETURN", opcode); break; case ARETURN: addInsn(mv, "ARETURN", opcode); break; case RETURN: addInsn(mv, "RETURN", opcode); break; case ARRAYLENGTH: addInsn(mv, "ARRAYLENGTH", opcode); addSpecialInsn(mv, 0); // for non-exceptional path addValueReadInsn(mv, "I", "GETVALUE_"); break; case ATHROW: addInsn(mv, "ATHROW", opcode); break; case MONITORENTER: addInsn(mv, "MONITORENTER", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; case MONITOREXIT: addInsn(mv, "MONITOREXIT", opcode); addSpecialInsn(mv, 0); // for non-exceptional path break; default: throw new RuntimeException("Unknown instruction opcode " + opcode); } } @Override public void visitVarInsn(int opcode, int var) { switch (opcode) { case ILOAD: addVarInsn(mv, var, "ILOAD", opcode); addValueReadInsn(mv, "I", "GETVALUE_"); break; case LLOAD: addVarInsn(mv, var, "LLOAD", opcode); addValueReadInsn(mv, "J", "GETVALUE_"); break; case FLOAD: addVarInsn(mv, var, "FLOAD", opcode); addValueReadInsn(mv, "F", "GETVALUE_"); break; case DLOAD: addVarInsn(mv, var, "DLOAD", opcode); addValueReadInsn(mv, "D", "GETVALUE_"); break; case ALOAD: addVarInsn(mv, var, "ALOAD", opcode); if (!(var == 0 && isInit && !isSuperInitCalled)) { addValueReadInsn(mv, "Ljava/lang/Object;", "GETVALUE_"); } break; case ISTORE: addVarInsn(mv, var, "ISTORE", opcode); break; case LSTORE: addVarInsn(mv, var, "LSTORE", opcode); break; case FSTORE: addVarInsn(mv, var, "FSTORE", opcode); break; case DSTORE: addVarInsn(mv, var, "DSTORE", opcode); break; case ASTORE: addVarInsn(mv, var, "ASTORE", opcode); break; case RET: addVarInsn(mv, var, "RET", opcode); break; default: throw new RuntimeException("Unknown var insn"); } } @Override public void visitIntInsn(int opcode, int operand) { addBipushInsn(mv, instrumentationState.incAndGetId()); addBipushInsn(mv, instrumentationState.getMid()); switch (opcode) { case BIPUSH: addBipushInsn(mv, operand); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "BIPUSH", "(III)V", false); break; case SIPUSH: addBipushInsn(mv, operand); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "SIPUSH", "(III)V", false); break; case NEWARRAY: mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "NEWARRAY", "(II)V", false); mv.visitIntInsn(opcode, operand); addSpecialInsn(mv, 0); // for non-exceptional path return; default: throw new RuntimeException("Unknown int instruction opcode " + opcode); } mv.visitIntInsn(opcode, operand); } @Override public void visitTypeInsn(int opcode, String type) { switch (opcode) { case NEW: addBipushInsn(mv, instrumentationState.incAndGetId()); addBipushInsn(mv, instrumentationState.getMid()); mv.visitLdcInsn(type); int cIdx = classNames.get(type); addBipushInsn(mv, cIdx); mv.visitMethodInsn( INVOKESTATIC, Config.instance.analysisClass, "NEW", "(IILjava/lang/String;I)V", false); mv.visitTypeInsn(opcode, type); addSpecialInsn(mv, 0); // for non-exceptional path calledNew = true; break; case ANEWARRAY: addTypeInsn(mv, type, opcode, "ANEWARRAY"); addSpecialInsn(mv, 0); // for non-exceptional path break; case CHECKCAST: addTypeInsn(mv, type, opcode, "CHECKCAST"); addSpecialInsn(mv, 0); // for non-exceptional path break; case INSTANCEOF: addTypeInsn(mv, type, opcode, "INSTANCEOF"); addSpecialInsn(mv, 0); // for non-exceptional path addValueReadInsn(mv, "I", "GETVALUE_"); break; default: throw new RuntimeException("Unknown type instruction opcode " + opcode); } } @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { addBipushInsn(mv, instrumentationState.incAndGetId()); addBipushInsn(mv, instrumentationState.getMid()); int cIdx = classNames.get(owner); addBipushInsn(mv, cIdx); ObjectInfo tmp = classNames.get(cIdx); switch (opcode) { case GETSTATIC: int fIdx = tmp.getIdx(name, true); addBipushInsn(mv, fIdx); mv.visitLdcInsn(desc); mv.visitMethodInsn( INVOKESTATIC, Config.instance.analysisClass, "GETSTATIC", "(IIIILjava/lang/String;)V", false); mv.visitFieldInsn(opcode, owner, name, desc); addSpecialInsn(mv, 0); // for non-exceptional path addValueReadInsn(mv, desc, "GETVALUE_"); break; case PUTSTATIC: fIdx = tmp.getIdx(name, true); addBipushInsn(mv, fIdx); mv.visitLdcInsn(desc); mv.visitMethodInsn( INVOKESTATIC, Config.instance.analysisClass, "PUTSTATIC", "(IIIILjava/lang/String;)V", false); mv.visitFieldInsn(opcode, owner, name, desc); addSpecialInsn(mv, 0); // for non-exceptional path break; case GETFIELD: fIdx = tmp.getIdx(name, false); addBipushInsn(mv, fIdx); mv.visitLdcInsn(desc); mv.visitMethodInsn( INVOKESTATIC, Config.instance.analysisClass, "GETFIELD", "(IIIILjava/lang/String;)V", false); mv.visitFieldInsn(opcode, owner, name, desc); addSpecialInsn(mv, 0); // for non-exceptional path addValueReadInsn(mv, desc, "GETVALUE_"); break; case PUTFIELD: fIdx = tmp.getIdx(name, false); addBipushInsn(mv, fIdx); mv.visitLdcInsn(desc); mv.visitMethodInsn( INVOKESTATIC, Config.instance.analysisClass, "PUTFIELD", "(IIIILjava/lang/String;)V", false); mv.visitFieldInsn(opcode, owner, name, desc); addSpecialInsn(mv, 0); // for non-exceptional path break; default: throw new RuntimeException("Unknown field access opcode " + opcode); } } private String getMethodName(int opcode) { switch (opcode) { case INVOKESPECIAL: return "INVOKESPECIAL"; case INVOKESTATIC: return "INVOKESTATIC"; case INVOKEINTERFACE: return "INVOKEINTERFACE"; case INVOKEVIRTUAL: return "INVOKEVIRTUAL"; default: throw new RuntimeException("Unknown opcode for method"); } } private void addMethodWithTryCatch(int opcode, String owner, String name, String desc, boolean itf) { addBipushInsn(mv, instrumentationState.incAndGetId()); addBipushInsn(mv, instrumentationState.getMid()); mv.visitLdcInsn(owner); mv.visitLdcInsn(name); mv.visitLdcInsn(desc); mv.visitMethodInsn( INVOKESTATIC, Config.instance.analysisClass, getMethodName(opcode), "(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", false); // Wrap the method call in a try-catch block Label begin = new Label(); Label handler = new Label(); Label end = new Label(); tryCatchBlocks.addFirst(new TryCatchBlock(begin, handler, handler, null)); mv.visitLabel(begin); mv.visitMethodInsn(opcode, owner, name, desc, itf); mv.visitJumpInsn(GOTO, end); mv.visitLabel(handler); mv.visitMethodInsn( INVOKESTATIC, Config.instance.analysisClass, "INVOKEMETHOD_EXCEPTION", "()V", false); mv.visitInsn(ATHROW); mv.visitLabel(end); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "INVOKEMETHOD_END", "()V", false); addValueReadInsn(mv, desc, "GETVALUE_"); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { if (opcode == INVOKESPECIAL && name.equals("<init>")) { if (isInit) { // This code is already inside an init method. // // Constructor calls to <init> method of the super class. If this is the // case, there is no need to wrap the method call in try catch block as // it uses uninitialized this object. isSuperInitCalled = true; mv.visitMethodInsn(opcode, owner, name, desc, itf); if (calledNew) { calledNew = false; } } else { addMethodWithTryCatch(opcode, owner, name, desc, itf); if (calledNew) { calledNew = false; addValueReadInsn(mv, "Ljava/lang/Object;", "GETVALUE_"); } } } else { addMethodWithTryCatch(opcode, owner, name, desc, itf); } } @Override public void visitJumpInsn(int opcode, Label label) { int iid3; addBipushInsn(mv, iid3 = instrumentationState.incAndGetId()); addBipushInsn(mv, instrumentationState.getMid()); addBipushInsn(mv, System.identityHashCode(label)); // label.getOffset() switch (opcode) { case IFEQ: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IFEQ", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IFNE: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IFNE", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IFLT: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IFLT", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IFGE: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IFGE", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IFGT: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IFGT", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IFLE: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IFLE", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IF_ICMPEQ: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IF_ICMPEQ", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IF_ICMPNE: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IF_ICMPNE", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IF_ICMPLT: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IF_ICMPLT", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IF_ICMPGE: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IF_ICMPGE", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IF_ICMPGT: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IF_ICMPGT", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IF_ICMPLE: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IF_ICMPLE", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IF_ACMPEQ: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IF_ACMPEQ", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IF_ACMPNE: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IF_ACMPNE", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case GOTO: mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "GOTO", "(III)V", false); mv.visitJumpInsn(opcode, label); break; case JSR: mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "JSR", "(III)V", false); mv.visitJumpInsn(opcode, label); break; case IFNULL: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IFNULL", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; case IFNONNULL: coverage.addBranchCount(iid3); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IFNONNULL", "(III)V", false); mv.visitJumpInsn(opcode, label); addSpecialInsn(mv, 1); // for true path break; default: throw new RuntimeException("Unknown jump opcode " + opcode); } } @Override public void visitLdcInsn(Object cst) { addBipushInsn(mv, instrumentationState.incAndGetId()); addBipushInsn(mv, instrumentationState.getMid()); mv.visitLdcInsn(cst); if (cst instanceof Integer) { mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "LDC", "(III)V", false); } else if (cst instanceof Long) { mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "LDC", "(IIJ)V", false); } else if (cst instanceof Float) { mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "LDC", "(IIF)V", false); } else if (cst instanceof Double) { mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "LDC", "(IID)V", false); } else if (cst instanceof String) { mv.visitMethodInsn( INVOKESTATIC, Config.instance.analysisClass, "LDC", "(IILjava/lang/String;)V", false); } else { mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "LDC", "(IILjava/lang/Object;)V", false); } mv.visitLdcInsn(cst); } @Override public void visitIincInsn(int var, int increment) { addBipushInsn(mv, instrumentationState.incAndGetId()); addBipushInsn(mv, instrumentationState.getMid()); addBipushInsn(mv, var); addBipushInsn(mv, increment); mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "IINC", "(IIII)V", false); mv.visitIincInsn(var, increment); } @Override public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { int iid3; addBipushInsn(mv, iid3 = instrumentationState.incAndGetId()); addBipushInsn(mv, instrumentationState.getMid()); addBipushInsn(mv, min); addBipushInsn(mv, max); addBipushInsn(mv, System.identityHashCode(dflt)); // label.getOffset() addBipushInsn(mv, labels.length); mv.visitIntInsn(NEWARRAY, T_INT); for (int i = 0; i < labels.length; i++) { if (i != 0) { iid3 = instrumentationState.incAndGetId(); } coverage.addBranchCount(iid3); mv.visitInsn(DUP); addBipushInsn(mv, i); addBipushInsn(mv, System.identityHashCode(labels[i])); // label.getOffset() mv.visitInsn(IASTORE); } mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "TABLESWITCH", "(IIIII[I)V", false); mv.visitTableSwitchInsn(min, max, dflt, labels); } @Override public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) { int iid3; addBipushInsn(mv, iid3 = instrumentationState.incAndGetId()); addBipushInsn(mv, instrumentationState.getMid()); addBipushInsn(mv, System.identityHashCode(dflt)); // label.getOffset() addBipushInsn(mv, keys.length); mv.visitIntInsn(NEWARRAY, T_INT); for (int i = 0; i < keys.length; i++) { mv.visitInsn(DUP); addBipushInsn(mv, i); addBipushInsn(mv, keys[i]); mv.visitInsn(IASTORE); } addBipushInsn(mv, labels.length); mv.visitIntInsn(NEWARRAY, T_INT); for (int i = 0; i < labels.length; i++) { if (i != 0) { iid3 = instrumentationState.incAndGetId(); } coverage.addBranchCount(iid3); mv.visitInsn(DUP); addBipushInsn(mv, i); addBipushInsn(mv, System.identityHashCode(labels[i])); // label.getOffset() mv.visitInsn(IASTORE); } mv.visitMethodInsn(INVOKESTATIC, Config.instance.analysisClass, "LOOKUPSWITCH", "(III[I[I)V", false); mv.visitLookupSwitchInsn(dflt, keys, labels); } @Override public void visitMultiANewArrayInsn(String desc, int dims) { addBipushInsn(mv, instrumentationState.incAndGetId()); addBipushInsn(mv, instrumentationState.getMid()); mv.visitLdcInsn(desc); addBipushInsn(mv, dims); mv.visitMethodInsn( INVOKESTATIC, Config.instance.analysisClass, "MULTIANEWARRAY", "(IILjava/lang/String;I)V", false); mv.visitMultiANewArrayInsn(desc, dims); addSpecialInsn(mv, 0); // for non-exceptional path } @Override public void visitMaxs(int maxStack, int maxLocals) { for (TryCatchBlock b : tryCatchBlocks) { b.visit(mv); } mv.visitMaxs( maxStack + 8, maxLocals); //To change body of overridden methods use File | Settings | File Templates. } @Override public void visitTryCatchBlock(Label label, Label label1, Label label2, String s) { tryCatchBlocks.addLast(new TryCatchBlock(label, label1, label2, s)); } }