Search in sources :

Example 1 with MethodNode

use of org.objectweb.asm.tree.MethodNode in project enumerable by hraberg.

the class LambdaExpressionTrees method findMethodNode.

@SuppressWarnings("unchecked")
static MethodNode findMethodNode(Method method) throws IOException {
    String className = method.getDeclaringClass().getName();
    ClassReader cr;
    if (InMemoryCompiler.bytesByClassName.containsKey(className))
        cr = new ClassReader(InMemoryCompiler.bytesByClassName.get(className));
    else
        cr = new ClassReader(className);
    ClassNode cn = new ClassNode();
    cr.accept(cn, 0);
    String descriptor = getMethodDescriptor(method);
    for (MethodNode mn : (List<MethodNode>) cn.methods) {
        if (method.getName().equals(mn.name) && descriptor.equals(mn.desc))
            return mn;
    }
    throw new IllegalStateException("Cannot find method which does exist");
}
Also used : ClassNode(org.objectweb.asm.tree.ClassNode) MethodNode(org.objectweb.asm.tree.MethodNode) ClassReader(org.objectweb.asm.ClassReader) List(java.util.List)

Example 2 with MethodNode

use of org.objectweb.asm.tree.MethodNode in project MinecraftForge by MinecraftForge.

the class EventSubscriptionTransformer method buildEvents.

