/** * Creates the new instructions, inlining each instantiation of each * subroutine until the code is fully elaborated. */ private void emitCode() { LinkedList<Instantiation> worklist = new LinkedList<Instantiation>(); // Create an instantiation of the "root" subroutine, which is just the // main routine worklist.add(new Instantiation(null, mainSubroutine)); // Emit instantiations of each subroutine we encounter, including the // main subroutine InsnList newInstructions = new InsnList(); List<TryCatchBlockNode> newTryCatchBlocks = new ArrayList<TryCatchBlockNode>(); List<LocalVariableNode> newLocalVariables = new ArrayList<LocalVariableNode>(); while (!worklist.isEmpty()) { Instantiation inst = worklist.removeFirst(); emitSubroutine(inst, worklist, newInstructions, newTryCatchBlocks, newLocalVariables); } instructions = newInstructions; tryCatchBlocks = newTryCatchBlocks; localVariables = newLocalVariables; }
private static void stringEncryptionTransformer(ClassNode classNode) { if (classNode.superName.equals("org/bukkit/plugin/java/JavaPlugin") || classNode.superName.equals("net/md_5/bungee/api/plugin/Plugin")) { for (MethodNode methodNode : classNode.methods) { InsnList nodes = methodNode.instructions; for (int i = 0; i < nodes.size(); i++) { AbstractInsnNode instruction = nodes.get(i); if (instruction instanceof LdcInsnNode) { if (instruction.getNext() instanceof MethodInsnNode) { LdcInsnNode ldc = (LdcInsnNode) instruction; MethodInsnNode methodinsnnode = (MethodInsnNode) ldc.getNext(); if (ldc.cst instanceof String) { if (methodinsnnode.name.equalsIgnoreCase("\u0972") && methodinsnnode.desc.equalsIgnoreCase("(Ljava/lang/String;)Ljava/lang/String;")) { methodNode.instructions.remove(methodinsnnode); ldc.cst = decryptionArray((String)ldc.cst); } } } } } } } }
public static InsnList toNumericalValue(String what) { Objects.requireNonNull(what); InsnList il = new InsnList(); il.add(new LdcInsnNode(what)); il.add(new MethodInsnNode( INVOKESTATIC, Type.getInternalName(Conversions.class), "toNumericalValue", Type.getMethodDescriptor( Type.getType(Number.class), Type.getType(Object.class), Type.getType(String.class)), false)); return il; }
private static BitSet getEntryPoints(MethodNode asmNode, Map<AbstractInsnNode, int[]> exitPoints) { InsnList il = asmNode.instructions; BitSet entryPoints = new BitSet(il.size()); for (int[] eps : exitPoints.values()) { if (eps != null) { for (int ep : eps) entryPoints.set(ep); } } for (TryCatchBlockNode n : asmNode.tryCatchBlocks) { entryPoints.set(il.indexOf(n.handler)); } return entryPoints; }
private static void addDirectExits(InsnList il, BitSet entryPoints, Map<AbstractInsnNode, int[]> exitPoints) { int idx = 0; // ignore 0 since it has no preceding instruction while ((idx = entryPoints.nextSetBit(idx + 1)) != -1) { AbstractInsnNode prev = il.get(idx - 1); if (exitPoints.containsKey(prev)) continue; int type = prev.getType(); if (prev.getOpcode() != Opcodes.ATHROW && (prev.getOpcode() < Opcodes.IRETURN || prev.getOpcode() > Opcodes.RETURN) && type != AbstractInsnNode.JUMP_INSN && type != AbstractInsnNode.TABLESWITCH_INSN && type != AbstractInsnNode.LOOKUPSWITCH_INSN) { exitPoints.put(prev, new int[] { idx }); } } }
@Override public MethodTransformer[] getMethodTransformers() { MethodTransformer loadWorldTransformer = new MethodTransformer() { public String getMethodName() {return CoreLoader.isObfuscated ? "a" : "loadWorld";} public String getDescName() {return "(L" + (CoreLoader.isObfuscated ? "bnq" : Type.getInternalName(WorldClient.class)) + ";Ljava/lang/String;)V";} public void transform(ClassNode classNode, MethodNode method, boolean obfuscated) { CLTLog.info("Found method: " + method.name + " " + method.desc); CLTLog.info("begining at start of method " + getMethodName()); //TransformerUtil.onWorldLoad(WorldClient worldClientIn) InsnList toInsert = new InsnList(); toInsert.add(new VarInsnNode(ALOAD, 1)); //worldClientIn toInsert.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(TransformerUtil.class), "onWorldLoad", "(L" + Type.getInternalName(WorldClient.class) + ";)V", false)); method.instructions.insertBefore(method.instructions.getFirst(), toInsert); } }; return new MethodTransformer[] {loadWorldTransformer}; }
public static InsnList newTable(int array, int hash) { InsnList il = new InsnList(); il.add(ASMUtils.loadInt(array)); il.add(ASMUtils.loadInt(hash)); il.add(new MethodInsnNode( INVOKEINTERFACE, selfTpe().getInternalName(), "newTable", Type.getMethodType( Type.getType(Table.class), Type.INT_TYPE, Type.INT_TYPE).getDescriptor(), true)); return il; }
public static InsnList get(int index) { Check.nonNegative(index); InsnList il = new InsnList(); if (index <= 4) { String methodName = "get" + index; il.add(new MethodInsnNode( INVOKEINTERFACE, selfTpe().getInternalName(), methodName, Type.getMethodType( Type.getType(Object.class)).getDescriptor(), true)); } else { il.add(ASMUtils.loadInt(index)); il.add(get()); } return il; }
public RunMethod.ClosureFieldInstance toClosureFieldInstance() { assert (this.isClosed()); FieldNode fieldNode = instanceFieldNode(); InsnList il = new InsnList(); il.add(new VarInsnNode(ALOAD, 0)); il.add(instantiationInsns()); il.add(new FieldInsnNode( PUTFIELD, context.thisClassType().getInternalName(), instanceFieldName(), instanceType().getDescriptor())); return new RunMethod.ClosureFieldInstance(instanceFieldNode(), il); }
private InsnList fetchInstanceInsns() { InsnList il = new InsnList(); if (this.isClosed()) { if (this.isPure()) { il.add(new FieldInsnNode( GETSTATIC, instanceType().getInternalName(), ASMBytecodeEmitter.instanceFieldName(), instanceType().getDescriptor())); } else { il.add(new VarInsnNode(ALOAD, 0)); il.add(new FieldInsnNode( GETFIELD, context.thisClassType().getInternalName(), instanceFieldName(), instanceType().getDescriptor())); } } else { il.add(instantiationInsns()); } return il; }
private InsnList dispatchTable(List<LabelNode> extLabels, List<LabelNode> resumptionLabels, LabelNode errorStateLabel) { InsnList il = new InsnList(); assert (!extLabels.isEmpty()); ArrayList<LabelNode> labels = new ArrayList<>(); labels.addAll(extLabels); labels.addAll(resumptionLabels); LabelNode[] labelArray = labels.toArray(new LabelNode[labels.size()]); int min = 1 - extLabels.size(); int max = resumptionLabels.size(); il.add(new VarInsnNode(ILOAD, LV_RESUME)); il.add(new TableSwitchInsnNode(min, max, errorStateLabel, labelArray)); return il; }
InsnList createSnapshot() { InsnList il = new InsnList(); il.add(new VarInsnNode(ALOAD, 0)); // this il.add(new VarInsnNode(ALOAD, 0)); il.add(new VarInsnNode(ILOAD, LV_RESUME)); if (context.isVararg()) { il.add(new VarInsnNode(ALOAD, LV_VARARGS)); } for (int i = 0; i < numOfRegisters(); i++) { il.add(new VarInsnNode(ALOAD, slotOffset() + i)); } il.add(snapshotMethodInvokeInsn()); return il; }
protected InsnList resumptionHandler(LabelNode label) { InsnList il = new InsnList(); il.add(label); il.add(ASMUtils.frameSame1(UnresolvedControlThrowable.class)); il.add(createSnapshot()); // register snapshot with the control exception il.add(new MethodInsnNode( INVOKEVIRTUAL, Type.getInternalName(UnresolvedControlThrowable.class), "resolve", Type.getMethodType( Type.getType(ResolvedControlThrowable.class), Type.getType(Resumable.class), Type.getType(Object.class)).getDescriptor(), false)); // rethrow il.add(new InsnNode(ATHROW)); return il; }
public byte[] transformCode(byte[] b1, String className) throws IOException { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); ClassReader cr = new ClassReader(b1); ClassNode classNode = new ClassNode(); Map<String, Boolean> methodInstructionTypeMap = new HashMap<>(); cr.accept(classNode, 0); final List<MethodNode> methods = classNode.methods; for (MethodNode m : methods) { InsnList inList = m.instructions; boolean isMethodInvoke = false; for (int i = 0; i < inList.size(); i++) { if (inList.get(i).getType() == AbstractInsnNode.METHOD_INSN) { isMethodInvoke = true; } } methodInstructionTypeMap.put(m.name + m.desc, isMethodInvoke); } InsertMethodBodyAdapter insertMethodBodyAdapter = new InsertMethodBodyAdapter(cw, className, methodInstructionTypeMap); cr.accept(insertMethodBodyAdapter, ClassReader.EXPAND_FRAMES); return cw.toByteArray(); }
public void populateClassGraph() { String className = Type.getObjectType(classNode.name).getClassName(); logger.debug("Creating graph for class {}" , className); for (MethodNode methodNode : classNode.methods) { String methodName = methodNode.name; MethodGraph caller = new MethodGraph(className, methodName); InsnList instructions = methodNode.instructions; for (int i = 0; i < instructions.size(); i++) { AbstractInsnNode insnNode = instructions.get(i); if (insnNode.getType() == AbstractInsnNode.METHOD_INSN) { MethodInsnNode methodInsnNode = (MethodInsnNode)insnNode; String calledOwner = Type.getObjectType(methodInsnNode.owner).getClassName(); String calledName = methodInsnNode.name; MethodGraph called = new MethodGraph(calledOwner, calledName); Call call = new Call(caller, called); if (!called.getOwner().equals("java.lang.Object") && !called.getName().equals("<init>")) { logger.trace("Adding call graph: {}", call.toString()); GraphHolder.addCallGraph(call); } } } } }
@Override public MethodTransformer[] getMethodTransformers() { MethodTransformer transformLoadWorld = new MethodTransformer() { @Override public MethodName getName() { return Names.Minecraft_loadWorld; } @Override public void transform(ClassNode classNode, MethodNode method, boolean obfuscated) { CLTLog.info("Found method: " + method.name + " " + method.desc); CLTLog.info("begining at start of method " + getName().all()); InsnList toInsert = new InsnList(); toInsert.add(new VarInsnNode(ALOAD, 1)); //worldClientIn toInsert.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(RenderUtil.class), "onWorldLoad", "(L" + Type.getInternalName(WorldClient.class) + ";)V", false)); method.instructions.insertBefore(method.instructions.getFirst(), toInsert); } }; return new MethodTransformer[] {transformLoadWorld}; }
/** * 格式化输出字节码 * @param bytecode */ public static void viewByteCode(byte[] bytecode) { ClassReader cr = new ClassReader(bytecode); ClassNode cn = new ClassNode(); cr.accept(cn, 0); final List<MethodNode> mns = cn.methods; Printer printer = new Textifier(); TraceMethodVisitor mp = new TraceMethodVisitor(printer); for (MethodNode mn : mns) { InsnList inList = mn.instructions; System.out.println(mn.name); for (int i = 0; i < inList.size(); i++) { inList.get(i).accept(mp); StringWriter sw = new StringWriter(); printer.print(new PrintWriter(sw)); printer.getText().clear(); System.out.print(sw.toString()); } } }
public void printClassByteCode(byte code[]) { ClassReader cr = new ClassReader(code); ClassNode cn = new ClassNode(); cr.accept(cn, 0); @SuppressWarnings("unchecked") List<MethodNode> methods = (List<MethodNode>)cn.methods; for (int i = 0; i < methods.size(); ++i) { MethodNode method = methods.get(i); InsnList instructions = method.instructions; if (instructions.size() <= 0) continue; System.out.println("Method: "+method.name+" "); for (int j = 0; j < instructions.size(); ++j) { AbstractInsnNode insn = (AbstractInsnNode)instructions.get(j); System.out.println("\tInsn: opc="+OpcodeUtil.getOpcode(insn.getOpcode())+", type="+insn.getType()); if (insn.getType() == AbstractInsnNode.METHOD_INSN) { MethodInsnNode min = (MethodInsnNode)insn; System.out.printf("\t\towner=%s, name=%s, desc=%s\n", min.owner, min.name, min.desc); } } } }
@Override public void patchMethod(MethodNode methodNode, ClassNode classNode, boolean obfuscated) { AbstractInsnNode insert = ASMUtil.findFirstInstruction(methodNode, Opcodes.DSTORE, 5); if (insert == null) return; InsnList insnList = new InsnList(); insnList.add(new VarInsnNode(Opcodes.ALOAD, 0)); insnList.add(new FieldInsnNode(Opcodes.GETFIELD, obfuscated ? "nh" : "net/minecraft/network/NetHandlerPlayServer", obfuscated ? "b" : "playerEntity", obfuscated ? "Lmw;" : "Lnet/minecraft/entity/player/EntityPlayerMP;")); insnList.add(new VarInsnNode(Opcodes.DLOAD, 5)); insnList.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "com/techjar/vivecraftforge/util/ASMDelegator", "playerEntityReachDistance", obfuscated ? "(Lyz;D)D" : "(Lnet/minecraft/entity/player/EntityPlayer;D)D", false)); insnList.add(new VarInsnNode(Opcodes.DSTORE, 5)); methodNode.instructions.insert(insert, insnList); VivecraftForgeLog.debug("Inserted delegate method call."); AbstractInsnNode removeInsn = ASMUtil.findFirstInstruction(methodNode, Opcodes.LDC, 9.0D); if (removeInsn != null) { int remove = methodNode.instructions.indexOf(removeInsn); for (int i = 0; i < 2; i++) { methodNode.instructions.remove(methodNode.instructions.get(remove)); } VivecraftForgeLog.debug("Removed variable assignment."); } else { VivecraftForgeLog.debug("Variable assignment not found."); } }
@Override public ClassVisitor patch(String className, ClassVisitor delegate) throws Exception { return new FindingVisitor( delegate, new VarInsnNode(ALOAD, 4), new LdcInsnNode(7000L), new MethodInsnNode(INVOKEVIRTUAL, "java/lang/Thread", "join", "(J)V", false) ) { @Override public void handle(InsnList nodes, MethodVisitor visitor) { visitor.visitVarInsn(ALOAD, 4); visitor.visitFieldInsn(GETSTATIC, "org/squiddev/cctweaks/lua/Config$Computer", "computerThreadTimeout", "I"); visitor.visitInsn(I2L); visitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Thread", "join", "(J)V", false); } }.onMethod("run").once().mustFind(); }
@Override public ClassVisitor patch(String className, ClassVisitor delegate) throws Exception { return new FindingVisitor( delegate, new LdcInsnNode("lua/bios.lua") ) { @Override public void handle(InsnList nodes, MethodVisitor visitor) { Label finish = new Label(), def = new Label(); visitor.visitVarInsn(ALOAD, 0); visitor.visitFieldInsn(GETFIELD, "dan200/computercraft/core/computer/Computer", "biosPath", "Ljava/lang/String;"); visitor.visitJumpInsn(IFNULL, def); visitor.visitVarInsn(ALOAD, 0); visitor.visitFieldInsn(GETFIELD, "dan200/computercraft/core/computer/Computer", "biosPath", "Ljava/lang/String;"); visitor.visitJumpInsn(GOTO, finish); visitor.visitLabel(def); visitor.visitLdcInsn("lua/bios.lua"); visitor.visitLabel(finish); } }.onMethod("initLua").mustFind(); }
public ImagineMethod callLast(final String owner, final String methodName) { final InsnList instructions = this.mMethod.instructions; final InsnList methodCall = methodCall(this, owner, methodName, owner != null, false); for (final AbstractInsnNode node : instructions) { switch (node.getOpcode()) { case 172: case 173: case 174: case 175: case 176: case 177: { instructions.insertBefore(node, methodCall); continue; } } } return this; }
public Iterable<ImagineMethodPosition> find(final InsnList patternRaw) { final List<AbstractInsnNode> pattern = ImagineASM.asList(patternRaw); return new LazyIterable<ImagineMethodPosition>(new LazyIterable.LazyAction<ImagineMethodPosition>() { private int mPosition = 0; private CuttableList<AbstractInsnNode> mInstructions = new CuttableList<AbstractInsnNode>(ImagineASM.asList(ImagineMethod.this.mMethod.instructions)); @Override public ImagineMethodPosition acquire() { final int index = Collections.indexOfSubList(this.mInstructions, pattern); if (index >= 0) { this.mPosition += index; for (int i = 0; i < index; ++i) {} } final Iterator<AbstractInsnNode> patternIterator = pattern.iterator(); return null; } }); }
public static InsnList getImportantList(InsnList list) { if (list.size() == 0) { return list; } HashMap<LabelNode, LabelNode> labels = new HashMap<>(); for (AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) { if (insn instanceof LabelNode) { labels.put((LabelNode) insn, (LabelNode) insn); } } InsnList importantNodeList = new InsnList(); for (AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) { if (insn instanceof LabelNode || insn instanceof LineNumberNode) { continue; } importantNodeList.add(insn.clone(labels)); } return importantNodeList; }
private static InsnListSection insnListMatchesL(InsnList haystack, InsnList needle, int start, HashSet<LabelNode> controlFlowLabels) { int h = start, n = 0; for (; h < haystack.size() && n < needle.size(); h++) { AbstractInsnNode insn = haystack.get(h); if (insn.getType() == 15) { continue; } if (insn.getType() == 8 && !controlFlowLabels.contains(insn)) { continue; } if (!insnEqual(haystack.get(h), needle.get(n))) { return null; } n++; } if (n != needle.size()) { return null; } return new InsnListSection(haystack, start, h - 1); }
private byte[] transformPlayer(byte[] bytes) { ClassNode clazz = ASMHelper.createClassNode(bytes); MethodNode method = ASMHelper.findMethod(clazz, ASMNames.MD_PLAYER_UPDATE); InsnList needle = new InsnList(); needle.add(new VarInsnNode(Opcodes.ALOAD, 0)); needle.add(ASMHelper.getFieldInsnNode(Opcodes.GETFIELD, ASMNames.FD_PLAYER_WORLD_OBJ)); needle.add(ASMHelper.getMethodInsnNode(Opcodes.INVOKEVIRTUAL, ASMNames.MD_WORLD_IS_DAY, false)); LabelNode l2 = new LabelNode(); needle.add(new JumpInsnNode(Opcodes.IFEQ, l2)); AbstractInsnNode insertPoint = ASMHelper.findFirstNodeFromNeedle(method.instructions, needle); method.instructions.remove(insertPoint.getNext().getNext()); method.instructions.set(insertPoint.getNext(), ASMHelper.getMethodInsnNode(Opcodes.INVOKESTATIC, ASMNames.MD_RM_HELPER_SLEEP_PLAEYR, false)); return ASMHelper.createBytes(clazz, ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); }
/** Test. */ @Test public void testNonEmptyFilter() throws Exception { final String className = SampleClass.class.getName(); IMethodFilter filter = new EmptyMethodFilter(); MethodNode methodNode; methodNode = new MethodNode(); methodNode.instructions = new InsnList(); methodNode.instructions.add(new InsnNode(Opcodes.NOP)); methodNode.maxLocals = 0; methodNode.maxStack = 0; assertFalse(analyze(filter, className, "empty", "()V", methodNode)); methodNode = new MethodNode(); methodNode.instructions = new InsnList(); methodNode.instructions.add(new InsnNode(Opcodes.ICONST_1)); methodNode.instructions.add(new InsnNode(Opcodes.IRETURN)); methodNode.maxLocals = 0; methodNode.maxStack = 1; assertTrue(analyze(filter, className, "returnTrue", "()Z", methodNode)); }
public static void markClinitCallback(ClassNode node, Runnable... runnables) { callback_mapping.get(node.name).addAll(Arrays.asList(runnables)); for (String i : node.interfaces) if (i.equals(CALLBACK_FLAG_DESC)) return; node.interfaces.add(CALLBACK_FLAG_DESC); MethodNode clinit = null; for (MethodNode method : node.methods) if (method.name.equals("<clinit>")) { clinit = method; break; } boolean flag = clinit == null; if (flag) node.methods.add(clinit = new MethodNode(0, "<clinit>", "()V", null, null)); InsnList list = new InsnList(); list.add(new LdcInsnNode(node.name)); list.add(new MethodInsnNode(INVOKESTATIC, "index/alchemy/core/asm/transformer/AlchemyTransformerManager", "callback", "(Ljava/lang/String;)V", false)); if (flag) list.add(new InsnNode(RETURN)); clinit.instructions.insert(list); }
@Override public byte[] transform(String name, String transformedName, byte[] basicClass) { ClassReader reader = new ClassReader(basicClass); ClassNode node = new ClassNode(ASM5); reader.accept(node, 0); node.methods.removeIf(m -> !m.name.equals("<init>")); node.methods.stream() .map(m -> m.instructions) .peek(InsnList::clear) .peek(l -> l.add(new VarInsnNode(ALOAD, 0))) .peek(l -> l.add(new MethodInsnNode(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false))) .forEach(l -> l.add(new InsnNode(RETURN))); node.interfaces.clear(); node.superName = "java/lang/Object"; node.innerClasses.clear(); ClassWriter writer = ASMHelper.newClassWriter(0); node.accept(writer); return writer.toByteArray(); }
@Nullable private static MethodInsnNode findConstructorInvocation( @NonNull MethodNode method, @NonNull String className) { InsnList nodes = method.instructions; for (int i = 0, n = nodes.size(); i < n; i++) { AbstractInsnNode instruction = nodes.get(i); if (instruction.getOpcode() == Opcodes.INVOKESPECIAL) { MethodInsnNode call = (MethodInsnNode) instruction; if (className.equals(call.owner)) { return call; } } } return null; }
private static MethodNode findEnumSwitchUsage(ClassNode classNode, String owner) { String target = ENUM_SWITCH_PREFIX + owner.replace('/', '$'); @SuppressWarnings("rawtypes") // ASM API List methodList = classNode.methods; for (Object f : methodList) { MethodNode method = (MethodNode) f; InsnList nodes = method.instructions; for (int i = 0, n = nodes.size(); i < n; i++) { AbstractInsnNode instruction = nodes.get(i); if (instruction.getOpcode() == Opcodes.GETSTATIC) { FieldInsnNode field = (FieldInsnNode) instruction; if (field.name.equals(target)) { return method; } } } } return null; }
private static boolean containsSimpleSdkCheck(@NonNull MethodNode method) { // Look for a compiled version of "if (Build.VERSION.SDK_INT op N) {" InsnList nodes = method.instructions; for (int i = 0, n = nodes.size(); i < n; i++) { AbstractInsnNode instruction = nodes.get(i); if (isSdkVersionLookup(instruction)) { AbstractInsnNode bipush = getNextInstruction(instruction); if (bipush != null && bipush.getOpcode() == Opcodes.BIPUSH) { AbstractInsnNode ifNode = getNextInstruction(bipush); if (ifNode != null && ifNode.getType() == AbstractInsnNode.JUMP_INSN) { return true; } } } } return false; }
@SuppressWarnings("unchecked") // ASM API @Nullable private static AbstractInsnNode findMethodCallInstruction( @NonNull InsnList instructions, @NonNull String owner, @NonNull String name, @NonNull String desc) { ListIterator<AbstractInsnNode> iterator = instructions.iterator(); while (iterator.hasNext()) { AbstractInsnNode insnNode = iterator.next(); if (insnNode.getType() == AbstractInsnNode.METHOD_INSN) { MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; if ((methodInsnNode.owner.equals(owner)) && (methodInsnNode.name.equals(name)) && (methodInsnNode.desc.equals(desc))) { return methodInsnNode; } } } return null; }
/** * Generates instructions to pop the result of the method off the stack. This will only generate instructions if the method being * invoked generates a return value. * @param invokeInsnNode instruction for the method that was invoked (can either be of type {@link MethodInsnNode} or * {@link InvokeDynamicInsnNode} -- this is used to determine how many items to pop off the stack * @return instructions for a pop (only if the method being invoked generates a return value) * @throws IllegalArgumentException if {@code invokeInsnNode} isn't of type {@link MethodInsnNode} or {@link InvokeDynamicInsnNode} * @throws NullPointerException if any argument is {@code null} */ private static InsnList popMethodResult(AbstractInsnNode invokeInsnNode) { Validate.notNull(invokeInsnNode); Type returnType = getReturnTypeOfInvocation(invokeInsnNode); InsnList ret = new InsnList(); switch (returnType.getSort()) { case Type.LONG: case Type.DOUBLE: ret.add(new InsnNode(Opcodes.POP2)); break; case Type.VOID: break; case Type.METHOD: throw new IllegalStateException(); // this should never happen default: ret.add(new InsnNode(Opcodes.POP)); break; } return ret; }
/** * Generates instructions for generating marker instructions. These marker instructions are meant to be is useful for debugging * instrumented code. For example, you can spot a specific portion of instrumented code by looking for specific markers in the assembly * output. * @param markerType marker type (determines what kind of instructions are generated) * @param text text to print out * @return instructions to call System.out.println with a string constant * @throws NullPointerException if any argument is {@code null} */ public static InsnList debugMarker(MarkerType markerType, String text) { Validate.notNull(markerType); Validate.notNull(text); InsnList ret = new InsnList(); switch (markerType) { case NONE: break; case CONSTANT: ret.add(new LdcInsnNode(text)); ret.add(new InsnNode(Opcodes.POP)); break; case STDOUT: ret.add(new FieldInsnNode(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;")); ret.add(new LdcInsnNode(text)); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false)); break; default: throw new IllegalStateException(); } return ret; }