Example usage for org.objectweb.asm.tree AbstractInsnNode getOpcode

List of usage examples for org.objectweb.asm.tree AbstractInsnNode getOpcode

Introduction

In this page you can find the example usage for org.objectweb.asm.tree AbstractInsnNode getOpcode.

Prototype

public int getOpcode() 

Source Link

Document

Returns the opcode of this instruction.

Usage

From source file:de.codesourcery.asm.controlflow.AbstractBlock.java

License:Apache License

@Override
public int getIndexOfSuperConstructorCall(MethodNode method) {
    if (!method.name.equals("<init>")) {
        return -1;
    }/*  w  ww  . ja  v a  2  s .c  o m*/

    @SuppressWarnings("unchecked")
    final ListIterator<AbstractInsnNode> iterator = method.instructions.iterator();
    for (int index = 0; iterator.hasNext(); index++) {
        final AbstractInsnNode instruction = iterator.next();
        if (containsInstructionNum(index) && instruction.getOpcode() == Opcodes.INVOKESPECIAL) {
            final MethodInsnNode invocation = (MethodInsnNode) instruction;
            if (invocation.name.equals("<init>")) {
                return index;
            }
        }
    }
    return -1;
}

From source file:de.codesourcery.asm.controlflow.AbstractBlock.java

License:Apache License

@Override
public int getFirstByteCodeInstructionNum(MethodNode method) throws NoSuchElementException {
    final List<Integer> sorted = new ArrayList<>(instructions);
    Collections.sort(sorted);//from  www. j a v a  2s . co m
    for (int idx : sorted) {
        AbstractInsnNode instruction = method.instructions.get(idx);
        if (instruction.getOpcode() != -1) {
            return idx;
        }
    }
    throw new NoSuchElementException("Block contains only virtual instructions");
}

From source file:de.codesourcery.asm.controlflow.AbstractBlock.java

License:Apache License

@Override
public int getByteCodeInstructionCount(MethodNode method) {

    final InsnList instructions = method.instructions;
    @SuppressWarnings("unchecked")
    final ListIterator<AbstractInsnNode> iterator = instructions.iterator();

    int count = 0;
    for (int index = 0; iterator.hasNext(); index++) {
        final AbstractInsnNode node = iterator.next();
        if (containsInstructionNum(index)) {
            final int opCode = node.getOpcode();
            if (opCode >= 0 && opCode < Printer.OPCODES.length) {
                count++;// ww  w.ja  v  a  2s .co m
            }
        }
    }
    return count;
}

From source file:de.codesourcery.asm.controlflow.ControlFlowAnalyzer.java

License:Apache License

