List of usage examples for org.objectweb.asm.tree AbstractInsnNode getOpcode
public int getOpcode()
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."); } }