private boolean buildEvents(ClassNode classNode) throws Exception {
    // Yes, this recursively loads classes until we get this base class. THIS IS NOT A ISSUE. Coremods should handle re-entry just fine.
    // If they do not this a COREMOD issue NOT a Forge/LaunchWrapper issue.
    Class<?> parent = this.getClass().getClassLoader().loadClass(classNode.superName.replace('/', '.'));
    if (!Event.class.isAssignableFrom(parent)) {
        return false;
    }
    //Class<?> listenerListClazz = Class.forName("net.minecraftforge.fml.common.eventhandler.ListenerList", false, getClass().getClassLoader());
    Type tList = Type.getType("Lnet/minecraftforge/fml/common/eventhandler/ListenerList;");
    boolean edited = false;
    boolean hasSetup = false;
    boolean hasGetListenerList = false;
    boolean hasDefaultCtr = false;
    boolean hasCancelable = false;
    boolean hasResult = false;
    String voidDesc = Type.getMethodDescriptor(VOID_TYPE);
    String boolDesc = Type.getMethodDescriptor(BOOLEAN_TYPE);
    String listDesc = tList.getDescriptor();
    String listDescM = Type.getMethodDescriptor(tList);
    for (MethodNode method : classNode.methods) {
        if (method.name.equals("setup") && method.desc.equals(voidDesc) && (method.access & ACC_PROTECTED) == ACC_PROTECTED)
            hasSetup = true;
        if ((method.access & ACC_PUBLIC) == ACC_PUBLIC) {
            if (method.name.equals("getListenerList") && method.desc.equals(listDescM))
                hasGetListenerList = true;
            if (method.name.equals("isCancelable") && method.desc.equals(boolDesc))
                hasCancelable = true;
            if (method.name.equals("hasResult") && method.desc.equals(boolDesc))
                hasResult = true;
        }
        if (method.name.equals("<init>") && method.desc.equals(voidDesc))
            hasDefaultCtr = true;
    }
    if (classNode.visibleAnnotations != null) {
        for (AnnotationNode node : classNode.visibleAnnotations) {
            if (!hasResult && node.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/Event$HasResult;")) {
                /* Add:
                     *      public boolean hasResult()
                     *      {
                     *            return true;
                     *      }
                     */
                MethodNode method = new MethodNode(ACC_PUBLIC, "hasResult", boolDesc, null, null);
                method.instructions.add(new InsnNode(ICONST_1));
                method.instructions.add(new InsnNode(IRETURN));
                classNode.methods.add(method);
                edited = true;
            } else if (!hasCancelable && node.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/Cancelable;")) {
                /* Add:
                     *      public boolean isCancelable()
                     *      {
                     *            return true;
                     *      }
                     */
                MethodNode method = new MethodNode(ACC_PUBLIC, "isCancelable", boolDesc, null, null);
                method.instructions.add(new InsnNode(ICONST_1));
                method.instructions.add(new InsnNode(IRETURN));
                classNode.methods.add(method);
                edited = true;
            }
        }
    }
    if (hasSetup) {
        if (!hasGetListenerList)
            throw new RuntimeException("Event class defines setup() but does not define getListenerList! " + classNode.name);
        else
            return edited;
    }
    Type tSuper = Type.getType(classNode.superName);
    //Add private static ListenerList LISTENER_LIST
    classNode.fields.add(new FieldNode(ACC_PRIVATE | ACC_STATIC, "LISTENER_LIST", listDesc, null, null));
    /*Add:
         *      public <init>()
         *      {
         *              super();
         *      }
         */
    if (!hasDefaultCtr) {
        MethodNode method = new MethodNode(ACC_PUBLIC, "<init>", voidDesc, null, null);
        method.instructions.add(new VarInsnNode(ALOAD, 0));
        method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "<init>", voidDesc, false));
        method.instructions.add(new InsnNode(RETURN));
        classNode.methods.add(method);
    }
    /*Add:
         *      protected void setup()
         *      {
         *              super.setup();
         *              if (LISTENER_LIST != NULL)
         *              {
         *                      return;
         *              }
         *              LISTENER_LIST = new ListenerList(super.getListenerList());
         *      }
         */
    MethodNode method = new MethodNode(ACC_PROTECTED, "setup", voidDesc, null, null);
    method.instructions.add(new VarInsnNode(ALOAD, 0));
    method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "setup", voidDesc, false));
    method.instructions.add(new FieldInsnNode(GETSTATIC, classNode.name, "LISTENER_LIST", listDesc));
    LabelNode initListener = new LabelNode();
    method.instructions.add(new JumpInsnNode(IFNULL, initListener));
    method.instructions.add(new InsnNode(RETURN));
    method.instructions.add(initListener);
    method.instructions.add(new FrameNode(F_SAME, 0, null, 0, null));
    method.instructions.add(new TypeInsnNode(NEW, tList.getInternalName()));
    method.instructions.add(new InsnNode(DUP));
    method.instructions.add(new VarInsnNode(ALOAD, 0));
    method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "getListenerList", listDescM, false));
    method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tList.getInternalName(), "<init>", getMethodDescriptor(VOID_TYPE, tList), false));
    method.instructions.add(new FieldInsnNode(PUTSTATIC, classNode.name, "LISTENER_LIST", listDesc));
    method.instructions.add(new InsnNode(RETURN));
    classNode.methods.add(method);
    /*Add:
         *      public ListenerList getListenerList()
         *      {
         *              return this.LISTENER_LIST;
         *      }
         */
    method = new MethodNode(ACC_PUBLIC, "getListenerList", listDescM, null, null);
    method.instructions.add(new FieldInsnNode(GETSTATIC, classNode.name, "LISTENER_LIST", listDesc));
    method.instructions.add(new InsnNode(ARETURN));
    classNode.methods.add(method);
    return true;
}
Also used : LabelNode(org.objectweb.asm.tree.LabelNode) FrameNode(org.objectweb.asm.tree.FrameNode) FieldNode(org.objectweb.asm.tree.FieldNode) FieldInsnNode(org.objectweb.asm.tree.FieldInsnNode) TypeInsnNode(org.objectweb.asm.tree.TypeInsnNode) FieldInsnNode(org.objectweb.asm.tree.FieldInsnNode) MethodInsnNode(org.objectweb.asm.tree.MethodInsnNode) TypeInsnNode(org.objectweb.asm.tree.TypeInsnNode) JumpInsnNode(org.objectweb.asm.tree.JumpInsnNode) VarInsnNode(org.objectweb.asm.tree.VarInsnNode) InsnNode(org.objectweb.asm.tree.InsnNode) Type(org.objectweb.asm.Type) MethodNode(org.objectweb.asm.tree.MethodNode) AnnotationNode(org.objectweb.asm.tree.AnnotationNode) MethodInsnNode(org.objectweb.asm.tree.MethodInsnNode) Event(net.minecraftforge.fml.common.eventhandler.Event) JumpInsnNode(org.objectweb.asm.tree.JumpInsnNode) VarInsnNode(org.objectweb.asm.tree.VarInsnNode)