@SuppressWarnings("unchecked")
public ControlFlowGraph analyze(String owner, final MethodNode mn) throws AnalyzerException {
    // line numbers with associated block
    // initially we'll create one block per line and merge adjacent ones later if control flow permits it  
    final Map<Integer, IBlock> blocks = new HashMap<>();

    final ListIterator<AbstractInsnNode> it = mn.instructions.iterator();

    IBlock currentLine = null;//from w w  w.  java 2s .  c om
    Object previousMetadata = null;
    IBlock previous = null;
    final IBlock methodExit = new MethodExit();
    for (int instrCounter = 0; it.hasNext(); instrCounter++) {
        final AbstractInsnNode instruction = it.next();
        currentLine = getBlockForInstruction(instrCounter, blocks);

        if (previous != null) {
            previous.addSuccessor(currentLine, EdgeType.REGULAR, previousMetadata);
            currentLine.addRegularPredecessor(previous);
            previousMetadata = null;
        }

        IBlock nextPrevious = currentLine;
        switch (instruction.getType()) {

        case AbstractInsnNode.LOOKUPSWITCH_INSN:
            LookupSwitchInsnNode lookup = (LookupSwitchInsnNode) instruction;

            // add edge for default handler
            if (lookup.dflt != null) {
                final IBlock target = getBlockForInstruction(lookup.dflt, mn, blocks);
                target.addRegularPredecessor(currentLine);
                currentLine.addRegularSuccessor(target);
            }

            @SuppressWarnings("cast")
            final Iterator<Integer> keys = (Iterator<Integer>) lookup.keys.iterator();

            for (LabelNode ln : (List<LabelNode>) lookup.labels) {
                final IBlock target = getBlockForInstruction(ln, mn, blocks);
                final Integer key = keys.next();

                target.addPredecessor(currentLine, EdgeType.LOOKUP_SWITCH, key);
                currentLine.addSuccessor(target, EdgeType.LOOKUP_SWITCH, key);
            }
            nextPrevious = null;
            break;

        case AbstractInsnNode.TABLESWITCH_INSN:

            TableSwitchInsnNode tblSwitch = (TableSwitchInsnNode) instruction;

            // add edge for default handler
            if (tblSwitch.dflt != null) {
                final IBlock target = getBlockForInstruction(tblSwitch.dflt, mn, blocks);
                target.addRegularPredecessor(currentLine);
                currentLine.addRegularSuccessor(target);
            }
            int currentKey = tblSwitch.min;

            for (LabelNode ln : (List<LabelNode>) tblSwitch.labels) {
                final IBlock target = getBlockForInstruction(ln, mn, blocks);

                target.addPredecessor(currentLine, EdgeType.TABLE_SWITCH, currentKey);
                currentLine.addSuccessor(target, EdgeType.TABLE_SWITCH, currentKey);

                currentKey++;
            }
            nextPrevious = null;
            break;

        case AbstractInsnNode.INSN:

            if (instruction.getOpcode() == Opcodes.RETURN
                    || instruction.getOpcode() == Opcodes.IRETURN) /* method exit */
            {
                currentLine.addRegularSuccessor(methodExit);
                methodExit.addRegularPredecessor(currentLine);
                nextPrevious = null;
            } else if (instruction.getOpcode() == Opcodes.ATHROW || instruction.getOpcode() == Opcodes.RET) {
                nextPrevious = null;
            }
            break;

        case AbstractInsnNode.JUMP_INSN: /* jump */

            final JumpInsnNode jmp = (JumpInsnNode) instruction;
            final LabelNode label = jmp.label;
            final int target = mn.instructions.indexOf(label);

            final boolean isConditional = ASMUtil.isConditionalJump(instruction);

            if (isConditional) { // label edges of conditional jump instructions with "true" and "false
                previousMetadata = "false";
            }

            final IBlock targetBlock = getBlockForInstruction(target, blocks);
            targetBlock.addRegularPredecessor(currentLine);

            // create edge from current block to jump target 
            currentLine.addSuccessor(targetBlock, EdgeType.REGULAR, isConditional ? "true" : null);

            if (instruction.getOpcode() == Opcodes.GOTO) {
                nextPrevious = null;
            }
            break;
        }

        // link last instruction with method_exit block
        if (!it.hasNext()) {
            currentLine.addRegularSuccessor(methodExit);
            methodExit.addRegularPredecessor(currentLine);
        }
        previous = nextPrevious;
    }
    // try/catch blocks need special treatment because
    // they are not represented as opcodes
    for (TryCatchBlockNode node : (List<TryCatchBlockNode>) mn.tryCatchBlocks) {
        final LabelNode startLabel = node.start;
        final int startTarget = mn.instructions.indexOf(startLabel);

        final LabelNode endLabel = node.end;
        final int endTarget = mn.instructions.indexOf(endLabel);

        final int handlerTarget = mn.instructions.indexOf(node.handler);
        IBlock handler = getBlockForInstruction(node.handler, mn, blocks);

        for (int i = startTarget; i <= endTarget; i++) {
            if (i != handlerTarget) {
                getBlockForInstruction(i, blocks).addExceptionHandler(handler, node.type);
            }
        }
    }

    // merge adjacent instructions
    final Set<Integer> linesBeforeMerge = new HashSet<>();
    for (IBlock block : blocks.values()) {
        linesBeforeMerge.addAll(block.getInstructionNums());
    }

    final List<IBlock> result = mergeBlocks(blocks, mn);

    if (debug) {
        System.out.println("################ Control-blocks merged ################");
    }
    // sanity check
    final Set<Integer> linesAfterMerge = new HashSet<>();
    for (IBlock block : result) {
        linesAfterMerge.addAll(block.getInstructionNums());
        if (debug) {
            System.out.println("-----");
            System.out.println(block + " has " + block.getByteCodeInstructionCount(mn) + " instructions.");
            System.out.println(block.disassemble(mn, false, true));
        }
        for (Edge e : block.getEdges()) {
            if (!result.contains(e.src) && e.src != methodExit) {
                throw new RuntimeException(e + " has src that is not in result list?");
            }
            if (!result.contains(e.dst) && e.dst != methodExit) {
                throw new RuntimeException(e + " has destination that is not in result list?");
            }
        }
    }

    if (!linesBeforeMerge.equals(linesAfterMerge)) {
        throw new RuntimeException("Internal error, line count mismatch before/after control block merge: \n\n"
                + linesBeforeMerge + "\n\n" + linesAfterMerge);
    }

    // add starting block and link it with block that contains the lowest instruction number
    MethodEntry methodEntry = new MethodEntry();
    int lowest = Integer.MAX_VALUE;
    for (Integer i : blocks.keySet()) {
        if (i < lowest) {
            lowest = i;
        }
    }

    final IBlock firstBlock = blocks.get(lowest);
    if (firstBlock.hasRegularPredecessor()) {
        throw new IllegalStateException(firstBlock + " that constrains first instruction has a predecessor?");
    }

    methodEntry.addRegularSuccessor(firstBlock);
    firstBlock.addRegularPredecessor(methodEntry);
    result.add(0, methodEntry);

    // add end block to results
    result.add(methodExit);//owner+"#"+
    ControlFlowGraph cfg = new ControlFlowGraph(mn, result);
    System.out.println("CFGMAP:" + formatname(owner) + "#" + cfg.getMethod().name);
    graphmap.put(formatname(owner) + "#" + cfg.getMethod().name, cfg);
    return cfg;
}