Example 3 with MethodNode

use of org.objectweb.asm.tree.MethodNode in project MinecraftForge by MinecraftForge.

the class SideTransformer method transform.

@Override
public byte[] transform(String name, String transformedName, byte[] bytes) {
    if (bytes == null) {
        return null;
    }
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);
    if (remove(classNode.visibleAnnotations, SIDE)) {
        if (DEBUG) {
            System.out.println(String.format("Attempted to load class %s for invalid side %s", classNode.name, SIDE));
        }
        throw new RuntimeException(String.format("Attempted to load class %s for invalid side %s", classNode.name, SIDE));
    }
    Iterator<FieldNode> fields = classNode.fields.iterator();
    while (fields.hasNext()) {
        FieldNode field = fields.next();
        if (remove(field.visibleAnnotations, SIDE)) {
            if (DEBUG) {
                System.out.println(String.format("Removing Field: %s.%s", classNode.name, field.name));
            }
            fields.remove();
        }
    }
    LambdaGatherer lambdaGatherer = new LambdaGatherer();
    Iterator<MethodNode> methods = classNode.methods.iterator();
    while (methods.hasNext()) {
        MethodNode method = methods.next();
        if (remove(method.visibleAnnotations, SIDE)) {
            if (DEBUG) {
                System.out.println(String.format("Removing Method: %s.%s%s", classNode.name, method.name, method.desc));
            }
            methods.remove();
            lambdaGatherer.accept(method);
        }
    }
    // remove dynamic lambda methods that are inside of removed methods
    List<Handle> dynamicLambdaHandles = lambdaGatherer.getDynamicLambdaHandles();
    if (!dynamicLambdaHandles.isEmpty()) {
        methods = classNode.methods.iterator();
        while (methods.hasNext()) {
            MethodNode method = methods.next();
            for (Handle dynamicLambdaHandle : dynamicLambdaHandles) {
                if (method.name.equals(dynamicLambdaHandle.getName()) && method.desc.equals(dynamicLambdaHandle.getDesc())) {
                    if (DEBUG) {
                        System.out.println(String.format("Removing Method: %s.%s%s", classNode.name, method.name, method.desc));
                    }
                    methods.remove();
                }
            }
        }
    }
    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(writer);
    return writer.toByteArray();
}
Also used : ClassNode(org.objectweb.asm.tree.ClassNode) FieldNode(org.objectweb.asm.tree.FieldNode) MethodNode(org.objectweb.asm.tree.MethodNode) ClassReader(org.objectweb.asm.ClassReader) ClassWriter(org.objectweb.asm.ClassWriter) Handle(org.objectweb.asm.Handle)

Example 4 with MethodNode

use of org.objectweb.asm.tree.MethodNode in project LogisticsPipes by RS485.

the class LogisticsClassTransformer method handleWorldClass.