From source file:de.codesourcery.asm.util.ASMUtil.java

License:Apache License

/**
 * Check whether an instruction is a conditional branch operation.
 *  /*ww w.  ja va 2s.c  o  m*/
 * @param node
 * @return
 */
public static boolean isConditionalJump(AbstractInsnNode node) {
    if (node.getType() == AbstractInsnNode.JUMP_INSN) {
        switch (node.getOpcode()) {
        case Opcodes.IFEQ:
        case Opcodes.IFNE:
        case Opcodes.IFLT:
        case Opcodes.IFGE:
        case Opcodes.IFGT:
        case Opcodes.IFLE:
        case Opcodes.IF_ICMPEQ:
        case Opcodes.IF_ICMPNE:
        case Opcodes.IF_ICMPLT:
        case Opcodes.IF_ICMPGE:
        case Opcodes.IF_ICMPGT:
        case Opcodes.IF_ICMPLE:
        case Opcodes.IF_ACMPEQ:
        case Opcodes.IF_ACMPNE:
        case Opcodes.IFNULL:
        case Opcodes.IFNONNULL:
            return true;
        }
    }
    return false;
}

From source file:de.codesourcery.asm.util.Disassembler.java

License:Apache License

/**
 * Disassemble a single {@link AbstractInsnNode} node.
 * //from  w  w w  .ja  v a 2 s.c  o  m
 * @param node the node to disassemble
 * @param method the method this node comes from
 * @param includeVirtual whether to 'disassemble' virtual (ASM-generated) nodes that
 * have no equivalent in .class files
 * @param printInsnIndices whether to output the instruction index in front of the mnemonic
 * @return disassembled instruction or <code>null</code> if the node does not map 
 * to a bytecode (=is virtual) and the <code>includeVirtual</code> flag was <code>false</code>
 */
public static String disassemble(AbstractInsnNode node, MethodNode method, boolean includeVirtual,
        boolean printInsnIndices) {
    final int opCode = node.getOpcode();
    final String mnemonic;
    if (opCode < 0 || opCode >= Printer.OPCODES.length) {
        if (!includeVirtual) {
            return null;
        }
        mnemonic = "// " + node.getClass().getSimpleName();
    } else {
        mnemonic = disassemble(node, method);
    }

    if (printInsnIndices) {
        final int indexOf = method.instructions.indexOf(node);
        String index = Integer.toString(indexOf);
        if (index.length() < 4) {
            index = StringUtils.leftPad(index, 4);
        }
        return index + ": " + mnemonic;
    }
    return mnemonic;
}

From source file:de.codesourcery.asm.util.Disassembler.java

License:Apache License

private static String disassemble(AbstractInsnNode node, MethodNode method) {
    final int opCode = node.getOpcode();
    String mnemonic = Printer.OPCODES[opCode];

    switch (node.getType()) {
    case AbstractInsnNode.FIELD_INSN: // GETSTATIC, PUTSTATIC, GETFIELD , PUTFIELD
        FieldInsnNode tmp = (FieldInsnNode) node;
        mnemonic += " " + (tmp.owner + "#" + tmp.name);
        break;//from   w  ww .  j a va2s  . com
    case AbstractInsnNode.IINC_INSN: // IINC
        IincInsnNode tmp2 = (IincInsnNode) node;
        mnemonic += " " + (tmp2.var + " , " + tmp2.incr);
        break;
    case AbstractInsnNode.INSN: // regular opcodes
        break;
    case AbstractInsnNode.INT_INSN: // BIPUSH, SIPUSH or NEWARRAY
        IntInsnNode tmp3 = (IntInsnNode) node;
        mnemonic += " " + (tmp3.operand);
        break;
    case AbstractInsnNode.INVOKE_DYNAMIC_INSN: // INVOKEDYNAMIC
        break;
    case AbstractInsnNode.JUMP_INSN: // IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL
        JumpInsnNode tmp4 = (JumpInsnNode) node;
        int index = method.instructions.indexOf(tmp4.label);
        while (method.instructions.get(index).getOpcode() == -1) {
            index++;
        }
        mnemonic += " " + index;
        break;
    case AbstractInsnNode.LDC_INSN: // load constant
        LdcInsnNode tmp5 = (LdcInsnNode) node;
        Class<?> clazz = tmp5.cst.getClass();
        if (clazz == String.class) {
            mnemonic += " \"" + tmp5.cst + "\"";
        } else if (clazz == org.objectweb.asm.Type.class) {
            org.objectweb.asm.Type type = (org.objectweb.asm.Type) tmp5.cst;
            mnemonic += " (a " + type.getClassName() + ")";
        } else {
            mnemonic += " " + tmp5.cst + " (" + tmp5.cst.getClass().getName() + ")";
        }
        break;
    case AbstractInsnNode.LOOKUPSWITCH_INSN: // LOOKUPSWITCH
        break;
    case AbstractInsnNode.METHOD_INSN: // INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC , INVOKEINTERFACE
        MethodInsnNode tmp6 = (MethodInsnNode) node;
        mnemonic += " " + (tmp6.owner + "#" + tmp6.name + "()");
        break;
    case AbstractInsnNode.MULTIANEWARRAY_INSN: // MULTIANEWARRAY
        break;
    case AbstractInsnNode.TABLESWITCH_INSN: // TABLESWITCH
        break;
    case AbstractInsnNode.TYPE_INSN: // NEW, ANEWARRAY, CHECKCAST , INSTANCEOF
        TypeInsnNode tmp8 = (TypeInsnNode) node;
        mnemonic += " " + tmp8.desc;
        break;
    case AbstractInsnNode.VAR_INSN: // ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE , RET
        VarInsnNode tmp7 = (VarInsnNode) node;
        mnemonic += "_" + tmp7.var;
        break;
    // -- VIRTUAL --
    case AbstractInsnNode.FRAME: /* VIRTUAL */
    case AbstractInsnNode.LABEL: /* VIRTUAL */
    case AbstractInsnNode.LINE: /* VIRTUAL */
    default:
        throw new RuntimeException("Internal error, unhandled node type: " + node);
    }
    return mnemonic;
}