private byte[] handleWorldClass(byte[] bytes) {
    final ClassReader reader = new ClassReader(bytes);
    final ClassNode node = new ClassNode();
    reader.accept(node, 0);
    for (MethodNode m : node.methods) {
        if (m.name.equals("notifyBlocksOfNeighborChange") || m.name.equals("func_147459_d") || (m.name.equals("d") && m.desc.equals("(IIILaji;)V"))) {
            MethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {

                @Override
                public void visitCode() {
                    super.visitCode();
                    Label l0 = new Label();
                    visitLabel(l0);
                    visitVarInsn(Opcodes.ALOAD, 0);
                    visitVarInsn(Opcodes.ILOAD, 1);
                    visitVarInsn(Opcodes.ILOAD, 2);
                    visitVarInsn(Opcodes.ILOAD, 3);
                    this.visitMethodInsn(Opcodes.INVOKESTATIC, "logisticspipes/asm/LogisticsASMHookClass", "notifyBlocksOfNeighborChange_Start", "(Lnet/minecraft/world/World;III)V");
                }

                @Override
                public void visitInsn(int opcode) {
                    if (opcode == Opcodes.RETURN) {
                        visitVarInsn(Opcodes.ALOAD, 0);
                        visitVarInsn(Opcodes.ILOAD, 1);
                        visitVarInsn(Opcodes.ILOAD, 2);
                        visitVarInsn(Opcodes.ILOAD, 3);
                        this.visitMethodInsn(Opcodes.INVOKESTATIC, "logisticspipes/asm/LogisticsASMHookClass", "notifyBlocksOfNeighborChange_Stop", "(Lnet/minecraft/world/World;III)V");
                        Label l0 = new Label();
                        visitLabel(l0);
                    }
                    super.visitInsn(opcode);
                }
            };
            m.accept(mv);
            node.methods.set(node.methods.indexOf(m), mv);
        }
        if (m.name.equals("notifyBlockOfNeighborChange") || m.name.equals("func_147460_e") || (m.name.equals("e") && m.desc.equals("(IIILaji;)V"))) {
            MethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {

                boolean done = false;

                @Override
                public void visitLabel(Label label) {
                    if (!done) {
                        done = true;
                        Label l0 = new Label();
                        visitLabel(l0);
                        visitVarInsn(Opcodes.ALOAD, 0);
                        visitVarInsn(Opcodes.ILOAD, 1);
                        visitVarInsn(Opcodes.ILOAD, 2);
                        visitVarInsn(Opcodes.ILOAD, 3);
                        this.visitMethodInsn(Opcodes.INVOKESTATIC, "logisticspipes/asm/LogisticsASMHookClass", "notifyBlockOfNeighborChange", "(Lnet/minecraft/world/World;III)V");
                    }
                    super.visitLabel(label);
                }
            };
            m.accept(mv);
            node.methods.set(node.methods.indexOf(m), mv);
        }
    }
    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    node.accept(writer);
    return writer.toByteArray();
}
Also used : ClassNode(org.objectweb.asm.tree.ClassNode) MethodNode(org.objectweb.asm.tree.MethodNode)

Example 5 with MethodNode

use of org.objectweb.asm.tree.MethodNode in project Minechem by iopleke.

the class MinechemTransformer method injectBytes.

private byte[] injectBytes(Method method, InstructionNode instructionNode, byte[] data) {
    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(data);
    classReader.accept(classNode, ClassReader.EXPAND_FRAMES);
    MethodNode methodNode = getMethodByName(classNode, method);
    AbstractInsnNode pos = findInstructionNode(instructionNode, methodNode);
    if (instructionNode.replace) {
        methodNode.instructions.insertBefore(pos, instructionNode.getInsnList());
        methodNode.instructions.remove(pos);
    } else {
        methodNode.instructions.insertBefore(pos, instructionNode.getInsnList());
    }
    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    classNode.accept(writer);
    return writer.toByteArray();
}
Also used : ClassNode(org.objectweb.asm.tree.ClassNode) MethodNode(org.objectweb.asm.tree.MethodNode) ClassReader(org.objectweb.asm.ClassReader) AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode) ClassWriter(org.objectweb.asm.ClassWriter)

Aggregations

MethodNode (org.objectweb.asm.tree.MethodNode)322 ClassNode (org.objectweb.asm.tree.ClassNode)123 Test (org.junit.Test)94 AbstractInsnNode (org.objectweb.asm.tree.AbstractInsnNode)59 ClassReader (org.objectweb.asm.ClassReader)57 InsnList (org.objectweb.asm.tree.InsnList)49 MethodInsnNode (org.objectweb.asm.tree.MethodInsnNode)47 Label (org.objectweb.asm.Label)44 VarInsnNode (org.objectweb.asm.tree.VarInsnNode)41 InsnNode (org.objectweb.asm.tree.InsnNode)34 ClassWriter (org.objectweb.asm.ClassWriter)26 FieldNode (org.objectweb.asm.tree.FieldNode)26 JumpInsnNode (org.objectweb.asm.tree.JumpInsnNode)26 ArrayList (java.util.ArrayList)24 FieldInsnNode (org.objectweb.asm.tree.FieldInsnNode)24 LdcInsnNode (org.objectweb.asm.tree.LdcInsnNode)21 LabelNode (org.objectweb.asm.tree.LabelNode)19 TypeInsnNode (org.objectweb.asm.tree.TypeInsnNode)19 List (java.util.List)17 Type (org.objectweb.asm.Type)17