From source file:de.jiac.micro.config.analysis.BasicGuesser.java

License:Open Source License

public Value newOperation(final AbstractInsnNode insn) {
    switch (insn.getOpcode()) {
    case ACONST_NULL:
        return RuntimeGuessValue.NULL_CONSTANT;
    case ICONST_M1:
        return RuntimeGuessValue.IM1_CONSTANT;
    case ICONST_0:
        return RuntimeGuessValue.I0_CONSTANT;
    case ICONST_1:
        return RuntimeGuessValue.I1_CONSTANT;
    case ICONST_2:
        return RuntimeGuessValue.I2_CONSTANT;
    case ICONST_3:
        return RuntimeGuessValue.I3_CONSTANT;
    case ICONST_4:
        return RuntimeGuessValue.I4_CONSTANT;
    case ICONST_5:
        return RuntimeGuessValue.I5_CONSTANT;
    case LCONST_0:
        return RuntimeGuessValue.L0_CONSTANT;
    case LCONST_1:
        return RuntimeGuessValue.L1_CONSTANT;
    case FCONST_0:
        return RuntimeGuessValue.F0_CONSTANT;
    case FCONST_1:
        return RuntimeGuessValue.F1_CONSTANT;
    case FCONST_2:
        return RuntimeGuessValue.F2_CONSTANT;
    case DCONST_0:
        return RuntimeGuessValue.D0_CONSTANT;
    case DCONST_1:
        return RuntimeGuessValue.D1_CONSTANT;
    case BIPUSH:/*from w  w  w . j ava  2s .  com*/
    case SIPUSH:
        return new RuntimeGuessValue(Type.INT_TYPE, Integer.valueOf(((IntInsnNode) insn).operand));
    case LDC:
        Object cst = ((LdcInsnNode) insn).cst;
        if (cst instanceof Integer) {
            return new RuntimeGuessValue(Type.INT_TYPE, cst);
        } else if (cst instanceof Float) {
            return new RuntimeGuessValue(Type.FLOAT_TYPE, cst);
        } else if (cst instanceof Long) {
            return new RuntimeGuessValue(Type.LONG_TYPE, cst);
        } else if (cst instanceof Double) {
            return new RuntimeGuessValue(Type.DOUBLE_TYPE, cst);
        } else if (cst instanceof Type) {
            return new RuntimeGuessValue(Type.getObjectType("java/lang/Class"), ((Type) cst).getClassName());
        } else {
            return new RuntimeGuessValue(Type.getType(cst.getClass()), cst);
        }
    case JSR:
        return RuntimeGuessValue.RETURNADDRESS_VALUE;
    case GETSTATIC:
        return newValue(Type.getType(((FieldInsnNode) insn).desc));
    case NEW:
        return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
    default:
        throw new Error("Internal error.");
    }
}

From source file:de.jiac.micro.config.analysis.BasicGuesser.java

License:Open Source License

public Value unaryOperation(final AbstractInsnNode insn, final Value value) throws AnalyzerException {
    switch (insn.getOpcode()) {
    case INEG://from w  w  w  .j  a v  a  2s. c om
    case IINC:
    case L2I:
    case F2I:
    case D2I:
    case I2B:
    case I2C:
    case I2S:
        return RuntimeGuessValue.UNSPECIFIED_INT_VALUE;
    case FNEG:
    case I2F:
    case L2F:
    case D2F:
        return RuntimeGuessValue.UNSPECIFIED_FLOAT_VALUE;
    case LNEG:
    case I2L:
    case F2L:
    case D2L:
        return RuntimeGuessValue.UNSPECIFIED_LONG_VALUE;
    case DNEG:
    case I2D:
    case L2D:
    case F2D:
        return RuntimeGuessValue.UNSPECIFIED_DOUBLE_VALUE;
    case IFEQ:
    case IFNE:
    case IFLT:
    case IFGE:
    case IFGT:
    case IFLE:
    case TABLESWITCH:
    case LOOKUPSWITCH:
    case IRETURN:
    case LRETURN:
    case FRETURN:
    case DRETURN:
    case ARETURN:
    case PUTSTATIC:
        return null;
    case GETFIELD:
        return newValue(Type.getType(((FieldInsnNode) insn).desc));
    case NEWARRAY:
        switch (((IntInsnNode) insn).operand) {
        case T_BOOLEAN:
            return newValue(Type.getType("[Z"));
        case T_CHAR:
            return newValue(Type.getType("[C"));
        case T_BYTE:
            return newValue(Type.getType("[B"));
        case T_SHORT:
            return newValue(Type.getType("[S"));
        case T_INT:
            return newValue(Type.getType("[I"));
        case T_FLOAT:
            return newValue(Type.getType("[F"));
        case T_DOUBLE:
            return newValue(Type.getType("[D"));
        case T_LONG:
            return newValue(Type.getType("[J"));
        default:
            throw new AnalyzerException("Invalid array type");
        }
    case ANEWARRAY:
        String desc = ((TypeInsnNode) insn).desc;
        return newValue(Type.getType("[" + Type.getObjectType(desc)));
    case ARRAYLENGTH:
        return RuntimeGuessValue.UNSPECIFIED_INT_VALUE;
    case ATHROW:
        return null;
    case CHECKCAST:
        desc = ((TypeInsnNode) insn).desc;
        return newValue(Type.getObjectType(desc));
    case INSTANCEOF:
        return RuntimeGuessValue.UNSPECIFIED_INT_VALUE;
    case MONITORENTER:
    case MONITOREXIT:
    case IFNULL:
    case IFNONNULL:
        return null;
    default:
        throw new Error("Internal error.");
    }
}

From source file:de.jiac.micro.config.analysis.BasicGuesser.java

License:Open Source License

public Value binaryOperation(final AbstractInsnNode insn, final Value value1, final Value value2)
        throws AnalyzerException {
    switch (insn.getOpcode()) {
    case IALOAD://w  w  w.  j  av  a  2  s  . c o  m
    case BALOAD:
    case CALOAD:
    case SALOAD:
    case IADD:
    case ISUB:
    case IMUL:
    case IDIV:
    case IREM:
    case ISHL:
    case ISHR:
    case IUSHR:
    case IAND:
    case IOR:
    case IXOR:
        return RuntimeGuessValue.UNSPECIFIED_INT_VALUE;
    case FALOAD:
    case FADD:
    case FSUB:
    case FMUL:
    case FDIV:
    case FREM:
        return RuntimeGuessValue.UNSPECIFIED_FLOAT_VALUE;
    case LALOAD:
    case LADD:
    case LSUB:
    case LMUL:
    case LDIV:
    case LREM:
    case LSHL:
    case LSHR:
    case LUSHR:
    case LAND:
    case LOR:
    case LXOR:
        return RuntimeGuessValue.UNSPECIFIED_LONG_VALUE;
    case DALOAD:
    case DADD:
    case DSUB:
    case DMUL:
    case DDIV:
    case DREM:
        return RuntimeGuessValue.UNSPECIFIED_DOUBLE_VALUE;
    case AALOAD:
        return new RuntimeGuessValue(Type.getObjectType("java/lang/Object"), null); // FIXME: type!
    case LCMP:
    case FCMPL:
    case FCMPG:
    case DCMPL:
    case DCMPG:
        return RuntimeGuessValue.UNSPECIFIED_INT_VALUE;
    case IF_ICMPEQ:
    case IF_ICMPNE:
    case IF_ICMPLT:
    case IF_ICMPGE:
    case IF_ICMPGT:
    case IF_ICMPLE:
    case IF_ACMPEQ:
    case IF_ACMPNE:
    case PUTFIELD:
        return null;
    default:
        throw new Error("Internal error.");
    }
}